diff --git a/lang/de.json b/lang/de.json index 99b413c2..83fd95fc 100644 --- a/lang/de.json +++ b/lang/de.json @@ -2717,9 +2717,11 @@ "Generate a new key and authorize it on the server automatically (recommended)": "Einen neuen Schlüssel generieren und automatisch auf dem Server autorisieren (empfohlen)", "Generate a new key, show me the line to paste manually": "Erzeugen Sie einen neuen Schlüssel und zeigen Sie mir die Zeile, die manuell eingefügt werden soll", "Generate a new keyfile": "Erzeugen Sie eine neue Schlüsseldatei", + "Generated Miniflux administrator": "Generiertes Miniflux-Administratorkonto", "Generated Paperless administrator": "Generierter papierloser Administrator", "Generated Tandoor administrator": "Tandoor-Administrator generiert", "Generated administrator login": "Generierte Administrator-Login", + "Generated linkding administrator": "Generiertes linkding-Administratorkonto", "Generated: {generated}; failed: {failed}; family: {provider}": "Erstellt: {generated}; fehlgeschlagen: {failed}; Familie: {provider}", "Generating OVF descriptor...": "OVF-Deskriptor wird generiert...", "Generating dkms.conf...": "dkms.conf wird generiert...", @@ -3151,9 +3153,11 @@ "Indexers and quality profiles still need to be configured.": "Indexer und Qualitätsprofile müssen noch konfiguriert werden.", "Inherited retention:": "Geerbte Aufbewahrung:", "Inherited schedule:": "Geerbter Zeitplan:", + "Initial Mealie account": "Erstes Mealie-Konto", "Initial Nextcloud administrator": "Erster Nextcloud-Administrator", "Initial Nextcloud settings applied": "Erste Nextcloud-Einstellungen", "Initial Paperless-ngx administrator": "Erster Paperless-ngx-Administrator", + "Initial Stirling-PDF account": "Erstes Stirling-PDF-Konto", "Initial Tandoor administrator": "Initial Tandoor Administrator", "Initial administrator created:": "Erster Administrator erstellt:", "Initial administrator user": "Erster Administrator", @@ -3857,6 +3861,8 @@ "Migrated": "Migriert", "Migrated legacy ProxMenux NVIDIA blacklist state — module will reload after reboot": "Migrierter Legacy-ProxMenux-NVIDIA-Blacklist-Status – Modul wird nach dem Neustart neu geladen", "MineOS web interface": "MineOS Web-Schnittstelle", + "Minimal self-hosted bookmark manager.": "Minimalistischer, selbst gehosteter Lesezeichenmanager.", + "Minimalist self-hosted RSS reader.": "Minimalistischer, selbst gehosteter RSS-Reader.", "Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards.": "Minisatip ist eine Multi-Threaded-Satip-Server-Version 1.2, die unter Linux läuft und mit DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC und ISDB-T-Karten getestet wurde.", "Mirror URL not available for this script.": "Die Spiegel-URL ist für dieses Skript nicht verfügbar.", "Miscellaneous": "Verschiedenes", @@ -5925,6 +5931,8 @@ "Selected utilities installation completed": "Die Installation ausgewählter Dienstprogramme ist abgeschlossen", "Selection": "Auswahl", "Self-custodial Bitcoin Lightning wallet with integrated node and app connections.": "Bitcoin Lightning Wallet mit integrierten Knoten- und App-Verbindungen.", + "Self-hosted Git forge for code, issues and collaboration.": "Selbst gehostete Git-Plattform für Code, Fehlerverwaltung und Zusammenarbeit.", + "Self-hosted PDF tools for editing, converting and signing documents.": "Selbst gehostete PDF-Werkzeuge zum Bearbeiten, Umwandeln und Signieren von Dokumenten.", "Self-hosted ZeroTier network controller with web UI for centralized management.": "Selbst gehosteter ZeroTier-Netzwerkcontroller mit Web-Benutzeroberfläche zur zentralen Verwaltung.", "Self-hosted cloud data migration & sync manager": "Selbst gehostete Cloud Datenmigration & Sync Manager", "Self-hosted collaborative bookmark manager to collect, read, annotate, and fully preserve what matters, all in one place.": "Selbst gehosteter kollaborativer Bookmark-Manager, um alles an einem Ort zu sammeln, zu lesen, zu kommentieren und vollständig zu bewahren, was wichtig ist.", @@ -5932,8 +5940,11 @@ "Self-hosted file sharing with a modern web interface": "Self-Hosted File Sharing mit einem modernen Web-Interface", "Self-hosted file toolkit for images, video, audio, PDFs, and files": "Selbst gehostetes Datei-Toolkit für Bilder, Video, Audio, PDFs und Dateien", "Self-hosted internet archiving solution": "Selbst gehostete Internet-Archivierungslösung", + "Self-hosted inventory and home organization.": "Selbst gehostete Inventarverwaltung und Organisation des Zuhauses.", "Self-hosted recipe manager and meal planner": "Selbstgehosteter Rezeptmanager und Mahlzeitenplaner", + "Self-hosted recipe manager and meal planner.": "Selbst gehostete Rezeptverwaltung und Essensplanung.", "Self-hosted software development service": "Entwicklung von selbst gehosteter Software", + "Self-hosted task and project management.": "Selbst gehostete Aufgaben- und Projektverwaltung.", "Self-signed TLS certificate created:": "Selbstsigniertes TLS-Zertifikat erstellt:", "Selfhosted PDF manager, viewer and editor": "Selfhosted PDF Manager, Viewer und Editor", "Selkies desktop and streaming acceleration": "Selkies Desktop und Streaming Beschleunigung", diff --git a/lang/es.json b/lang/es.json index 222217b9..05a3e313 100644 --- a/lang/es.json +++ b/lang/es.json @@ -2714,9 +2714,11 @@ "Generate a new key and authorize it on the server automatically (recommended)": "Generar una nueva clave y autorizarla en el servidor automáticamente (recomendado)", "Generate a new key, show me the line to paste manually": "Genera una nueva clave, muéstrame la línea para pegar manualmente", "Generate a new keyfile": "Generar un nuevo archivo de claves", + "Generated Miniflux administrator": "Cuenta de administrador de Miniflux generada", "Generated Paperless administrator": "Administrador de Paperless generado", "Generated Tandoor administrator": "Administrador de Tandoor generado", "Generated administrator login": "Acceso de administrador generado", + "Generated linkding administrator": "Cuenta de administrador de linkding generada", "Generated: {generated}; failed: {failed}; family: {provider}": "Generadas: {generated}; fallidas: {failed}; familia: {provider}", "Generating OVF descriptor...": "Generando descriptor OVF...", "Generating dkms.conf...": "Generando dkms.conf...", @@ -3148,9 +3150,11 @@ "Indexers and quality profiles still need to be configured.": "Los índices y perfiles de calidad todavía necesitan ser configurados.", "Inherited retention:": "Retención heredada:", "Inherited schedule:": "Horario heredado:", + "Initial Mealie account": "Cuenta inicial de Mealie", "Initial Nextcloud administrator": "Administrador inicial Nextcloud", "Initial Nextcloud settings applied": "Ajustes iniciales Nextcloud aplicados", "Initial Paperless-ngx administrator": "Administrador inicial Paperless-ngx", + "Initial Stirling-PDF account": "Cuenta inicial de Stirling-PDF", "Initial Tandoor administrator": "Administrador inicial de Tandoor", "Initial administrator created:": "Administrador inicial creado:", "Initial administrator user": "Usuario administrador inicial", @@ -3853,6 +3857,8 @@ "Migrated": "Migrados", "Migrated legacy ProxMenux NVIDIA blacklist state — module will reload after reboot": "Estado de lista negra de NVIDIA ProxMenux heredado migrado: el módulo se recargará después del reinicio", "MineOS web interface": "Interfaz web de MineOS", + "Minimal self-hosted bookmark manager.": "Gestor de marcadores minimalista autoalojado.", + "Minimalist self-hosted RSS reader.": "Lector RSS minimalista autoalojado.", "Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards.": "Minisatip es un servidor satip multihilo, versión 1.2, que funciona en Linux y se ha probado con tarjetas DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC e ISDB-T.", "Mirror URL not available for this script.": "No hay URL de mirror disponible para este script.", "Miscellaneous": "Miscellaneous", @@ -5909,6 +5915,8 @@ "Selected utilities installation completed": "Instalación de utilidades seleccionadas completada", "Selection": "Selección", "Self-custodial Bitcoin Lightning wallet with integrated node and app connections.": "Monedero Bitcoin Lightning con autocustodia, nodo integrado y conexiones con aplicaciones.", + "Self-hosted Git forge for code, issues and collaboration.": "Plataforma Git autoalojada para alojar código, gestionar incidencias y colaborar.", + "Self-hosted PDF tools for editing, converting and signing documents.": "Herramientas PDF autoalojadas para editar, convertir y firmar documentos.", "Self-hosted ZeroTier network controller with web UI for centralized management.": "Controlador de red ZeroTier autoalojado con interfaz web para la gestión centralizada.", "Self-hosted cloud data migration & sync manager": "Gestor autoalojado de migración y sincronización de datos en la nube", "Self-hosted collaborative bookmark manager to collect, read, annotate, and fully preserve what matters, all in one place.": "Gestor de marcadores colaborativo y autoalojado para recopilar, leer, anotar y conservar íntegramente lo que importa, todo en un solo lugar.", @@ -5916,8 +5924,11 @@ "Self-hosted file sharing with a modern web interface": "Compartición de archivos autoalojada con una interfaz web moderna", "Self-hosted file toolkit for images, video, audio, PDFs, and files": "Kit de herramientas autoalojado para imágenes, vídeo, audio, PDF y archivos", "Self-hosted internet archiving solution": "Solución autoalojada de archivado de Internet", + "Self-hosted inventory and home organization.": "Inventario y organización del hogar autoalojados.", "Self-hosted recipe manager and meal planner": "Gestor de recetas y planificador de comidas autoalojado", + "Self-hosted recipe manager and meal planner.": "Gestor de recetas y planificador de comidas autoalojado.", "Self-hosted software development service": "Servicio autoalojado de desarrollo de software", + "Self-hosted task and project management.": "Gestión autoalojada de tareas y proyectos.", "Self-signed TLS certificate created:": "Certificado TLS auto-firmado creado:", "Selfhosted PDF manager, viewer and editor": "Gestor, visor y editor de PDF autoalojado", "Selkies desktop and streaming acceleration": "Aceleración del escritorio y del streaming de Selkies", diff --git a/lang/fr.json b/lang/fr.json index 4012be6f..c20cca4c 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -2717,9 +2717,11 @@ "Generate a new key and authorize it on the server automatically (recommended)": "générer une nouvelle clé et l'autoriser automatiquement sur le serveur (recommandé)", "Generate a new key, show me the line to paste manually": "Générez une nouvelle clé, montrez-moi la ligne à coller manuellement", "Generate a new keyfile": "générer un nouveau fichier de clés", + "Generated Miniflux administrator": "Compte administrateur Miniflux généré", "Generated Paperless administrator": "Administrateur sans papier généré", "Generated Tandoor administrator": "Administrateur Tandoor généré", "Generated administrator login": "Connexion de l'administrateur généré", + "Generated linkding administrator": "Compte administrateur linkding généré", "Generated: {generated}; failed: {failed}; family: {provider}": "Générés : {generated} ; échecs : {failed} ; famille : {provider}", "Generating OVF descriptor...": "Génération du descripteur OVF...", "Generating dkms.conf...": "Génération de dkms.conf...", @@ -3151,9 +3153,11 @@ "Indexers and quality profiles still need to be configured.": "Les indexeurs et les profils de qualité doivent encore être configurés.", "Inherited retention:": "Rétention héritée :", "Inherited schedule:": "Horaire hérité :", + "Initial Mealie account": "Compte initial Mealie", "Initial Nextcloud administrator": "Administrateur initial Nextcloud", "Initial Nextcloud settings applied": "Paramètres Nextcloud initiaux appliqués", "Initial Paperless-ngx administrator": "Administrateur initial Paperless-ngx", + "Initial Stirling-PDF account": "Compte initial Stirling-PDF", "Initial Tandoor administrator": "Administrateur Tandoor initial", "Initial administrator created:": "Administrateur initial créé :", "Initial administrator user": "Administrateur initial", @@ -3857,6 +3861,8 @@ "Migrated": "Migré", "Migrated legacy ProxMenux NVIDIA blacklist state — module will reload after reboot": "État de la liste noire ProxMenux NVIDIA héritée migrée : le module se rechargera après le redémarrage", "MineOS web interface": "Interface web MineOS", + "Minimal self-hosted bookmark manager.": "Gestionnaire de marque-pages minimaliste auto-hébergé.", + "Minimalist self-hosted RSS reader.": "Lecteur RSS minimaliste auto-hébergé.", "Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards.": "Minisatip est une version de serveur satip multi-threaded 1.2 qui fonctionne sous Linux et qui a été testée avec des cartes DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC et ISDB-T.", "Mirror URL not available for this script.": "URL miroir non disponible pour ce script.", "Miscellaneous": "Divers", @@ -5925,6 +5931,8 @@ "Selected utilities installation completed": "Installation des utilitaires sélectionnés terminée", "Selection": "Sélection", "Self-custodial Bitcoin Lightning wallet with integrated node and app connections.": "Auto-custodial Bitcoin Lightning portefeuille avec nœud intégré et connexions app.", + "Self-hosted Git forge for code, issues and collaboration.": "Forge Git auto-hébergée pour le code, le suivi des problèmes et la collaboration.", + "Self-hosted PDF tools for editing, converting and signing documents.": "Outils PDF auto-hébergés pour modifier, convertir et signer des documents.", "Self-hosted ZeroTier network controller with web UI for centralized management.": "Contrôleur réseau ZeroTier auto-organisé avec interface utilisateur web pour une gestion centralisée.", "Self-hosted cloud data migration & sync manager": "Gestion de migration et de synchronisation de données en nuage auto-organisé", "Self-hosted collaborative bookmark manager to collect, read, annotate, and fully preserve what matters, all in one place.": "Gestionnaire de signets collaboratifs auto-organisés pour recueillir, lire, annoter et préserver pleinement ce qui compte, le tout en un seul endroit.", @@ -5932,8 +5940,11 @@ "Self-hosted file sharing with a modern web interface": "Partage de fichiers auto-organisé avec une interface web moderne", "Self-hosted file toolkit for images, video, audio, PDFs, and files": "Boîte à outils de fichiers auto-organisé pour les images, vidéo, audio, PDF et fichiers", "Self-hosted internet archiving solution": "Solution d'archivage internet auto-organisé", + "Self-hosted inventory and home organization.": "Gestion des stocks et organisation de la maison auto-hébergées.", "Self-hosted recipe manager and meal planner": "Gestionnaire de recettes et planificateur de repas", + "Self-hosted recipe manager and meal planner.": "Gestionnaire de recettes et planificateur de repas auto-hébergé.", "Self-hosted software development service": "Service de développement de logiciels autonomes", + "Self-hosted task and project management.": "Gestion des tâches et des projets auto-hébergée.", "Self-signed TLS certificate created:": "Certificat TLS autosigné créé :", "Selfhosted PDF manager, viewer and editor": "Gestionnaire, visionneur et éditeur de PDF auto-organisé", "Selkies desktop and streaming acceleration": "Selkies bureau et l'accélération de streaming", diff --git a/lang/it.json b/lang/it.json index 2eb78b83..f90af3c1 100644 --- a/lang/it.json +++ b/lang/it.json @@ -2717,9 +2717,11 @@ "Generate a new key and authorize it on the server automatically (recommended)": "Genera una nuova chiave e autorizzala automaticamente sul server (consigliato)", "Generate a new key, show me the line to paste manually": "Genera una nuova chiave, mostrami la riga da incollare manualmente", "Generate a new keyfile": "Genera un nuovo file di chiavi", + "Generated Miniflux administrator": "Account amministratore di Miniflux generato", "Generated Paperless administrator": "Amministratore Paperless generato", "Generated Tandoor administrator": "Amministratore Tandoor generato", "Generated administrator login": "Credenziali di accesso amministratore generate", + "Generated linkding administrator": "Account amministratore di linkding generato", "Generated: {generated}; failed: {failed}; family: {provider}": "Generati: {generated}; non riusciti: {failed}; famiglia: {provider}", "Generating OVF descriptor...": "Generazione descrittore OVF...", "Generating dkms.conf...": "Generazione dkms.conf...", @@ -3151,9 +3153,11 @@ "Indexers and quality profiles still need to be configured.": "Gli indicizzatori e i profili di qualità devono ancora essere configurati.", "Inherited retention:": "Conservazione ereditata:", "Inherited schedule:": "Pianificazione ereditata:", + "Initial Mealie account": "Account iniziale di Mealie", "Initial Nextcloud administrator": "Amministratore iniziale Nextcloud", "Initial Nextcloud settings applied": "Impostazioni iniziali Nextcloud applicate", "Initial Paperless-ngx administrator": "Amministratore iniziale Paperless-ngx", + "Initial Stirling-PDF account": "Account iniziale di Stirling-PDF", "Initial Tandoor administrator": "Amministratore iniziale Tandoor", "Initial administrator created:": "Amministratore iniziale creato:", "Initial administrator user": "Utente amministratore iniziale", @@ -3857,6 +3861,8 @@ "Migrated": "Migrato", "Migrated legacy ProxMenux NVIDIA blacklist state — module will reload after reboot": "Stato della lista nera NVIDIA ProxMenux legacy migrato: il modulo verrà ricaricato dopo il riavvio", "MineOS web interface": "Interfaccia web MineOS", + "Minimal self-hosted bookmark manager.": "Gestore minimale di segnalibri, ospitato sul proprio server.", + "Minimalist self-hosted RSS reader.": "Lettore RSS minimale, ospitato sul proprio server.", "Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards.": "Minisatip è un server SAT>IP multithread versione 1.2 per Linux, testato con schede DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC e ISDB-T.", "Mirror URL not available for this script.": "URL mirror non disponibile per questo script.", "Miscellaneous": "Varie", @@ -5925,6 +5931,8 @@ "Selected utilities installation completed": "Installazione utilità selezionate completata", "Selection": "Selezione", "Self-custodial Bitcoin Lightning wallet with integrated node and app connections.": "Wallet Bitcoin Lightning con custodia autonoma, nodo integrato e connessioni alle app.", + "Self-hosted Git forge for code, issues and collaboration.": "Piattaforma Git sul proprio server per codice, segnalazioni e collaborazione.", + "Self-hosted PDF tools for editing, converting and signing documents.": "Strumenti PDF sul proprio server per modificare, convertire e firmare documenti.", "Self-hosted ZeroTier network controller with web UI for centralized management.": "Controller di rete ZeroTier self-hosted con interfaccia web per la gestione centralizzata.", "Self-hosted cloud data migration & sync manager": "Gestore self-hosted per migrare e sincronizzare dati cloud", "Self-hosted collaborative bookmark manager to collect, read, annotate, and fully preserve what matters, all in one place.": "Gestore collaborativo di segnalibri self-hosted per raccogliere, leggere, annotare e conservare integralmente ciò che conta, tutto in un unico posto.", @@ -5932,8 +5940,11 @@ "Self-hosted file sharing with a modern web interface": "Condivisione file self-hosted con interfaccia web moderna", "Self-hosted file toolkit for images, video, audio, PDFs, and files": "Set di strumenti self-hosted per immagini, video, audio, PDF e altri file", "Self-hosted internet archiving solution": "Soluzione self-hosted per archiviare contenuti Internet", + "Self-hosted inventory and home organization.": "Inventario e organizzazione della casa sul proprio server.", "Self-hosted recipe manager and meal planner": "Gestore di ricette e pianificatore dei pasti self-hosted", + "Self-hosted recipe manager and meal planner.": "Gestore di ricette e pianificatore dei pasti sul proprio server.", "Self-hosted software development service": "Servizio di sviluppo software ospitabile sul proprio server", + "Self-hosted task and project management.": "Gestione di attività e progetti sul proprio server.", "Self-signed TLS certificate created:": "Certificato TLS autofirmato creato:", "Selfhosted PDF manager, viewer and editor": "Gestore, visualizzatore ed editor PDF self-hosted", "Selkies desktop and streaming acceleration": "Accelerazione desktop e streaming con Selkies", diff --git a/lang/pt.json b/lang/pt.json index 29191f7e..873bd39a 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -2717,9 +2717,11 @@ "Generate a new key and authorize it on the server automatically (recommended)": "Gere uma nova chave e autorize-a automaticamente no servidor (recomendado)", "Generate a new key, show me the line to paste manually": "Gere uma nova chave, mostre-me a linha para colar manualmente", "Generate a new keyfile": "Gere um novo arquivo-chave", + "Generated Miniflux administrator": "Conta de administrador do Miniflux gerada", "Generated Paperless administrator": "Administrador Gerado sem Papel", "Generated Tandoor administrator": "Gerado o administrador Tandoor", "Generated administrator login": "Gerou o login do administrador", + "Generated linkding administrator": "Conta de administrador do linkding gerada", "Generated: {generated}; failed: {failed}; family: {provider}": "Gerados: {generated}; com falha: {failed}; família: {provider}", "Generating OVF descriptor...": "Gerando descritor OVF...", "Generating dkms.conf...": "Gerando dkms.conf...", @@ -3151,9 +3153,11 @@ "Indexers and quality profiles still need to be configured.": "Os indexadores e os perfis de qualidade ainda precisam ser configurados.", "Inherited retention:": "retenção herdada:", "Inherited schedule:": "Cronograma herdado:", + "Initial Mealie account": "Conta inicial do Mealie", "Initial Nextcloud administrator": "Administrador inicial do Nextcloud", "Initial Nextcloud settings applied": "Configurações iniciais do Nextcloud aplicadas", "Initial Paperless-ngx administrator": "Administrador inicial do Paperless-ngx", + "Initial Stirling-PDF account": "Conta inicial do Stirling-PDF", "Initial Tandoor administrator": "Administrador inicial Tandoor", "Initial administrator created:": "Administrador inicial criado:", "Initial administrator user": "Utilizador de administrador inicial", @@ -3857,6 +3861,8 @@ "Migrated": "Migrado", "Migrated legacy ProxMenux NVIDIA blacklist state — module will reload after reboot": "Estado de lista negra legado ProxMenux NVIDIA migrado – o módulo será recarregado após a reinicialização", "MineOS web interface": "Interface Web MineOS", + "Minimal self-hosted bookmark manager.": "Gestor de marcadores minimalista autoalojado.", + "Minimalist self-hosted RSS reader.": "Leitor RSS minimalista autoalojado.", "Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards.": "Minisatip é um servidor de satip multi-threaded versão 1.2 que é executado sob Linux e foi testado com placas DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC e ISDB-T.", "Mirror URL not available for this script.": "URL espelhado não disponível para este script.", "Miscellaneous": "Diversos", @@ -5925,6 +5931,8 @@ "Selected utilities installation completed": "Instalação de utilitários selecionados concluída", "Selection": "Selecção", "Self-custodial Bitcoin Lightning wallet with integrated node and app connections.": "Carteira Bitcoin Lightning com nó integrado e conexões de aplicativo.", + "Self-hosted Git forge for code, issues and collaboration.": "Plataforma Git autoalojada para código, gestão de problemas e colaboração.", + "Self-hosted PDF tools for editing, converting and signing documents.": "Ferramentas PDF autoalojadas para editar, converter e assinar documentos.", "Self-hosted ZeroTier network controller with web UI for centralized management.": "Controlador de rede ZeroTier self-hosted com interface web para gerenciamento centralizado.", "Self-hosted cloud data migration & sync manager": "Gerenciador de migração e sincronização de dados em nuvem hospedada automaticamente", "Self-hosted collaborative bookmark manager to collect, read, annotate, and fully preserve what matters, all in one place.": "Gerenciador de favoritos colaborativo para coletar, ler, anotar e preservar totalmente o que importa, tudo em um só lugar.", @@ -5932,8 +5940,11 @@ "Self-hosted file sharing with a modern web interface": "Partilha de ficheiros auto- hospedados com uma interface Web moderna", "Self-hosted file toolkit for images, video, audio, PDFs, and files": "Kit de ferramentas de arquivo auto hospedado para imagens, vídeo, áudio, PDFs e arquivos", "Self-hosted internet archiving solution": "Solução de arquivamento de internet self-hosted", + "Self-hosted inventory and home organization.": "Inventário e organização da casa autoalojados.", "Self-hosted recipe manager and meal planner": "Gestor de receitas e organizador de refeições", + "Self-hosted recipe manager and meal planner.": "Gestor de receitas e planeador de refeições autoalojado.", "Self-hosted software development service": "Serviço de desenvolvimento de software self-hosted", + "Self-hosted task and project management.": "Gestão de tarefas e projetos autoalojada.", "Self-signed TLS certificate created:": "Certificado TLS auto- assinado criado:", "Selfhosted PDF manager, viewer and editor": "Gerenciador de PDF, visualizador e editor selfhosted", "Selkies desktop and streaming acceleration": "Aceleração da área de trabalho e da transmissão", diff --git a/lang/sk.json b/lang/sk.json index 6e8ac21a..5e927508 100644 --- a/lang/sk.json +++ b/lang/sk.json @@ -2717,9 +2717,11 @@ "Generate a new key and authorize it on the server automatically (recommended)": "Vygenerovať nový kľúč a automaticky ho autorizovať na serveri (odporúčané)", "Generate a new key, show me the line to paste manually": "Vygenerovať nový kľúč a zobraziť riadok na ručné vloženie", "Generate a new keyfile": "Vygenerovať nový keyfile", + "Generated Miniflux administrator": "Vygenerovaný účet správcu Miniflux", "Generated Paperless administrator": "Vygenerovaný účet správcu Paperless", "Generated Tandoor administrator": "Vygenerovaný účet správcu Tandoor", "Generated administrator login": "Prihlásenie generovaného správcu", + "Generated linkding administrator": "Vygenerovaný účet správcu linkding", "Generated: {generated}; failed: {failed}; family: {provider}": "Vygenerované: {generated}; neúspešné: {failed}; rodina: {provider}", "Generating OVF descriptor...": "Vytváram OVF popisovač...", "Generating dkms.conf...": "Vytváram dkms.conf...", @@ -3151,9 +3153,11 @@ "Indexers and quality profiles still need to be configured.": "Indexery a profily kvality ešte treba nastaviť.", "Inherited retention:": "Prevzaté uchovávanie:", "Inherited schedule:": "Prevzatý plán:", + "Initial Mealie account": "Počiatočný účet Mealie", "Initial Nextcloud administrator": "Počiatočný správca Nextcloud", "Initial Nextcloud settings applied": "Použité počiatočné nastavenia Nextcloud", "Initial Paperless-ngx administrator": "Počiatočný správca Paperless-ngx", + "Initial Stirling-PDF account": "Počiatočný účet Stirling-PDF", "Initial Tandoor administrator": "Počiatočný správca Tandoor", "Initial administrator created:": "Pôvodný správca vytvorený:", "Initial administrator user": "Počiatočné používateľské meno správcu", @@ -3857,6 +3861,8 @@ "Migrated": "Migrované", "Migrated legacy ProxMenux NVIDIA blacklist state — module will reload after reboot": "Starý stav ProxMenux NVIDIA blacklistu bol migrovaný - modul sa znovu načíta po reštarte", "MineOS web interface": "Webové rozhranie MineOS", + "Minimal self-hosted bookmark manager.": "Minimalistický správca záložiek na vlastnom serveri.", + "Minimalist self-hosted RSS reader.": "Minimalistická RSS čítačka na vlastnom serveri.", "Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards.": "Minisatip je viacvláknový server SAT>IP verzie 1.2 pre Linux. Bol testovaný s kartami DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC a ISDB-T.", "Mirror URL not available for this script.": "Záložná adresa pre tento skript nie je dostupná.", "Miscellaneous": "Rôzne", @@ -5927,6 +5933,8 @@ "Selected utilities installation completed": "Inštalácia vybraných nástrojov je dokončená", "Selection": "Výber", "Self-custodial Bitcoin Lightning wallet with integrated node and app connections.": "Peňaženka Bitcoin Lightning s vlastnou správou prostriedkov, integrovaným uzlom a pripojením aplikácií.", + "Self-hosted Git forge for code, issues and collaboration.": "Gitová platforma na vlastnom serveri na správu kódu, hlásení problémov a spoluprácu.", + "Self-hosted PDF tools for editing, converting and signing documents.": "PDF nástroje na vlastnom serveri na úpravu, konverziu a podpisovanie dokumentov.", "Self-hosted ZeroTier network controller with web UI for centralized management.": "Sieťový kontrolér ZeroTier na vlastnom serveri s webovým rozhraním na centrálnu správu.", "Self-hosted cloud data migration & sync manager": "Správca migrácie a synchronizácie cloudových údajov na vlastnom serveri", "Self-hosted collaborative bookmark manager to collect, read, annotate, and fully preserve what matters, all in one place.": "Spoločný správca záložiek na vlastnom serveri na zhromažďovanie, čítanie, komentovanie a úplné uchovávanie dôležitého obsahu na jednom mieste.", @@ -5934,8 +5942,11 @@ "Self-hosted file sharing with a modern web interface": "Zdieľanie súborov na vlastnom serveri s moderným webovým rozhraním", "Self-hosted file toolkit for images, video, audio, PDFs, and files": "Súprava nástrojov na vlastnom serveri na prácu s obrázkami, videom, zvukom, PDF a ďalšími súbormi", "Self-hosted internet archiving solution": "Riešenie na archiváciu internetového obsahu na vlastnom serveri", + "Self-hosted inventory and home organization.": "Inventár a organizácia domácnosti na vlastnom serveri.", "Self-hosted recipe manager and meal planner": "Správca receptov a plánovač jedál na vlastnom serveri", + "Self-hosted recipe manager and meal planner.": "Správca receptov a plánovač jedál na vlastnom serveri.", "Self-hosted software development service": "Služba na vývoj softvéru s vlastným hostovaním", + "Self-hosted task and project management.": "Správa úloh a projektov na vlastnom serveri.", "Self-signed TLS certificate created:": "Vytvorený samopodpísaný certifikát TLS:", "Selfhosted PDF manager, viewer and editor": "Správca, prehliadač a editor PDF na vlastnom serveri", "Selkies desktop and streaming acceleration": "Zrýchlenie pracovnej plochy a streamovania Selkies", diff --git a/lang/sv.json b/lang/sv.json index 53adb648..64cdd063 100644 --- a/lang/sv.json +++ b/lang/sv.json @@ -2717,9 +2717,11 @@ "Generate a new key and authorize it on the server automatically (recommended)": "Generera en ny nyckel och auktorisera den på servern automatiskt (rekommenderas)", "Generate a new key, show me the line to paste manually": "Skapa en ny nyckel, visa mig raden för att klistra in manuellt", "Generate a new keyfile": "Skapa en ny nyckelfil", + "Generated Miniflux administrator": "Genererat administratörskonto för Miniflux", "Generated Paperless administrator": "Genererad papperslös administratör", "Generated Tandoor administrator": "Genererad Tandoor administratör", "Generated administrator login": "Genererad administratörsinloggning", + "Generated linkding administrator": "Genererat administratörskonto för linkding", "Generated: {generated}; failed: {failed}; family: {provider}": "Genererade: {generated}; misslyckade: {failed}; familj: {provider}", "Generating OVF descriptor...": "Genererar OVF-beskrivning...", "Generating dkms.conf...": "Genererar dkms.conf...", @@ -3151,9 +3153,11 @@ "Indexers and quality profiles still need to be configured.": "Indexers och kvalitetsprofiler behöver fortfarande konfigureras.", "Inherited retention:": "Ärvd retention:", "Inherited schedule:": "Ärvt schema:", + "Initial Mealie account": "Första Mealie-kontot", "Initial Nextcloud administrator": "Initial Nextcloud administratör", "Initial Nextcloud settings applied": "Initial Nextcloud inställningar tillämpas", "Initial Paperless-ngx administrator": "Initial Paperless-ngx administratör", + "Initial Stirling-PDF account": "Första Stirling-PDF-kontot", "Initial Tandoor administrator": "Initial Tandoor administratör", "Initial administrator created:": "Initial administratör skapad:", "Initial administrator user": "Initial administratör användare", @@ -3857,6 +3861,8 @@ "Migrated": "Migrerade", "Migrated legacy ProxMenux NVIDIA blacklist state — module will reload after reboot": "Migrerat äldre ProxMenux NVIDIA-svartlistatillstånd — modulen laddas om efter omstart", "MineOS web interface": "MineOS webbgränssnitt", + "Minimal self-hosted bookmark manager.": "Minimalistisk, självhostad bokmärkeshanterare.", + "Minimalist self-hosted RSS reader.": "Minimalistisk, självhostad RSS-läsare.", "Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards.": "Minisatip är en multi-threaded satip server version 1.2 som körs under Linux och det testades med DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC och ISDB-T-kort.", "Mirror URL not available for this script.": "Mirror URL inte tillgänglig för det här skriptet.", "Miscellaneous": "Övrigt", @@ -5925,6 +5931,8 @@ "Selected utilities installation completed": "Installationen av valda verktyg har slutförts", "Selection": "Urval", "Self-custodial Bitcoin Lightning wallet with integrated node and app connections.": "Självhäktande Bitcoin Lightning plånbok med integrerade nod- och appanslutningar.", + "Self-hosted Git forge for code, issues and collaboration.": "Självhostad Git-tjänst för kod, ärenden och samarbete.", + "Self-hosted PDF tools for editing, converting and signing documents.": "Självhostade PDF-verktyg för att redigera, konvertera och signera dokument.", "Self-hosted ZeroTier network controller with web UI for centralized management.": "Self-hosted ZeroTier nätverkskontroller med webb-UI för centraliserad förvaltning.", "Self-hosted cloud data migration & sync manager": "Self-hosted molndatamigrerings- och synkroniseringshanterare", "Self-hosted collaborative bookmark manager to collect, read, annotate, and fully preserve what matters, all in one place.": "Self-hosted collaborative bookmark manager för att samla, läsa, notera och helt bevara vad som är viktigt, allt på ett ställe.", @@ -5932,8 +5940,11 @@ "Self-hosted file sharing with a modern web interface": "Självhäftad fildelning med ett modernt webbgränssnitt", "Self-hosted file toolkit for images, video, audio, PDFs, and files": "Självvärd filverktyg för bilder, video, ljud, PDF-filer och filer", "Self-hosted internet archiving solution": "Självhäftad internetarkiveringslösning", + "Self-hosted inventory and home organization.": "Självhostad inventariehantering och ordning i hemmet.", "Self-hosted recipe manager and meal planner": "Självvärd receptchef och måltidsplanerare", + "Self-hosted recipe manager and meal planner.": "Självhostad receptsamling och måltidsplanering.", "Self-hosted software development service": "Självvärd programvara utvecklingstjänst", + "Self-hosted task and project management.": "Självhostad hantering av uppgifter och projekt.", "Self-signed TLS certificate created:": "Självsignerat TLS-certifikat skapat:", "Selfhosted PDF manager, viewer and editor": "Selfhosted PDF manager, tittare och redaktör", "Selkies desktop and streaming acceleration": "Selkies skrivbord och streaming acceleration", diff --git a/oci/VALIDATION.md b/oci/VALIDATION.md index 72621991..d3de1209 100644 --- a/oci/VALIDATION.md +++ b/oci/VALIDATION.md @@ -2,7 +2,7 @@ -43 of 347 applications in the OCI catalog have been tested for real: 41 in the ProxMenux lab and 2 by the community. The OCI installer shows them as verified, with a ✓ in the lists. +43 of 354 applications in the OCI catalog have been tested for real: 41 in the ProxMenux lab and 2 by the community. The OCI installer shows them as verified, with a ✓ in the lists. Each test describes the scenario that was run and names the image it ran on. It does not cover every possible configuration of the application, and a newer image has not been tested until someone reports it. diff --git a/oci/catalog/apps/forgejo.json b/oci/catalog/apps/forgejo.json new file mode 100644 index 00000000..b3f20c73 --- /dev/null +++ b/oci/catalog/apps/forgejo.json @@ -0,0 +1,462 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-forgejo", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Forgejo" + }, + "tagline": { + "en_US": "Self-hosted Git forge for code, issues and collaboration." + }, + "description": { + "en_US": "Host Git repositories and collaborate through a web interface with an integrated SSH server." + }, + "category": "ai", + "category_label": "AI / Coding & Dev-Tools", + "author": "Forgejo", + "developer": "Forgejo", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/forgejo.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 3000, + "path": "/" + }, + "website": "https://forgejo.org/", + "documentation": "https://forgejo.org/docs/v17.0/admin/installation/docker/", + "repository": "https://codeberg.org/forgejo/forgejo", + "tips": [ + "The official :17 image tag follows the latest Forgejo 17.x release; a major-version upgrade requires reading the release instructions.", + "Forgejo stores configuration, repositories and application data in /data. Create the first account through the initial web setup; SSH listens on port 22 of the LXC." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "forgejo", + "repository": "https://codeberg.org/forgejo/forgejo", + "revision": "ba0ffa712db27a668dccafc80f2474fe2fa9d62561d1f0ffbd923a12b192d971", + "image_repository_url": "https://codeberg.org/forgejo/forgejo", + "readme_pushed_at": "", + "compose_sha256": "0d2c0f5b29a0a9b5b1704e8454441cca77281282e25a4d7e2699c96a55af6a22", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://forgejo.org/docs/v17.0/admin/installation/docker/" + }, + "container_contract": { + "service_name": "forgejo", + "container_name": "forgejo", + "image": { + "reference": "codeberg.org/forgejo/forgejo:17", + "registry": "codeberg.org", + "repository": "codeberg.org/forgejo/forgejo", + "tag": "17", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "USER_UID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "USER_GID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/data", + "compose_source_example": "forgejo-data", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 16 + } + } + ], + "ports": [ + { + "container_port": 3000, + "published_example": 3000, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + }, + { + "container_port": 22, + "published_example": 222, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"forgejo\",\n \"services\": {\n \"forgejo\": {\n \"image\": \"codeberg.org/forgejo/forgejo:17\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"3000:3000\",\n \"222:22\"\n ],\n \"volumes\": [\n \"forgejo-data:/data\"\n ],\n \"environment\": {\n \"USER_UID\": \"1000\",\n \"USER_GID\": \"1000\"\n }\n }\n },\n \"volumes\": {\n \"forgejo-data\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "forgejo", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "forgejo", + "service_count": 1, + "services": [ + { + "name": "forgejo", + "image": "codeberg.org/forgejo/forgejo:17", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "codeberg.org/forgejo/forgejo:17", + "restart": "unless-stopped", + "ports": [ + "3000:3000", + "222:22" + ], + "volumes": [ + "forgejo-data:/data" + ], + "environment": { + "USER_UID": "1000", + "USER_GID": "1000" + } + } + } + ], + "top_level": { + "name": "forgejo", + "volumes": { + "forgejo-data": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "forgejo-volume-0", + "service": "forgejo", + "container_path": "/data", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "forgejo" + ], + "stop_order": [ + "forgejo" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 3000, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "The official Compose example uses the Forgejo :17 major-version tag, which tracks releases within the 17.x series.", + "native_lxc_behavior": "ProxMenux keeps the official :17 image reference and resolves that tag to an architecture-specific digest at installation.", + "reason": "Avoid crossing a Forgejo major-version boundary automatically; major upgrades need the documented manual steps.", + "behavioral_impact": "Automatic image checks follow 17.x. Moving to a later major version requires changing the image tag deliberately.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "volume_owner": { + "uid": 1000, + "gid": 1000 + }, + "volume_preparations": [ + { + "container_path": "/data", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + } + ] + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-configured-image-tag-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-configured-image-tag-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/apps/homebox.json b/oci/catalog/apps/homebox.json new file mode 100644 index 00000000..9e6f0366 --- /dev/null +++ b/oci/catalog/apps/homebox.json @@ -0,0 +1,458 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-homebox", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Homebox" + }, + "tagline": { + "en_US": "Self-hosted inventory and home organization." + }, + "description": { + "en_US": "Track household items, locations, warranties, documents and maintenance in one place." + }, + "category": "tools", + "category_label": "Tools", + "author": "Sysadmins Media", + "developer": "Sysadmins Media", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/homebox.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 7745, + "path": "/" + }, + "website": "https://homebox.software/", + "documentation": "https://github.com/sysadminsmedia/homebox#readme", + "repository": "https://github.com/sysadminsmedia/homebox", + "tips": [ + "The current Homebox Docker setup requires an API-key pepper; ProxMenux generates a unique value during installation." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "homebox", + "repository": "https://github.com/sysadminsmedia/homebox", + "revision": "1718e533b6ac0248c0756781ce0b69dd6239500ff87c3de01e5e8eee971143ed", + "image_repository_url": "https://ghcr.io/sysadminsmedia/homebox", + "readme_pushed_at": "", + "compose_sha256": "6da49efbad3d693bd5d8b327e0ac11a4b224cc53c6951107d7213edbf4bc4b02", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://github.com/sysadminsmedia/homebox#readme" + }, + "container_contract": { + "service_name": "homebox", + "container_name": "homebox", + "image": { + "reference": "ghcr.io/sysadminsmedia/homebox:latest", + "registry": "ghcr.io", + "repository": "ghcr.io/sysadminsmedia/homebox", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "TZ", + "example": "Etc/UTC", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "HBOX_AUTH_API_KEY_PEPPER", + "example": "${GENERATED_HBOX_AUTH_API_KEY_PEPPER}", + "required": true, + "sensitive": true, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/data", + "compose_source_example": "homebox-data", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 8 + } + } + ], + "ports": [ + { + "container_port": 7745, + "published_example": 3100, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"homebox\",\n \"services\": {\n \"homebox\": {\n \"image\": \"ghcr.io/sysadminsmedia/homebox:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"3100:7745\"\n ],\n \"volumes\": [\n \"homebox-data:/data\"\n ],\n \"environment\": {\n \"TZ\": \"Etc/UTC\",\n \"HBOX_AUTH_API_KEY_PEPPER\": \"${GENERATED_HBOX_AUTH_API_KEY_PEPPER}\"\n }\n }\n },\n \"volumes\": {\n \"homebox-data\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "homebox", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "homebox", + "service_count": 1, + "services": [ + { + "name": "homebox", + "image": "ghcr.io/sysadminsmedia/homebox:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "ghcr.io/sysadminsmedia/homebox:latest", + "restart": "unless-stopped", + "ports": [ + "3100:7745" + ], + "volumes": [ + "homebox-data:/data" + ], + "environment": { + "TZ": "Etc/UTC", + "HBOX_AUTH_API_KEY_PEPPER": "${GENERATED_HBOX_AUTH_API_KEY_PEPPER}" + } + } + } + ], + "top_level": { + "name": "homebox", + "volumes": { + "homebox-data": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "homebox-volume-0", + "service": "homebox", + "container_path": "/data", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "homebox" + ], + "stop_order": [ + "homebox" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [ + { + "id": "generated-hbox-auth-api-key-pepper", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "homebox", + "environment_variable": "HBOX_AUTH_API_KEY_PEPPER" + } + ] + } + ] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 7745, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 1, + "memory_mb": 512, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "generated_sensitive_environment": { + "HBOX_AUTH_API_KEY_PEPPER": { + "strategy": "token-hex", + "bytes": 48 + } + } + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/apps/linkding.json b/oci/catalog/apps/linkding.json new file mode 100644 index 00000000..53307b7e --- /dev/null +++ b/oci/catalog/apps/linkding.json @@ -0,0 +1,469 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-linkding", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "linkding" + }, + "tagline": { + "en_US": "Minimal self-hosted bookmark manager." + }, + "description": { + "en_US": "Save, tag and search bookmarks with a lightweight self-hosted web app." + }, + "category": "documents", + "category_label": "Documents & Notes", + "author": "linkding", + "developer": "linkding", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/linkding.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 9090, + "path": "/" + }, + "website": "https://linkding.link/", + "documentation": "https://github.com/sissbruecker/linkding#readme", + "repository": "https://github.com/sissbruecker/linkding", + "tips": [ + "The initial admin account is created at first start; ProxMenux generates its password and displays it after installation." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "linkding", + "repository": "https://github.com/sissbruecker/linkding", + "revision": "027502f1af892efbd166de7906e48a86b40b36a66bae1ef3396401d7f1814b12", + "image_repository_url": "https://hub.docker.com/r/sissbruecker/linkding", + "readme_pushed_at": "", + "compose_sha256": "acf453b78767f9d2e5c800bc0be41d0dc226621e064b284d94ad31335f0a940d", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://github.com/sissbruecker/linkding#readme" + }, + "container_contract": { + "service_name": "linkding", + "container_name": "linkding", + "image": { + "reference": "sissbruecker/linkding:latest", + "registry": "docker.io", + "repository": "sissbruecker/linkding", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "LD_SUPERUSER_NAME", + "example": "admin", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "LD_SUPERUSER_PASSWORD", + "example": "${GENERATED_ADMIN_PASSWORD}", + "required": true, + "sensitive": true, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/etc/linkding/data", + "compose_source_example": "linkding-data", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 4 + } + } + ], + "ports": [ + { + "container_port": 9090, + "published_example": 9090, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"linkding\",\n \"services\": {\n \"linkding\": {\n \"image\": \"sissbruecker/linkding:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"9090:9090\"\n ],\n \"volumes\": [\n \"linkding-data:/etc/linkding/data\"\n ],\n \"environment\": {\n \"LD_SUPERUSER_NAME\": \"admin\",\n \"LD_SUPERUSER_PASSWORD\": \"${GENERATED_ADMIN_PASSWORD}\"\n }\n }\n },\n \"volumes\": {\n \"linkding-data\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "linkding", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "linkding", + "service_count": 1, + "services": [ + { + "name": "linkding", + "image": "sissbruecker/linkding:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "sissbruecker/linkding:latest", + "restart": "unless-stopped", + "ports": [ + "9090:9090" + ], + "volumes": [ + "linkding-data:/etc/linkding/data" + ], + "environment": { + "LD_SUPERUSER_NAME": "admin", + "LD_SUPERUSER_PASSWORD": "${GENERATED_ADMIN_PASSWORD}" + } + } + } + ], + "top_level": { + "name": "linkding", + "volumes": { + "linkding-data": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "linkding-volume-0", + "service": "linkding", + "container_path": "/etc/linkding/data", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "linkding" + ], + "stop_order": [ + "linkding" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [ + { + "id": "generated-admin-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "linkding", + "environment_variable": "LD_SUPERUSER_PASSWORD" + } + ] + } + ] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 9090, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [ + { + "label": "Generated linkding administrator", + "type": "runtime-generated", + "username": "admin", + "password": null, + "password_environment": "LD_SUPERUSER_PASSWORD", + "change_required": true, + "source": "proxmenux-installer-generated", + "retrieval": null + } + ] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 1, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "generated_sensitive_environment": { + "LD_SUPERUSER_PASSWORD": { + "strategy": "token-hex", + "bytes": 24 + } + } + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/apps/mealie.json b/oci/catalog/apps/mealie.json new file mode 100644 index 00000000..15158b80 --- /dev/null +++ b/oci/catalog/apps/mealie.json @@ -0,0 +1,487 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-mealie", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Mealie" + }, + "tagline": { + "en_US": "Self-hosted recipe manager and meal planner." + }, + "description": { + "en_US": "Save, organize and share recipes with a self-hosted recipe manager." + }, + "category": "productivity", + "category_label": "Productivity & Workflows", + "author": "Mealie", + "developer": "Mealie", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/mealie.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 9000, + "path": "/" + }, + "website": "https://mealie.io/", + "documentation": "https://github.com/mealie-recipes/mealie/blob/mealie-next/docs/docs/documentation/getting-started/installation/sqlite.md", + "repository": "https://github.com/mealie-recipes/mealie", + "tips": [ + "SQLite is suitable for a small household; use PostgreSQL instead of SQLite when storing Mealie data on a NAS.", + "The documented initial login is changeme@example.com / MyPassword; change it after first sign-in." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "mealie", + "repository": "https://github.com/mealie-recipes/mealie", + "revision": "1fd76abcb208cc2ccc6245bfc1a573407552a33b1e0ce58c28fbdc7e7d10dff9", + "image_repository_url": "https://ghcr.io/mealie-recipes/mealie", + "readme_pushed_at": "", + "compose_sha256": "219e8c23c6e022f7bd0fb11411360ae9dd1ed87314cf7229a763ddf3b24243a9", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://github.com/mealie-recipes/mealie/blob/mealie-next/docs/docs/documentation/getting-started/installation/sqlite.md" + }, + "container_contract": { + "service_name": "mealie", + "container_name": "mealie", + "image": { + "reference": "ghcr.io/mealie-recipes/mealie:latest", + "registry": "ghcr.io", + "repository": "ghcr.io/mealie-recipes/mealie", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "ALLOW_SIGNUP", + "example": "false", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "PUID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "PGID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "TZ", + "example": "Etc/UTC", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/app/data", + "compose_source_example": "mealie-data", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 8 + } + } + ], + "ports": [ + { + "container_port": 9000, + "published_example": 9925, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"mealie\",\n \"services\": {\n \"mealie\": {\n \"image\": \"ghcr.io/mealie-recipes/mealie:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"9925:9000\"\n ],\n \"volumes\": [\n \"mealie-data:/app/data\"\n ],\n \"environment\": {\n \"ALLOW_SIGNUP\": \"false\",\n \"PUID\": \"1000\",\n \"PGID\": \"1000\",\n \"TZ\": \"Etc/UTC\"\n },\n \"deploy\": {\n \"resources\": {\n \"limits\": {\n \"memory\": \"1g\"\n }\n }\n }\n }\n },\n \"volumes\": {\n \"mealie-data\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "mealie", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "mealie", + "service_count": 1, + "services": [ + { + "name": "mealie", + "image": "ghcr.io/mealie-recipes/mealie:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "ghcr.io/mealie-recipes/mealie:latest", + "restart": "unless-stopped", + "ports": [ + "9925:9000" + ], + "volumes": [ + "mealie-data:/app/data" + ], + "environment": { + "ALLOW_SIGNUP": "false", + "PUID": "1000", + "PGID": "1000", + "TZ": "Etc/UTC" + }, + "deploy": { + "resources": { + "limits": { + "memory": "1g" + } + } + } + } + } + ], + "top_level": { + "name": "mealie", + "volumes": { + "mealie-data": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "mealie-volume-0", + "service": "mealie", + "container_path": "/app/data", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "mealie" + ], + "stop_order": [ + "mealie" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 9000, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [ + { + "label": "Initial Mealie account", + "type": "static-default", + "username": "changeme@example.com", + "password": "MyPassword", + "change_required": true, + "source": "https://github.com/mealie-recipes/mealie/blob/mealie-next/docs/docs/documentation/getting-started/installation/installation-checklist.md", + "retrieval": null + } + ] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "volume_owner": { + "uid": 1000, + "gid": 1000 + }, + "volume_preparations": [ + { + "container_path": "/app/data", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + } + ] + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/apps/miniflux.json b/oci/catalog/apps/miniflux.json new file mode 100644 index 00000000..545d4caf --- /dev/null +++ b/oci/catalog/apps/miniflux.json @@ -0,0 +1,536 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-miniflux", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Miniflux" + }, + "tagline": { + "en_US": "Minimalist self-hosted RSS reader." + }, + "description": { + "en_US": "Read and organize RSS feeds with a lightweight web-based feed reader." + }, + "category": "documents", + "category_label": "Documents & Notes", + "author": "Miniflux", + "developer": "Miniflux", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/miniflux.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 8080, + "path": "/" + }, + "website": "https://miniflux.app/", + "documentation": "https://miniflux.app/docs/docker.html", + "repository": "https://github.com/miniflux/v2", + "tips": [ + "Miniflux requires PostgreSQL; this recipe creates a separate private dependency LXC and uses the official PostgreSQL 18 data path.", + "The initial admin password is generated during installation. RUN_MIGRATIONS and CREATE_ADMIN are included for first startup; review upstream release notes before upgrades." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "miniflux", + "repository": "https://github.com/miniflux/v2", + "revision": "aba0cf8134b8a81a8dee4c10f771eec0ff39d1981fd414e707baf5164eb9b237", + "image_repository_url": "https://hub.docker.com/r/miniflux/miniflux", + "readme_pushed_at": "", + "compose_sha256": "279df22f2107c5be16a5e9bc90f48bbc32061e45eaf7c364ab742eba389086ca", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://miniflux.app/docs/docker.html" + }, + "container_contract": { + "service_name": "miniflux", + "container_name": "miniflux", + "image": { + "reference": "miniflux/miniflux:latest", + "registry": "docker.io", + "repository": "miniflux/miniflux", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "DATABASE_URL", + "example": "postgres://miniflux:${GENERATED_DB_PASSWORD}@postgres/miniflux?sslmode=disable", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "RUN_MIGRATIONS", + "example": "1", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "CREATE_ADMIN", + "example": "1", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "ADMIN_USERNAME", + "example": "admin", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "ADMIN_PASSWORD", + "example": "${GENERATED_ADMIN_PASSWORD}", + "required": true, + "sensitive": true, + "source": "docker-compose" + } + ], + "volumes": [], + "ports": [ + { + "container_port": 8080, + "published_example": 8080, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [ + { + "name": "postgres", + "image": "postgres:latest" + } + ], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"miniflux\",\n \"services\": {\n \"miniflux\": {\n \"image\": \"miniflux/miniflux:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"8080:8080\"\n ],\n \"depends_on\": {\n \"postgres\": {\n \"condition\": \"service_healthy\"\n }\n },\n \"environment\": {\n \"DATABASE_URL\": \"postgres://miniflux:${GENERATED_DB_PASSWORD}@postgres/miniflux?sslmode=disable\",\n \"RUN_MIGRATIONS\": \"1\",\n \"CREATE_ADMIN\": \"1\",\n \"ADMIN_USERNAME\": \"admin\",\n \"ADMIN_PASSWORD\": \"${GENERATED_ADMIN_PASSWORD}\"\n },\n \"deploy\": {\n \"resources\": {\n \"limits\": {\n \"memory\": \"1g\"\n }\n }\n }\n },\n \"postgres\": {\n \"image\": \"postgres:18\",\n \"restart\": \"unless-stopped\",\n \"environment\": {\n \"POSTGRES_USER\": \"miniflux\",\n \"POSTGRES_PASSWORD\": \"${GENERATED_DB_PASSWORD}\",\n \"POSTGRES_DB\": \"miniflux\"\n },\n \"volumes\": [\n \"miniflux-db:/var/lib/postgresql\"\n ],\n \"healthcheck\": {\n \"test\": [\n \"CMD\",\n \"pg_isready\",\n \"-U\",\n \"miniflux\"\n ],\n \"interval\": \"10s\",\n \"start_period\": \"30s\"\n }\n }\n },\n \"volumes\": {\n \"miniflux-db\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "miniflux", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "miniflux", + "service_count": 2, + "services": [ + { + "name": "postgres", + "image": "postgres:18", + "is_main": false, + "role": "dependency", + "vmid_offset": 1, + "depends_on": [], + "frontend_network": false, + "private_network": true, + "compose": { + "image": "postgres:18", + "restart": "unless-stopped", + "environment": { + "POSTGRES_USER": "miniflux", + "POSTGRES_PASSWORD": "${GENERATED_DB_PASSWORD}", + "POSTGRES_DB": "miniflux" + }, + "volumes": [ + "miniflux-db:/var/lib/postgresql" + ], + "healthcheck": { + "test": [ + "CMD", + "pg_isready", + "-U", + "miniflux" + ], + "interval": "10s", + "start_period": "30s" + } + } + }, + { + "name": "miniflux", + "image": "miniflux/miniflux:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [ + "postgres" + ], + "frontend_network": true, + "private_network": true, + "compose": { + "image": "miniflux/miniflux:latest", + "restart": "unless-stopped", + "ports": [ + "8080:8080" + ], + "depends_on": { + "postgres": { + "condition": "service_healthy" + } + }, + "environment": { + "DATABASE_URL": "postgres://miniflux:${GENERATED_DB_PASSWORD}@postgres/miniflux?sslmode=disable", + "RUN_MIGRATIONS": "1", + "CREATE_ADMIN": "1", + "ADMIN_USERNAME": "admin", + "ADMIN_PASSWORD": "${GENERATED_ADMIN_PASSWORD}" + }, + "deploy": { + "resources": { + "limits": { + "memory": "1g" + } + } + } + } + } + ], + "top_level": { + "name": "miniflux", + "volumes": { + "miniflux-db": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": true, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "postgres-volume-0", + "service": "postgres", + "container_path": "/var/lib/postgresql", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 2, + "start_order": [ + "postgres", + "miniflux" + ], + "stop_order": [ + "miniflux", + "postgres" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [ + { + "id": "db-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "postgres", + "environment_variable": "POSTGRES_PASSWORD" + }, + { + "service": "miniflux", + "environment_variable": "DATABASE_URL" + } + ] + }, + { + "id": "admin-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "miniflux", + "environment_variable": "ADMIN_PASSWORD" + } + ] + } + ] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 8080, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [ + { + "label": "Generated Miniflux administrator", + "type": "runtime-generated", + "username": "admin", + "password": null, + "password_environment": "ADMIN_PASSWORD", + "change_required": true, + "source": "proxmenux-installer-generated", + "retrieval": null + } + ] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "stack_driver": "generic-multi-lxc-stack" + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/apps/stirling-pdf.json b/oci/catalog/apps/stirling-pdf.json new file mode 100644 index 00000000..089af2e4 --- /dev/null +++ b/oci/catalog/apps/stirling-pdf.json @@ -0,0 +1,502 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-stirling-pdf", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Stirling-PDF" + }, + "tagline": { + "en_US": "Self-hosted PDF tools for editing, converting and signing documents." + }, + "description": { + "en_US": "A web-based toolkit for working with PDF files on your own server." + }, + "category": "documents", + "category_label": "Documents & Notes", + "author": "Stirling Tools", + "developer": "Stirling Tools", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/stirling-pdf.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 8080, + "path": "/" + }, + "website": "https://www.stirlingpdf.com/", + "documentation": "https://docs.stirlingpdf.com/Server/Install/Docker/", + "repository": "https://github.com/Stirling-Tools/Stirling-PDF", + "tips": [ + "The standard image includes OCR and office conversion tools; the official documentation suggests 4 GB of memory.", + "Keep both /configs and /storage persistent. The standard image documents admin / stirling as its initial login; change it after first sign-in." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "stirling-pdf", + "repository": "https://github.com/Stirling-Tools/Stirling-PDF", + "revision": "e7f6b5fe482945fca3527cc2f4035df717a526cf26c1ebd3e5a272ec140132f0", + "image_repository_url": "https://docker.stirlingpdf.com/stirlingtools/stirling-pdf", + "readme_pushed_at": "", + "compose_sha256": "6fa4793bff33f54b73a99364f26f3b69313a7c39dcd787c836d4f01f75e55146", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://docs.stirlingpdf.com/Server/Install/Docker/" + }, + "container_contract": { + "service_name": "stirling-pdf", + "container_name": "stirling-pdf", + "image": { + "reference": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest", + "registry": "docker.stirlingpdf.com", + "repository": "docker.stirlingpdf.com/stirlingtools/stirling-pdf", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "PUID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "PGID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/configs", + "compose_source_example": "stirling-config", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 2 + } + }, + { + "id": "volume-1", + "container_path": "/storage", + "compose_source_example": "stirling-storage", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 8 + } + } + ], + "ports": [ + { + "container_port": 8080, + "published_example": 8080, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"stirling-pdf\",\n \"services\": {\n \"stirling-pdf\": {\n \"image\": \"docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"8080:8080\"\n ],\n \"volumes\": [\n \"stirling-config:/configs\",\n \"stirling-storage:/storage\"\n ],\n \"environment\": {\n \"PUID\": \"1000\",\n \"PGID\": \"1000\"\n },\n \"deploy\": {\n \"resources\": {\n \"limits\": {\n \"memory\": \"4g\"\n }\n }\n }\n }\n }\n}" + }, + "compose_stack": { + "project_name": "stirling-pdf", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "stirling-pdf", + "service_count": 1, + "services": [ + { + "name": "stirling-pdf", + "image": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest", + "restart": "unless-stopped", + "ports": [ + "8080:8080" + ], + "volumes": [ + "stirling-config:/configs", + "stirling-storage:/storage" + ], + "environment": { + "PUID": "1000", + "PGID": "1000" + }, + "deploy": { + "resources": { + "limits": { + "memory": "4g" + } + } + } + } + } + ], + "top_level": { + "name": "stirling-pdf" + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "stirling-pdf-volume-0", + "service": "stirling-pdf", + "container_path": "/configs", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "stirling-pdf-volume-1", + "service": "stirling-pdf", + "container_path": "/storage", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "stirling-pdf" + ], + "stop_order": [ + "stirling-pdf" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 8080, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [ + { + "label": "Initial Stirling-PDF account", + "type": "static-default", + "username": "admin", + "password": "stirling", + "change_required": true, + "source": "https://docs.stirlingpdf.com/Server/Install/Docker/", + "retrieval": null + } + ] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 4096, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "volume_owner": { + "uid": 1000, + "gid": 1000 + }, + "volume_preparations": [ + { + "container_path": "/configs", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + }, + { + "container_path": "/storage", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + } + ] + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/apps/vikunja.json b/oci/catalog/apps/vikunja.json new file mode 100644 index 00000000..bc789dd1 --- /dev/null +++ b/oci/catalog/apps/vikunja.json @@ -0,0 +1,481 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-vikunja", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Vikunja" + }, + "tagline": { + "en_US": "Self-hosted task and project management." + }, + "description": { + "en_US": "Manage personal and shared tasks, lists and projects through a web interface." + }, + "category": "productivity", + "category_label": "Productivity & Workflows", + "author": "Vikunja", + "developer": "Vikunja", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/vikunja.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 3456, + "path": "/" + }, + "website": "https://vikunja.io/", + "documentation": "https://vikunja.io/docs/full-docker-example/", + "repository": "https://github.com/go-vikunja/vikunja", + "tips": [ + "This profile uses the built-in SQLite database and keeps both /db and uploaded files under persistent storage.", + "The official image runs as UID 1000. CORS is disabled as the upstream quick-start alternative when no public URL is configured; set VIKUNJA_SERVICE_PUBLICURL if you later publish it behind a domain." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "vikunja", + "repository": "https://github.com/go-vikunja/vikunja", + "revision": "60b9dd81900feea4e92a28ae3a9c121e142795831ed916edd365825518294169", + "image_repository_url": "https://hub.docker.com/r/vikunja/vikunja", + "readme_pushed_at": "", + "compose_sha256": "c0a35d2f2e20bf3ffcd5eaf7213cd06829bcbb15a697cd9fc6e38f61cfb8cb5e", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://vikunja.io/docs/full-docker-example/" + }, + "container_contract": { + "service_name": "vikunja", + "container_name": "vikunja", + "image": { + "reference": "vikunja/vikunja:latest", + "registry": "docker.io", + "repository": "vikunja/vikunja", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "VIKUNJA_CORS_ENABLE", + "example": "false", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/app/vikunja/files", + "compose_source_example": "vikunja-files", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 16 + } + }, + { + "id": "volume-1", + "container_path": "/db", + "compose_source_example": "vikunja-db", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 4 + } + } + ], + "ports": [ + { + "container_port": 3456, + "published_example": 3456, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"vikunja\",\n \"services\": {\n \"vikunja\": {\n \"image\": \"vikunja/vikunja:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"3456:3456\"\n ],\n \"volumes\": [\n \"vikunja-files:/app/vikunja/files\",\n \"vikunja-db:/db\"\n ],\n \"environment\": {\n \"VIKUNJA_CORS_ENABLE\": \"false\"\n }\n }\n },\n \"volumes\": {\n \"vikunja-db\": {},\n \"vikunja-files\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "vikunja", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "vikunja", + "service_count": 1, + "services": [ + { + "name": "vikunja", + "image": "vikunja/vikunja:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "vikunja/vikunja:latest", + "restart": "unless-stopped", + "ports": [ + "3456:3456" + ], + "volumes": [ + "vikunja-files:/app/vikunja/files", + "vikunja-db:/db" + ], + "environment": { + "VIKUNJA_CORS_ENABLE": "false" + } + } + } + ], + "top_level": { + "name": "vikunja", + "volumes": { + "vikunja-db": {}, + "vikunja-files": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "vikunja-volume-0", + "service": "vikunja", + "container_path": "/app/vikunja/files", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "vikunja-volume-1", + "service": "vikunja", + "container_path": "/db", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "vikunja" + ], + "stop_order": [ + "vikunja" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 3456, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "volume_owner": { + "uid": 1000, + "gid": 1000 + }, + "volume_preparations": [ + { + "container_path": "/app/vikunja/files", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + }, + { + "container_path": "/db", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + } + ] + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/categories.json b/oci/catalog/categories.json index 15bc49d0..2a6cacb7 100644 --- a/oci/catalog/categories.json +++ b/oci/catalog/categories.json @@ -88,6 +88,7 @@ "firefox": "desktop", "flexget": "arr", "flycast": "gaming", + "forgejo": "ai", "free-games-claimer-remaster": "gaming", "freecad": "creative", "gateway-go": "web", @@ -102,6 +103,7 @@ "heimdall": "productivity", "helium": "desktop", "hishtory-server": "ai", + "homebox": "tools", "htpcmanager": "media", "hugo": "web", "inkscape": "creative", @@ -117,15 +119,18 @@ "librespeed": "monitoring", "librewolf": "desktop", "limnoria": "communication", + "linkding": "documents", "lm-studio": "ai", "lollypop": "media", "luanti": "gaming", "lucky": "web", "mame": "gaming", "mdblistarr": "arr", + "mealie": "productivity", "mediaelch": "media", "melonds": "gaming", "mineos-node": "gaming", + "miniflux": "documents", "minisatip": "media", "mongodb4": "databases", "msedge": "desktop", @@ -185,6 +190,7 @@ "sqlitebrowser": "databases", "statping": "monitoring", "steam": "gaming", + "stirling-pdf": "documents", "strfry": "communication", "stunnel": "security", "swag": "web", @@ -201,6 +207,7 @@ "ungoogled-chromium": "desktop", "unifi-network-application": "network", "v2raya": "remote", + "vikunja": "productivity", "virt-manager": "management", "vivaldi": "desktop", "vlc": "media", diff --git a/oci/catalog/curated/forgejo.json b/oci/catalog/curated/forgejo.json new file mode 100644 index 00000000..b3f20c73 --- /dev/null +++ b/oci/catalog/curated/forgejo.json @@ -0,0 +1,462 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-forgejo", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Forgejo" + }, + "tagline": { + "en_US": "Self-hosted Git forge for code, issues and collaboration." + }, + "description": { + "en_US": "Host Git repositories and collaborate through a web interface with an integrated SSH server." + }, + "category": "ai", + "category_label": "AI / Coding & Dev-Tools", + "author": "Forgejo", + "developer": "Forgejo", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/forgejo.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 3000, + "path": "/" + }, + "website": "https://forgejo.org/", + "documentation": "https://forgejo.org/docs/v17.0/admin/installation/docker/", + "repository": "https://codeberg.org/forgejo/forgejo", + "tips": [ + "The official :17 image tag follows the latest Forgejo 17.x release; a major-version upgrade requires reading the release instructions.", + "Forgejo stores configuration, repositories and application data in /data. Create the first account through the initial web setup; SSH listens on port 22 of the LXC." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "forgejo", + "repository": "https://codeberg.org/forgejo/forgejo", + "revision": "ba0ffa712db27a668dccafc80f2474fe2fa9d62561d1f0ffbd923a12b192d971", + "image_repository_url": "https://codeberg.org/forgejo/forgejo", + "readme_pushed_at": "", + "compose_sha256": "0d2c0f5b29a0a9b5b1704e8454441cca77281282e25a4d7e2699c96a55af6a22", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://forgejo.org/docs/v17.0/admin/installation/docker/" + }, + "container_contract": { + "service_name": "forgejo", + "container_name": "forgejo", + "image": { + "reference": "codeberg.org/forgejo/forgejo:17", + "registry": "codeberg.org", + "repository": "codeberg.org/forgejo/forgejo", + "tag": "17", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "USER_UID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "USER_GID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/data", + "compose_source_example": "forgejo-data", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 16 + } + } + ], + "ports": [ + { + "container_port": 3000, + "published_example": 3000, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + }, + { + "container_port": 22, + "published_example": 222, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"forgejo\",\n \"services\": {\n \"forgejo\": {\n \"image\": \"codeberg.org/forgejo/forgejo:17\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"3000:3000\",\n \"222:22\"\n ],\n \"volumes\": [\n \"forgejo-data:/data\"\n ],\n \"environment\": {\n \"USER_UID\": \"1000\",\n \"USER_GID\": \"1000\"\n }\n }\n },\n \"volumes\": {\n \"forgejo-data\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "forgejo", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "forgejo", + "service_count": 1, + "services": [ + { + "name": "forgejo", + "image": "codeberg.org/forgejo/forgejo:17", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "codeberg.org/forgejo/forgejo:17", + "restart": "unless-stopped", + "ports": [ + "3000:3000", + "222:22" + ], + "volumes": [ + "forgejo-data:/data" + ], + "environment": { + "USER_UID": "1000", + "USER_GID": "1000" + } + } + } + ], + "top_level": { + "name": "forgejo", + "volumes": { + "forgejo-data": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "forgejo-volume-0", + "service": "forgejo", + "container_path": "/data", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "forgejo" + ], + "stop_order": [ + "forgejo" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 3000, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "The official Compose example uses the Forgejo :17 major-version tag, which tracks releases within the 17.x series.", + "native_lxc_behavior": "ProxMenux keeps the official :17 image reference and resolves that tag to an architecture-specific digest at installation.", + "reason": "Avoid crossing a Forgejo major-version boundary automatically; major upgrades need the documented manual steps.", + "behavioral_impact": "Automatic image checks follow 17.x. Moving to a later major version requires changing the image tag deliberately.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "volume_owner": { + "uid": 1000, + "gid": 1000 + }, + "volume_preparations": [ + { + "container_path": "/data", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + } + ] + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-configured-image-tag-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-configured-image-tag-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/curated/homebox.json b/oci/catalog/curated/homebox.json new file mode 100644 index 00000000..9e6f0366 --- /dev/null +++ b/oci/catalog/curated/homebox.json @@ -0,0 +1,458 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-homebox", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Homebox" + }, + "tagline": { + "en_US": "Self-hosted inventory and home organization." + }, + "description": { + "en_US": "Track household items, locations, warranties, documents and maintenance in one place." + }, + "category": "tools", + "category_label": "Tools", + "author": "Sysadmins Media", + "developer": "Sysadmins Media", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/homebox.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 7745, + "path": "/" + }, + "website": "https://homebox.software/", + "documentation": "https://github.com/sysadminsmedia/homebox#readme", + "repository": "https://github.com/sysadminsmedia/homebox", + "tips": [ + "The current Homebox Docker setup requires an API-key pepper; ProxMenux generates a unique value during installation." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "homebox", + "repository": "https://github.com/sysadminsmedia/homebox", + "revision": "1718e533b6ac0248c0756781ce0b69dd6239500ff87c3de01e5e8eee971143ed", + "image_repository_url": "https://ghcr.io/sysadminsmedia/homebox", + "readme_pushed_at": "", + "compose_sha256": "6da49efbad3d693bd5d8b327e0ac11a4b224cc53c6951107d7213edbf4bc4b02", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://github.com/sysadminsmedia/homebox#readme" + }, + "container_contract": { + "service_name": "homebox", + "container_name": "homebox", + "image": { + "reference": "ghcr.io/sysadminsmedia/homebox:latest", + "registry": "ghcr.io", + "repository": "ghcr.io/sysadminsmedia/homebox", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "TZ", + "example": "Etc/UTC", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "HBOX_AUTH_API_KEY_PEPPER", + "example": "${GENERATED_HBOX_AUTH_API_KEY_PEPPER}", + "required": true, + "sensitive": true, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/data", + "compose_source_example": "homebox-data", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 8 + } + } + ], + "ports": [ + { + "container_port": 7745, + "published_example": 3100, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"homebox\",\n \"services\": {\n \"homebox\": {\n \"image\": \"ghcr.io/sysadminsmedia/homebox:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"3100:7745\"\n ],\n \"volumes\": [\n \"homebox-data:/data\"\n ],\n \"environment\": {\n \"TZ\": \"Etc/UTC\",\n \"HBOX_AUTH_API_KEY_PEPPER\": \"${GENERATED_HBOX_AUTH_API_KEY_PEPPER}\"\n }\n }\n },\n \"volumes\": {\n \"homebox-data\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "homebox", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "homebox", + "service_count": 1, + "services": [ + { + "name": "homebox", + "image": "ghcr.io/sysadminsmedia/homebox:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "ghcr.io/sysadminsmedia/homebox:latest", + "restart": "unless-stopped", + "ports": [ + "3100:7745" + ], + "volumes": [ + "homebox-data:/data" + ], + "environment": { + "TZ": "Etc/UTC", + "HBOX_AUTH_API_KEY_PEPPER": "${GENERATED_HBOX_AUTH_API_KEY_PEPPER}" + } + } + } + ], + "top_level": { + "name": "homebox", + "volumes": { + "homebox-data": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "homebox-volume-0", + "service": "homebox", + "container_path": "/data", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "homebox" + ], + "stop_order": [ + "homebox" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [ + { + "id": "generated-hbox-auth-api-key-pepper", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "homebox", + "environment_variable": "HBOX_AUTH_API_KEY_PEPPER" + } + ] + } + ] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 7745, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 1, + "memory_mb": 512, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "generated_sensitive_environment": { + "HBOX_AUTH_API_KEY_PEPPER": { + "strategy": "token-hex", + "bytes": 48 + } + } + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/curated/linkding.json b/oci/catalog/curated/linkding.json new file mode 100644 index 00000000..53307b7e --- /dev/null +++ b/oci/catalog/curated/linkding.json @@ -0,0 +1,469 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-linkding", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "linkding" + }, + "tagline": { + "en_US": "Minimal self-hosted bookmark manager." + }, + "description": { + "en_US": "Save, tag and search bookmarks with a lightweight self-hosted web app." + }, + "category": "documents", + "category_label": "Documents & Notes", + "author": "linkding", + "developer": "linkding", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/linkding.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 9090, + "path": "/" + }, + "website": "https://linkding.link/", + "documentation": "https://github.com/sissbruecker/linkding#readme", + "repository": "https://github.com/sissbruecker/linkding", + "tips": [ + "The initial admin account is created at first start; ProxMenux generates its password and displays it after installation." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "linkding", + "repository": "https://github.com/sissbruecker/linkding", + "revision": "027502f1af892efbd166de7906e48a86b40b36a66bae1ef3396401d7f1814b12", + "image_repository_url": "https://hub.docker.com/r/sissbruecker/linkding", + "readme_pushed_at": "", + "compose_sha256": "acf453b78767f9d2e5c800bc0be41d0dc226621e064b284d94ad31335f0a940d", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://github.com/sissbruecker/linkding#readme" + }, + "container_contract": { + "service_name": "linkding", + "container_name": "linkding", + "image": { + "reference": "sissbruecker/linkding:latest", + "registry": "docker.io", + "repository": "sissbruecker/linkding", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "LD_SUPERUSER_NAME", + "example": "admin", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "LD_SUPERUSER_PASSWORD", + "example": "${GENERATED_ADMIN_PASSWORD}", + "required": true, + "sensitive": true, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/etc/linkding/data", + "compose_source_example": "linkding-data", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 4 + } + } + ], + "ports": [ + { + "container_port": 9090, + "published_example": 9090, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"linkding\",\n \"services\": {\n \"linkding\": {\n \"image\": \"sissbruecker/linkding:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"9090:9090\"\n ],\n \"volumes\": [\n \"linkding-data:/etc/linkding/data\"\n ],\n \"environment\": {\n \"LD_SUPERUSER_NAME\": \"admin\",\n \"LD_SUPERUSER_PASSWORD\": \"${GENERATED_ADMIN_PASSWORD}\"\n }\n }\n },\n \"volumes\": {\n \"linkding-data\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "linkding", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "linkding", + "service_count": 1, + "services": [ + { + "name": "linkding", + "image": "sissbruecker/linkding:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "sissbruecker/linkding:latest", + "restart": "unless-stopped", + "ports": [ + "9090:9090" + ], + "volumes": [ + "linkding-data:/etc/linkding/data" + ], + "environment": { + "LD_SUPERUSER_NAME": "admin", + "LD_SUPERUSER_PASSWORD": "${GENERATED_ADMIN_PASSWORD}" + } + } + } + ], + "top_level": { + "name": "linkding", + "volumes": { + "linkding-data": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "linkding-volume-0", + "service": "linkding", + "container_path": "/etc/linkding/data", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "linkding" + ], + "stop_order": [ + "linkding" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [ + { + "id": "generated-admin-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "linkding", + "environment_variable": "LD_SUPERUSER_PASSWORD" + } + ] + } + ] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 9090, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [ + { + "label": "Generated linkding administrator", + "type": "runtime-generated", + "username": "admin", + "password": null, + "password_environment": "LD_SUPERUSER_PASSWORD", + "change_required": true, + "source": "proxmenux-installer-generated", + "retrieval": null + } + ] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 1, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "generated_sensitive_environment": { + "LD_SUPERUSER_PASSWORD": { + "strategy": "token-hex", + "bytes": 24 + } + } + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/curated/mealie.json b/oci/catalog/curated/mealie.json new file mode 100644 index 00000000..15158b80 --- /dev/null +++ b/oci/catalog/curated/mealie.json @@ -0,0 +1,487 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-mealie", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Mealie" + }, + "tagline": { + "en_US": "Self-hosted recipe manager and meal planner." + }, + "description": { + "en_US": "Save, organize and share recipes with a self-hosted recipe manager." + }, + "category": "productivity", + "category_label": "Productivity & Workflows", + "author": "Mealie", + "developer": "Mealie", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/mealie.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 9000, + "path": "/" + }, + "website": "https://mealie.io/", + "documentation": "https://github.com/mealie-recipes/mealie/blob/mealie-next/docs/docs/documentation/getting-started/installation/sqlite.md", + "repository": "https://github.com/mealie-recipes/mealie", + "tips": [ + "SQLite is suitable for a small household; use PostgreSQL instead of SQLite when storing Mealie data on a NAS.", + "The documented initial login is changeme@example.com / MyPassword; change it after first sign-in." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "mealie", + "repository": "https://github.com/mealie-recipes/mealie", + "revision": "1fd76abcb208cc2ccc6245bfc1a573407552a33b1e0ce58c28fbdc7e7d10dff9", + "image_repository_url": "https://ghcr.io/mealie-recipes/mealie", + "readme_pushed_at": "", + "compose_sha256": "219e8c23c6e022f7bd0fb11411360ae9dd1ed87314cf7229a763ddf3b24243a9", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://github.com/mealie-recipes/mealie/blob/mealie-next/docs/docs/documentation/getting-started/installation/sqlite.md" + }, + "container_contract": { + "service_name": "mealie", + "container_name": "mealie", + "image": { + "reference": "ghcr.io/mealie-recipes/mealie:latest", + "registry": "ghcr.io", + "repository": "ghcr.io/mealie-recipes/mealie", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "ALLOW_SIGNUP", + "example": "false", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "PUID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "PGID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "TZ", + "example": "Etc/UTC", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/app/data", + "compose_source_example": "mealie-data", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 8 + } + } + ], + "ports": [ + { + "container_port": 9000, + "published_example": 9925, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"mealie\",\n \"services\": {\n \"mealie\": {\n \"image\": \"ghcr.io/mealie-recipes/mealie:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"9925:9000\"\n ],\n \"volumes\": [\n \"mealie-data:/app/data\"\n ],\n \"environment\": {\n \"ALLOW_SIGNUP\": \"false\",\n \"PUID\": \"1000\",\n \"PGID\": \"1000\",\n \"TZ\": \"Etc/UTC\"\n },\n \"deploy\": {\n \"resources\": {\n \"limits\": {\n \"memory\": \"1g\"\n }\n }\n }\n }\n },\n \"volumes\": {\n \"mealie-data\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "mealie", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "mealie", + "service_count": 1, + "services": [ + { + "name": "mealie", + "image": "ghcr.io/mealie-recipes/mealie:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "ghcr.io/mealie-recipes/mealie:latest", + "restart": "unless-stopped", + "ports": [ + "9925:9000" + ], + "volumes": [ + "mealie-data:/app/data" + ], + "environment": { + "ALLOW_SIGNUP": "false", + "PUID": "1000", + "PGID": "1000", + "TZ": "Etc/UTC" + }, + "deploy": { + "resources": { + "limits": { + "memory": "1g" + } + } + } + } + } + ], + "top_level": { + "name": "mealie", + "volumes": { + "mealie-data": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "mealie-volume-0", + "service": "mealie", + "container_path": "/app/data", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "mealie" + ], + "stop_order": [ + "mealie" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 9000, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [ + { + "label": "Initial Mealie account", + "type": "static-default", + "username": "changeme@example.com", + "password": "MyPassword", + "change_required": true, + "source": "https://github.com/mealie-recipes/mealie/blob/mealie-next/docs/docs/documentation/getting-started/installation/installation-checklist.md", + "retrieval": null + } + ] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "volume_owner": { + "uid": 1000, + "gid": 1000 + }, + "volume_preparations": [ + { + "container_path": "/app/data", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + } + ] + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/curated/miniflux.json b/oci/catalog/curated/miniflux.json new file mode 100644 index 00000000..545d4caf --- /dev/null +++ b/oci/catalog/curated/miniflux.json @@ -0,0 +1,536 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-miniflux", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Miniflux" + }, + "tagline": { + "en_US": "Minimalist self-hosted RSS reader." + }, + "description": { + "en_US": "Read and organize RSS feeds with a lightweight web-based feed reader." + }, + "category": "documents", + "category_label": "Documents & Notes", + "author": "Miniflux", + "developer": "Miniflux", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/miniflux.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 8080, + "path": "/" + }, + "website": "https://miniflux.app/", + "documentation": "https://miniflux.app/docs/docker.html", + "repository": "https://github.com/miniflux/v2", + "tips": [ + "Miniflux requires PostgreSQL; this recipe creates a separate private dependency LXC and uses the official PostgreSQL 18 data path.", + "The initial admin password is generated during installation. RUN_MIGRATIONS and CREATE_ADMIN are included for first startup; review upstream release notes before upgrades." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "miniflux", + "repository": "https://github.com/miniflux/v2", + "revision": "aba0cf8134b8a81a8dee4c10f771eec0ff39d1981fd414e707baf5164eb9b237", + "image_repository_url": "https://hub.docker.com/r/miniflux/miniflux", + "readme_pushed_at": "", + "compose_sha256": "279df22f2107c5be16a5e9bc90f48bbc32061e45eaf7c364ab742eba389086ca", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://miniflux.app/docs/docker.html" + }, + "container_contract": { + "service_name": "miniflux", + "container_name": "miniflux", + "image": { + "reference": "miniflux/miniflux:latest", + "registry": "docker.io", + "repository": "miniflux/miniflux", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "DATABASE_URL", + "example": "postgres://miniflux:${GENERATED_DB_PASSWORD}@postgres/miniflux?sslmode=disable", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "RUN_MIGRATIONS", + "example": "1", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "CREATE_ADMIN", + "example": "1", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "ADMIN_USERNAME", + "example": "admin", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "ADMIN_PASSWORD", + "example": "${GENERATED_ADMIN_PASSWORD}", + "required": true, + "sensitive": true, + "source": "docker-compose" + } + ], + "volumes": [], + "ports": [ + { + "container_port": 8080, + "published_example": 8080, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [ + { + "name": "postgres", + "image": "postgres:latest" + } + ], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"miniflux\",\n \"services\": {\n \"miniflux\": {\n \"image\": \"miniflux/miniflux:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"8080:8080\"\n ],\n \"depends_on\": {\n \"postgres\": {\n \"condition\": \"service_healthy\"\n }\n },\n \"environment\": {\n \"DATABASE_URL\": \"postgres://miniflux:${GENERATED_DB_PASSWORD}@postgres/miniflux?sslmode=disable\",\n \"RUN_MIGRATIONS\": \"1\",\n \"CREATE_ADMIN\": \"1\",\n \"ADMIN_USERNAME\": \"admin\",\n \"ADMIN_PASSWORD\": \"${GENERATED_ADMIN_PASSWORD}\"\n },\n \"deploy\": {\n \"resources\": {\n \"limits\": {\n \"memory\": \"1g\"\n }\n }\n }\n },\n \"postgres\": {\n \"image\": \"postgres:18\",\n \"restart\": \"unless-stopped\",\n \"environment\": {\n \"POSTGRES_USER\": \"miniflux\",\n \"POSTGRES_PASSWORD\": \"${GENERATED_DB_PASSWORD}\",\n \"POSTGRES_DB\": \"miniflux\"\n },\n \"volumes\": [\n \"miniflux-db:/var/lib/postgresql\"\n ],\n \"healthcheck\": {\n \"test\": [\n \"CMD\",\n \"pg_isready\",\n \"-U\",\n \"miniflux\"\n ],\n \"interval\": \"10s\",\n \"start_period\": \"30s\"\n }\n }\n },\n \"volumes\": {\n \"miniflux-db\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "miniflux", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "miniflux", + "service_count": 2, + "services": [ + { + "name": "postgres", + "image": "postgres:18", + "is_main": false, + "role": "dependency", + "vmid_offset": 1, + "depends_on": [], + "frontend_network": false, + "private_network": true, + "compose": { + "image": "postgres:18", + "restart": "unless-stopped", + "environment": { + "POSTGRES_USER": "miniflux", + "POSTGRES_PASSWORD": "${GENERATED_DB_PASSWORD}", + "POSTGRES_DB": "miniflux" + }, + "volumes": [ + "miniflux-db:/var/lib/postgresql" + ], + "healthcheck": { + "test": [ + "CMD", + "pg_isready", + "-U", + "miniflux" + ], + "interval": "10s", + "start_period": "30s" + } + } + }, + { + "name": "miniflux", + "image": "miniflux/miniflux:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [ + "postgres" + ], + "frontend_network": true, + "private_network": true, + "compose": { + "image": "miniflux/miniflux:latest", + "restart": "unless-stopped", + "ports": [ + "8080:8080" + ], + "depends_on": { + "postgres": { + "condition": "service_healthy" + } + }, + "environment": { + "DATABASE_URL": "postgres://miniflux:${GENERATED_DB_PASSWORD}@postgres/miniflux?sslmode=disable", + "RUN_MIGRATIONS": "1", + "CREATE_ADMIN": "1", + "ADMIN_USERNAME": "admin", + "ADMIN_PASSWORD": "${GENERATED_ADMIN_PASSWORD}" + }, + "deploy": { + "resources": { + "limits": { + "memory": "1g" + } + } + } + } + } + ], + "top_level": { + "name": "miniflux", + "volumes": { + "miniflux-db": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": true, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "postgres-volume-0", + "service": "postgres", + "container_path": "/var/lib/postgresql", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 2, + "start_order": [ + "postgres", + "miniflux" + ], + "stop_order": [ + "miniflux", + "postgres" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [ + { + "id": "db-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "postgres", + "environment_variable": "POSTGRES_PASSWORD" + }, + { + "service": "miniflux", + "environment_variable": "DATABASE_URL" + } + ] + }, + { + "id": "admin-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "miniflux", + "environment_variable": "ADMIN_PASSWORD" + } + ] + } + ] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 8080, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [ + { + "label": "Generated Miniflux administrator", + "type": "runtime-generated", + "username": "admin", + "password": null, + "password_environment": "ADMIN_PASSWORD", + "change_required": true, + "source": "proxmenux-installer-generated", + "retrieval": null + } + ] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "stack_driver": "generic-multi-lxc-stack" + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/curated/stirling-pdf.json b/oci/catalog/curated/stirling-pdf.json new file mode 100644 index 00000000..089af2e4 --- /dev/null +++ b/oci/catalog/curated/stirling-pdf.json @@ -0,0 +1,502 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-stirling-pdf", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Stirling-PDF" + }, + "tagline": { + "en_US": "Self-hosted PDF tools for editing, converting and signing documents." + }, + "description": { + "en_US": "A web-based toolkit for working with PDF files on your own server." + }, + "category": "documents", + "category_label": "Documents & Notes", + "author": "Stirling Tools", + "developer": "Stirling Tools", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/stirling-pdf.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 8080, + "path": "/" + }, + "website": "https://www.stirlingpdf.com/", + "documentation": "https://docs.stirlingpdf.com/Server/Install/Docker/", + "repository": "https://github.com/Stirling-Tools/Stirling-PDF", + "tips": [ + "The standard image includes OCR and office conversion tools; the official documentation suggests 4 GB of memory.", + "Keep both /configs and /storage persistent. The standard image documents admin / stirling as its initial login; change it after first sign-in." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "stirling-pdf", + "repository": "https://github.com/Stirling-Tools/Stirling-PDF", + "revision": "e7f6b5fe482945fca3527cc2f4035df717a526cf26c1ebd3e5a272ec140132f0", + "image_repository_url": "https://docker.stirlingpdf.com/stirlingtools/stirling-pdf", + "readme_pushed_at": "", + "compose_sha256": "6fa4793bff33f54b73a99364f26f3b69313a7c39dcd787c836d4f01f75e55146", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://docs.stirlingpdf.com/Server/Install/Docker/" + }, + "container_contract": { + "service_name": "stirling-pdf", + "container_name": "stirling-pdf", + "image": { + "reference": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest", + "registry": "docker.stirlingpdf.com", + "repository": "docker.stirlingpdf.com/stirlingtools/stirling-pdf", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "PUID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "PGID", + "example": "1000", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/configs", + "compose_source_example": "stirling-config", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 2 + } + }, + { + "id": "volume-1", + "container_path": "/storage", + "compose_source_example": "stirling-storage", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 8 + } + } + ], + "ports": [ + { + "container_port": 8080, + "published_example": 8080, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"stirling-pdf\",\n \"services\": {\n \"stirling-pdf\": {\n \"image\": \"docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"8080:8080\"\n ],\n \"volumes\": [\n \"stirling-config:/configs\",\n \"stirling-storage:/storage\"\n ],\n \"environment\": {\n \"PUID\": \"1000\",\n \"PGID\": \"1000\"\n },\n \"deploy\": {\n \"resources\": {\n \"limits\": {\n \"memory\": \"4g\"\n }\n }\n }\n }\n }\n}" + }, + "compose_stack": { + "project_name": "stirling-pdf", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "stirling-pdf", + "service_count": 1, + "services": [ + { + "name": "stirling-pdf", + "image": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest", + "restart": "unless-stopped", + "ports": [ + "8080:8080" + ], + "volumes": [ + "stirling-config:/configs", + "stirling-storage:/storage" + ], + "environment": { + "PUID": "1000", + "PGID": "1000" + }, + "deploy": { + "resources": { + "limits": { + "memory": "4g" + } + } + } + } + } + ], + "top_level": { + "name": "stirling-pdf" + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "stirling-pdf-volume-0", + "service": "stirling-pdf", + "container_path": "/configs", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "stirling-pdf-volume-1", + "service": "stirling-pdf", + "container_path": "/storage", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "stirling-pdf" + ], + "stop_order": [ + "stirling-pdf" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 8080, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [ + { + "label": "Initial Stirling-PDF account", + "type": "static-default", + "username": "admin", + "password": "stirling", + "change_required": true, + "source": "https://docs.stirlingpdf.com/Server/Install/Docker/", + "retrieval": null + } + ] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 4096, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "volume_owner": { + "uid": 1000, + "gid": 1000 + }, + "volume_preparations": [ + { + "container_path": "/configs", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + }, + { + "container_path": "/storage", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + } + ] + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/curated/vikunja.json b/oci/catalog/curated/vikunja.json new file mode 100644 index 00000000..bc789dd1 --- /dev/null +++ b/oci/catalog/curated/vikunja.json @@ -0,0 +1,481 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-vikunja", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Vikunja" + }, + "tagline": { + "en_US": "Self-hosted task and project management." + }, + "description": { + "en_US": "Manage personal and shared tasks, lists and projects through a web interface." + }, + "category": "productivity", + "category_label": "Productivity & Workflows", + "author": "Vikunja", + "developer": "Vikunja", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/vikunja.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "http", + "port": 3456, + "path": "/" + }, + "website": "https://vikunja.io/", + "documentation": "https://vikunja.io/docs/full-docker-example/", + "repository": "https://github.com/go-vikunja/vikunja", + "tips": [ + "This profile uses the built-in SQLite database and keeps both /db and uploaded files under persistent storage.", + "The official image runs as UID 1000. CORS is disabled as the upstream quick-start alternative when no public URL is configured; set VIKUNJA_SERVICE_PUBLICURL if you later publish it behind a domain." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "vikunja", + "repository": "https://github.com/go-vikunja/vikunja", + "revision": "60b9dd81900feea4e92a28ae3a9c121e142795831ed916edd365825518294169", + "image_repository_url": "https://hub.docker.com/r/vikunja/vikunja", + "readme_pushed_at": "", + "compose_sha256": "c0a35d2f2e20bf3ffcd5eaf7213cd06829bcbb15a697cd9fc6e38f61cfb8cb5e", + "generated_at": "2026-10-25T16:06:01+00:00", + "readme_raw_url": "https://vikunja.io/docs/full-docker-example/" + }, + "container_contract": { + "service_name": "vikunja", + "container_name": "vikunja", + "image": { + "reference": "vikunja/vikunja:latest", + "registry": "docker.io", + "repository": "vikunja/vikunja", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-selected-tag-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "VIKUNJA_CORS_ENABLE", + "example": "false", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/app/vikunja/files", + "compose_source_example": "vikunja-files", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 16 + } + }, + { + "id": "volume-1", + "container_path": "/db", + "compose_source_example": "vikunja-db", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume", + "host-bind" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 4 + } + } + ], + "ports": [ + { + "container_port": 3456, + "published_example": 3456, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "{\n \"name\": \"vikunja\",\n \"services\": {\n \"vikunja\": {\n \"image\": \"vikunja/vikunja:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"3456:3456\"\n ],\n \"volumes\": [\n \"vikunja-files:/app/vikunja/files\",\n \"vikunja-db:/db\"\n ],\n \"environment\": {\n \"VIKUNJA_CORS_ENABLE\": \"false\"\n }\n }\n },\n \"volumes\": {\n \"vikunja-db\": {},\n \"vikunja-files\": {}\n }\n}" + }, + "compose_stack": { + "project_name": "vikunja", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "vikunja", + "service_count": 1, + "services": [ + { + "name": "vikunja", + "image": "vikunja/vikunja:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [], + "frontend_network": true, + "private_network": false, + "compose": { + "image": "vikunja/vikunja:latest", + "restart": "unless-stopped", + "ports": [ + "3456:3456" + ], + "volumes": [ + "vikunja-files:/app/vikunja/files", + "vikunja-db:/db" + ], + "environment": { + "VIKUNJA_CORS_ENABLE": "false" + } + } + } + ], + "top_level": { + "name": "vikunja", + "volumes": { + "vikunja-db": {}, + "vikunja-files": {} + } + }, + "networking": { + "frontend": "selected-proxmox-bridge", + "private_required": false, + "private_creation": "automatic-create-if-missing", + "private_address_allocation": "automatic-static-address-per-service", + "service_discovery": "private-addresses-with-compose-service-host-aliases", + "dependency_external_access": "disabled-unless-service-publishes-ports", + "prompt_user_for_private_network": false + }, + "storage": [ + { + "id": "vikunja-volume-0", + "service": "vikunja", + "container_path": "/app/vikunja/files", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "vikunja-volume-1", + "service": "vikunja", + "container_path": "/db", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + } + ], + "orchestration": { + "reserve_vmids_atomically": 1, + "start_order": [ + "vikunja" + ], + "stop_order": [ + "vikunja" + ], + "dependency_readiness": "compose-healthcheck-then-port-or-process-fallback", + "rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes" + }, + "installer_inputs": { + "prompted": [ + "stack_name", + "base_vmid", + "rootfs_storage", + "persistent_data_destinations", + "frontend_bridge", + "frontend_ipv4_mode" + ], + "automatic": [ + "dependent_vmids", + "private_bridge", + "private_subnet", + "private_service_addresses", + "compose_service_aliases", + "generated_secrets", + "dependency_start_and_stop_order" + ], + "generated_secrets": [] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Web UI", + "scheme": "http", + "port": 3456, + "path": "/", + "source": "compose-metadata" + } + ], + "credentials": [] + }, + "proxmox": { + "runtime": "native-oci-lxc", + "technology_status": "proxmox-technology-preview", + "defaults": { + "unprivileged": true, + "ostype": "auto-from-image", + "cores": 2, + "memory_mb": 1024, + "swap_mb": 512, + "rootfs_size_gb": 8, + "rootfs_storage": "local-lvm", + "volume_storage": "local-lvm", + "template_storage": "local", + "bridge": "vmbr0", + "ipv4": "dhcp", + "firewall": true, + "host_managed_network": true, + "onboot": false, + "features": [ + "nesting=1" + ], + "shutdown_timeout_seconds": 120 + }, + "image_metadata_policy": { + "entrypoint": "import-from-oci-image", + "cmd": "import-from-oci-image", + "environment": "import-image-env-then-apply-compose-overrides", + "user": "import-from-oci-image", + "working_dir": "import-from-oci-image", + "stop_signal": "import-from-oci-image" + }, + "adaptations": [ + { + "id": "imported-compose-source", + "upstream_behavior": "The source definition deploys the complete Docker Compose application model.", + "native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.", + "reason": "Catalog import must not imply runtime compatibility.", + "behavioral_impact": "No automatic installation before review.", + "validation": "pending-per-application" + }, + { + "id": "rolling-latest-image", + "upstream_behavior": "A discovered Compose may pin a release tag or digest.", + "native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.", + "reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.", + "behavioral_impact": "The installed release can be newer than the discovered Compose revision.", + "validation": "pending-per-application" + }, + { + "id": "dedicated-lxc-network", + "upstream_behavior": "Docker publishes selected container ports on the Docker host.", + "native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.", + "reason": "A native LXC has its own address and does not require Docker port NAT.", + "behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.", + "validation": "pending-per-application" + }, + { + "id": "compose-shm-size", + "upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.", + "native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.", + "reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-command", + "upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.", + "native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.", + "reason": "Proxmox stores the effective OCI process as one entrypoint string.", + "behavioral_impact": "None expected.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-privileged-mode", + "upstream_behavior": "Compose selects whether the container runs in privileged mode.", + "native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.", + "reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.", + "behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.", + "validation": "native-equivalent" + }, + { + "id": "compose-process-runtime", + "upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.", + "native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.", + "reason": "The OCI process must start with the same identity, command and working directory without Docker.", + "behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-healthcheck", + "upstream_behavior": "Docker periodically executes the declared container healthcheck.", + "native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.", + "reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.", + "behavioral_impact": "The check runs during installation rather than continuously after installation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-cpu-priority", + "upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.", + "native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.", + "reason": "Both settings express relative CPU priority on different scales.", + "behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-resource-limits", + "upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.", + "native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.", + "reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.", + "behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-identity", + "upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.", + "native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.", + "reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.", + "behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-network-mode", + "upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.", + "native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.", + "reason": "The LXC is the application host and already has its own address and port namespace.", + "behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-capabilities-and-sysctls", + "upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.", + "native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.", + "reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.", + "behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.", + "validation": "not-requested-by-compose" + }, + { + "id": "docker-engine-metadata", + "upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.", + "native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.", + "reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.", + "behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-device-passthrough", + "upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.", + "native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.", + "reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.", + "behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.", + "validation": "not-requested-by-compose" + }, + { + "id": "compose-host-ipc", + "upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.", + "native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.", + "reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.", + "behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.", + "validation": "not-requested-by-compose" + } + ], + "installer_profile": { + "volume_owner": { + "uid": 1000, + "gid": 1000 + }, + "volume_preparations": [ + { + "container_path": "/app/vikunja/files", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + }, + { + "container_path": "/db", + "remove_lost_found": true, + "owner_strategy": "mapped-application-user", + "only_when_mount_type": "managed-volume" + } + ] + } + }, + "compatibility": { + "automatic_install_candidate": true, + "validated": false, + "supported_compose_keys": [ + "cap_add", + "command", + "container_name", + "cpu_shares", + "deploy", + "devices", + "entrypoint", + "environment", + "extra_hosts", + "group_add", + "healthcheck", + "hostname", + "image", + "init", + "ipc", + "labels", + "logging", + "mac_address", + "mem_limit", + "network_mode", + "networks", + "ports", + "privileged", + "restart", + "runtime", + "security_opt", + "shm_size", + "stdin_open", + "stop_grace_period", + "sysctls", + "tty", + "ulimits", + "user", + "volumes", + "working_dir" + ], + "untranslated_blockers": [], + "policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available." + }, + "validation": { + "schema": "pending", + "clean_install": "pending", + "service_health": "pending", + "restart_persistence": "pending", + "backup_restore": "pending", + "update_preserves_data": "pending" + }, + "lifecycle": { + "update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update", + "registry_state": { + "resolved_architecture": null, + "resolved_digest": null, + "image_version_label": null, + "image_created": null + }, + "change_detection": "compare-compose-sha256-and-resolved-latest-image-digest", + "automatic_unattended_updates": false + } +} diff --git a/oci/catalog/index.json b/oci/catalog/index.json index 269b3190..39961060 100644 --- a/oci/catalog/index.json +++ b/oci/catalog/index.json @@ -3508,6 +3508,38 @@ "hidden": false, "template_id": "linuxserver-foldingathome" }, + { + "id": "forgejo", + "provider": "forgejo", + "template_family": "curated-profile", + "title": "Forgejo", + "repository": "https://codeberg.org/forgejo/forgejo", + "description": "Host Git repositories and collaborate through a web interface with an integrated SSH server.", + "website": "https://forgejo.org/", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/forgejo.webp", + "architectures": [ + "amd64", + "arm64" + ], + "updated_at": null, + "main_image": "codeberg.org/forgejo/forgejo:17", + "category": "ai", + "category_label": "AI / Coding & Dev-Tools", + "replaces_discovered_ids": [], + "curated_path": "catalog/curated/forgejo.json", + "template": "apps/forgejo.json", + "template_status": "generated-unvalidated", + "automatic_install_candidate": true, + "untranslated_blockers": [], + "requires_privileged_lxc": false, + "optional_privileged_lxc": false, + "requires_host_pid_namespace": false, + "requires_relaxed_confinement": false, + "optional_relaxed_confinement": false, + "requires_security_confirmation": false, + "hidden": false, + "template_id": "image-forgejo" + }, { "id": "free-games-claimer-remaster", "provider": "p-adamiec", @@ -4480,6 +4512,38 @@ "hidden": false, "template_id": "image-homeassistant-official" }, + { + "id": "homebox", + "provider": "homebox", + "template_family": "curated-profile", + "title": "Homebox", + "repository": "https://github.com/sysadminsmedia/homebox", + "description": "Track household items, locations, warranties, documents and maintenance in one place.", + "website": "https://homebox.software/", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/homebox.webp", + "architectures": [ + "amd64", + "arm64" + ], + "updated_at": null, + "main_image": "ghcr.io/sysadminsmedia/homebox:latest", + "category": "tools", + "category_label": "Tools", + "replaces_discovered_ids": [], + "curated_path": "catalog/curated/homebox.json", + "template": "apps/homebox.json", + "template_status": "generated-unvalidated", + "automatic_install_candidate": true, + "untranslated_blockers": [], + "requires_privileged_lxc": false, + "optional_privileged_lxc": false, + "requires_host_pid_namespace": false, + "requires_relaxed_confinement": false, + "optional_relaxed_confinement": false, + "requires_security_confirmation": false, + "hidden": false, + "template_id": "image-homebox" + }, { "id": "homebridge", "source_app_id": "homebridge", @@ -5717,6 +5781,38 @@ "hidden": false, "template_id": "linuxserver-limnoria" }, + { + "id": "linkding", + "provider": "linkding", + "template_family": "curated-profile", + "title": "linkding", + "repository": "https://github.com/sissbruecker/linkding", + "description": "Save, tag and search bookmarks with a lightweight self-hosted web app.", + "website": "https://linkding.link/", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/linkding.webp", + "architectures": [ + "amd64", + "arm64" + ], + "updated_at": null, + "main_image": "sissbruecker/linkding:latest", + "category": "documents", + "category_label": "Documents & Notes", + "replaces_discovered_ids": [], + "curated_path": "catalog/curated/linkding.json", + "template": "apps/linkding.json", + "template_status": "generated-unvalidated", + "automatic_install_candidate": true, + "untranslated_blockers": [], + "requires_privileged_lxc": false, + "optional_privileged_lxc": false, + "requires_host_pid_namespace": false, + "requires_relaxed_confinement": false, + "optional_relaxed_confinement": false, + "requires_security_confirmation": false, + "hidden": false, + "template_id": "image-linkding" + }, { "id": "linkwarden", "source_app_id": "linkwarden", @@ -6294,6 +6390,38 @@ "hidden": false, "template_id": "image-mdblistarr" }, + { + "id": "mealie", + "provider": "mealie", + "template_family": "curated-profile", + "title": "Mealie", + "repository": "https://github.com/mealie-recipes/mealie", + "description": "Save, organize and share recipes with a self-hosted recipe manager.", + "website": "https://mealie.io/", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/mealie.webp", + "architectures": [ + "amd64", + "arm64" + ], + "updated_at": null, + "main_image": "ghcr.io/mealie-recipes/mealie:latest", + "category": "productivity", + "category_label": "Productivity & Workflows", + "replaces_discovered_ids": [], + "curated_path": "catalog/curated/mealie.json", + "template": "apps/mealie.json", + "template_status": "generated-unvalidated", + "automatic_install_candidate": true, + "untranslated_blockers": [], + "requires_privileged_lxc": false, + "optional_privileged_lxc": false, + "requires_host_pid_namespace": false, + "requires_relaxed_confinement": false, + "optional_relaxed_confinement": false, + "requires_security_confirmation": false, + "hidden": false, + "template_id": "image-mealie" + }, { "id": "mediaelch", "provider": "linuxserver.io", @@ -6496,6 +6624,38 @@ "hidden": false, "template_id": "image-mineos-node" }, + { + "id": "miniflux", + "provider": "miniflux", + "template_family": "curated-profile", + "title": "Miniflux", + "repository": "https://github.com/miniflux/v2", + "description": "Read and organize RSS feeds with a lightweight web-based feed reader.", + "website": "https://miniflux.app/", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/miniflux.webp", + "architectures": [ + "amd64", + "arm64" + ], + "updated_at": null, + "main_image": "miniflux/miniflux:latest", + "category": "documents", + "category_label": "Documents & Notes", + "replaces_discovered_ids": [], + "curated_path": "catalog/curated/miniflux.json", + "template": "apps/miniflux.json", + "template_status": "generated-unvalidated", + "automatic_install_candidate": true, + "untranslated_blockers": [], + "requires_privileged_lxc": false, + "optional_privileged_lxc": false, + "requires_host_pid_namespace": false, + "requires_relaxed_confinement": false, + "optional_relaxed_confinement": false, + "requires_security_confirmation": false, + "hidden": false, + "template_id": "image-miniflux" + }, { "id": "minisatip", "provider": "linuxserver.io", @@ -10612,6 +10772,38 @@ "hidden": false, "template_id": "linuxserver-steam" }, + { + "id": "stirling-pdf", + "provider": "stirling-pdf", + "template_family": "curated-profile", + "title": "Stirling-PDF", + "repository": "https://github.com/Stirling-Tools/Stirling-PDF", + "description": "A web-based toolkit for working with PDF files on your own server.", + "website": "https://www.stirlingpdf.com/", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/stirling-pdf.webp", + "architectures": [ + "amd64", + "arm64" + ], + "updated_at": null, + "main_image": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest", + "category": "documents", + "category_label": "Documents & Notes", + "replaces_discovered_ids": [], + "curated_path": "catalog/curated/stirling-pdf.json", + "template": "apps/stirling-pdf.json", + "template_status": "generated-unvalidated", + "automatic_install_candidate": true, + "untranslated_blockers": [], + "requires_privileged_lxc": false, + "optional_privileged_lxc": false, + "requires_host_pid_namespace": false, + "requires_relaxed_confinement": false, + "optional_relaxed_confinement": false, + "requires_security_confirmation": false, + "hidden": false, + "template_id": "image-stirling-pdf" + }, { "id": "stremio", "provider": "tsaridas", @@ -11806,6 +11998,38 @@ "hidden": false, "template_id": "image-vaultwarden" }, + { + "id": "vikunja", + "provider": "vikunja", + "template_family": "curated-profile", + "title": "Vikunja", + "repository": "https://github.com/go-vikunja/vikunja", + "description": "Manage personal and shared tasks, lists and projects through a web interface.", + "website": "https://vikunja.io/", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/vikunja.webp", + "architectures": [ + "amd64", + "arm64" + ], + "updated_at": null, + "main_image": "vikunja/vikunja:latest", + "category": "productivity", + "category_label": "Productivity & Workflows", + "replaces_discovered_ids": [], + "curated_path": "catalog/curated/vikunja.json", + "template": "apps/vikunja.json", + "template_status": "generated-unvalidated", + "automatic_install_candidate": true, + "untranslated_blockers": [], + "requires_privileged_lxc": false, + "optional_privileged_lxc": false, + "requires_host_pid_namespace": false, + "requires_relaxed_confinement": false, + "optional_relaxed_confinement": false, + "requires_security_confirmation": false, + "hidden": false, + "template_id": "image-vikunja" + }, { "id": "virt-manager", "source_app_id": "virt-manager",