diff --git a/lang/de.json b/lang/de.json index 7e532494..89c17f1f 100644 --- a/lang/de.json +++ b/lang/de.json @@ -1644,6 +1644,7 @@ "Create scheduled backup job": "Erstellen Sie einen geplanten Sicherungsauftrag", "Create share directory:": "Freigabeverzeichnis erstellen:", "Create shared directory:": "Freigegebenes Verzeichnis erstellen:", + "ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux erzeugt das Administratorpasswort und zeigt es am Ende der Installation an. Ändern Sie es nach der ersten Anmeldung.", "Create this LXC in privileged mode?": "Erstellen Sie diese LXC im privilegierten Modus?", "Create with create_user in the container console": "Erstellen Sie den Benutzer mit create_user in der Container-Konsole", "Create, send and sign documents with a self-hosted web app.": "Erstelle, versende und signiere Dokumente mit einer selbst gehosteten Web-App.", @@ -3904,6 +3905,7 @@ "Linux/Mac path:": "Linux/Mac-Pfad:", "LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin mit optionalem GPU-Passthrough", "LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requires ein Benutzer, Datenbank und Passwort", + "LinuxServer Nextcloud with MariaDB and Redis": "LinuxServer Nextcloud mit MariaDB und Redis", "List Available Disks": "Verfügbare Festplatten auflisten", "List IOMMU group mapping": "IOMMU-Gruppenzuordnung auflisten", "List NVMe devices": "NVMe-Geräte auflisten", @@ -4484,6 +4486,7 @@ "Next Step Required": "Nächster Schritt erforderlich", "Next Steps:": "Nächste Schritte:", "Next step: stop that VM first, then run": "Nächster Schritt: Stoppen Sie zuerst die VM und führen Sie sie dann aus", + "Nextcloud Web UI": "Nextcloud-Weboberfläche", "Nextcloud configuration cancelled": "Nextcloud-Konfiguration gestrichen", "Nextcloud gives you access to all your files wherever you are.": "Nextcloud bietet Ihnen Zugriff auf alle Ihre Dateien, wo immer Sie sind.", "Nextcloud volume size in GB": "Nextcloud Volumengröße in GB", @@ -5605,6 +5608,7 @@ "Recreation prepared": "Erholung vorbereitet", "Recursive DNS resolver.": "Rekursiver DNS-Resolver.", "Recursive and authoritative DNS server.": "Rekursiver und autoritativer DNS-Server.", + "Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Die Dateisperre mit Redis wird automatisch eingerichtet. Vorhandene Nextcloud-Konfigurationsdateien bleiben erhalten.", "Redmine": "Redmine", "Refresh APT index and verify repositories:": "APT-Index aktualisieren und Repositorys überprüfen:", "Refresh catalog": "Katalog aktualisieren", @@ -7995,6 +7999,7 @@ "Use a privileged LXC for NFS server/client workflows.": "Verwenden Sie einen privilegierten LXC für NFS-Server-/Client-Workflows.", "Use a privileged LXC for Samba client/server workflows.": "Verwenden Sie einen privilegierten LXC für Samba-Client/Server-Workflows.", "Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Verwenden Sie einen Registrierungs-Hostnamen, zum Beispiel ghcr.io oder registry.example.com:5000.", + "Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Verwenden Sie einen HTTPS-Reverse-Proxy mit einem vertrauenswürdigen Zertifikat. Aktualisieren Sie Nextcloud jeweils auf die nächste Hauptversion, ohne eine zu überspringen.", "Use an existing SSH private key file on this host": "Verwenden Sie eine vorhandene private SSH-Schlüsseldatei auf diesem Host", "Use an existing keyfile": "Verwenden Sie eine vorhandene Schlüsseldatei", "Use an image reference, for example ghcr.io/owner/app:latest.": "Verwenden Sie eine Bildreferenz, zum Beispiel ghcr.io/owner/app:latest.", @@ -8008,6 +8013,7 @@ "Use existing filesystem": "Vorhandenes Dateisystem verwenden", "Use existing: mount without formatting": "Vorhandenes verwenden: mounten ohne Formatierung", "Use images only if the directory is on suitable storage.": "Verwenden Sie Bilder nur, wenn sich das Verzeichnis auf einem geeigneten Speicher befindet.", + "Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Verwenden Sie verwalteten Speicher für /config und MariaDB. Für /data können Sie ein Verzeichnis auf dem Host/NAS auswählen, das eine eigene Sicherung benötigt.", "Use mp1/mp2/... for extra mount points.": "Verwenden Sie mp1/mp2/... für zusätzliche Mount-Punkte.", "Use only when unprivileged containers cannot meet your needs": "Verwenden Sie es nur, wenn nicht privilegierte Container Ihre Anforderungen nicht erfüllen können", "Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Verwenden Sie Option 1, um eine lokale Festplatte hinzuzufügen (als Proxmox-Speicher und/oder als Host-Mount).", diff --git a/lang/es.json b/lang/es.json index 457f5bdc..2bffe518 100644 --- a/lang/es.json +++ b/lang/es.json @@ -1642,6 +1642,7 @@ "Create scheduled backup job": "Crear trabajo de backup programado", "Create share directory:": "Crear directorio compartido:", "Create shared directory:": "Crear directorio compartido:", + "ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux genera la contraseña del administrador y la muestra al final de la instalación. Cámbiala después del primer inicio de sesión.", "Create this LXC in privileged mode?": "¿Crear este LXC en modo privilegiado?", "Create with create_user in the container console": "Crea el usuario con create_user desde la consola del contenedor", "Create, send and sign documents with a self-hosted web app.": "Crea, envía y firma documentos con una aplicación web autoalojada.", @@ -3899,6 +3900,7 @@ "Linux/Mac path:": "Ruta Linux/Mac:", "LinuxServer Jellyfin with optional GPU passthrough": "Jellyfin de LinuxServer con passthrough de GPU opcional", "LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requiere un usuario, base de datos y contraseña", + "LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud de LinuxServer con MariaDB y Redis", "List Available Disks": "Listar discos disponibles", "List IOMMU group mapping": "Listar el mapeo del grupo IOMMU", "List NVMe devices": "Listar dispositivos NVMe", @@ -4479,6 +4481,7 @@ "Next Step Required": "Se requiere el siguiente paso", "Next Steps:": "Próximos pasos:", "Next step: stop that VM first, then run": "Siguiente paso: detén esa VM primero y luego ejecuta", + "Nextcloud Web UI": "Interfaz web de Nextcloud", "Nextcloud configuration cancelled": "Configuración Nextcloud cancelada", "Nextcloud gives you access to all your files wherever you are.": "Nextcloud te da acceso a todos tus archivos estés donde estés.", "Nextcloud volume size in GB": "Tamaño del volumen de Nextcloud en GB", @@ -5588,6 +5591,7 @@ "Recreating the container:": "Recreando el contenedor:", "Recursive DNS resolver.": "Resolvedor DNS recursivo.", "Recursive and authoritative DNS server.": "Servidor DNS recursivo y autoritativo.", + "Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "El bloqueo con Redis se configura automáticamente. Se conservan los archivos de configuración existentes de Nextcloud.", "Redmine": "Redmine", "Refresh APT index and verify repositories:": "Actualizar el índice APT y verificar los repositorios:", "Refresh catalog": "Actualizar catálogo", @@ -7966,6 +7970,7 @@ "Use a privileged LXC for NFS server/client workflows.": "Utiliza un LXC privilegiado para flujos de trabajo de servidor/cliente NFS.", "Use a privileged LXC for Samba client/server workflows.": "Utiliza un LXC privilegiado para flujos de trabajo de cliente/servidor Samba.", "Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Escribe el nombre de un registro, por ejemplo ghcr.io o registry.example.com:5000.", + "Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Usa un proxy inverso HTTPS con un certificado de confianza. Actualiza Nextcloud de una versión principal a la siguiente, sin saltarte ninguna.", "Use an existing SSH private key file on this host": "Usar un archivo de clave privada SSH existente en este host", "Use an existing keyfile": "Usar un archivo de claves existente", "Use an image reference, for example ghcr.io/owner/app:latest.": "Escribe una referencia de imagen, por ejemplo ghcr.io/owner/app:latest.", @@ -7979,6 +7984,7 @@ "Use existing filesystem": "Usar el sistema de archivos existente", "Use existing: mount without formatting": "Usar existente: montar sin formatear", "Use images only if the directory is on suitable storage.": "Utiliza imágenes solo si el directorio está en un almacenamiento adecuado.", + "Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Usa almacenamiento gestionado para /config y MariaDB. Para /data puedes elegir un directorio del host/NAS, que necesita su propia copia de seguridad.", "Use mp1/mp2/... for extra mount points.": "Utiliza mp1/mp2/... para puntos de montaje adicionales.", "Use only when unprivileged containers cannot meet your needs": "Úselo solo cuando los contenedores sin privilegios no puedan satisfacer sus necesidades", "Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Utiliza la opción 1 para añadir un disco local (como almacenamiento Proxmox y/o como montaje de host).", diff --git a/lang/fr.json b/lang/fr.json index 5b584a87..32aa40ac 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -1644,6 +1644,7 @@ "Create scheduled backup job": "Créer une tâche de sauvegarde planifiée", "Create share directory:": "Créer un répertoire de partage :", "Create shared directory:": "Créer un répertoire partagé :", + "ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux génère le mot de passe de l'administrateur et l'affiche à la fin de l'installation. Modifiez-le après la première connexion.", "Create this LXC in privileged mode?": "Créer ce LXC en mode privilégié ?", "Create with create_user in the container console": "Créez l’utilisateur avec create_user dans la console du conteneur", "Create, send and sign documents with a self-hosted web app.": "Créez, envoyez et signez des documents avec une application web auto-hébergée.", @@ -3904,6 +3905,7 @@ "Linux/Mac path:": "Chemin Linux/Mac :", "LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin avec passage GPU optionnel", "LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requires un utilisateur, une base de données et un mot de passe", + "LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud de LinuxServer avec MariaDB et Redis", "List Available Disks": "Liste des disques disponibles", "List IOMMU group mapping": "Répertorier le mappage de groupe IOMMU", "List NVMe devices": "Répertorier les appareils NVMe", @@ -4484,6 +4486,7 @@ "Next Step Required": "Prochaine étape requise", "Next Steps:": "Prochaines étapes :", "Next step: stop that VM first, then run": "Étape suivante : arrêtez d'abord cette VM, puis exécutez", + "Nextcloud Web UI": "Interface web de Nextcloud", "Nextcloud configuration cancelled": "Configuration Nextcloud annulée", "Nextcloud gives you access to all your files wherever you are.": "Nextcloud vous donne accès à tous vos fichiers où que vous soyez.", "Nextcloud volume size in GB": "Taille du volume Nextcloud en GB", @@ -5605,6 +5608,7 @@ "Recreation prepared": "Loisirs préparés", "Recursive DNS resolver.": "Résolveur DNS récursif.", "Recursive and authoritative DNS server.": "Serveur DNS récursif et faisant autorité.", + "Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Le verrouillage avec Redis est configuré automatiquement. Les fichiers de configuration existants de Nextcloud sont conservés.", "Redmine": "Redmine", "Refresh APT index and verify repositories:": "Actualisez l'index APT et vérifiez les référentiels :", "Refresh catalog": "Actualiser le catalogue", @@ -7994,6 +7998,7 @@ "Use a privileged LXC for NFS server/client workflows.": "Utilisez un LXC privilégié pour les workflows serveur/client NFS.", "Use a privileged LXC for Samba client/server workflows.": "Utilisez un LXC privilégié pour les workflows client/serveur Samba.", "Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Utilisez un nom d'hôte de registre, par exemple ghcr.io ou registry.example.com:5000.", + "Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Utilisez un proxy inverse HTTPS avec un certificat de confiance. Mettez Nextcloud à niveau vers la version majeure suivante, sans en sauter.", "Use an existing SSH private key file on this host": "Utiliser un fichier de clé privée SSH existant sur cet hôte", "Use an existing keyfile": "utiliser un fichier de clés existant", "Use an image reference, for example ghcr.io/owner/app:latest.": "Utilisez une référence d'image, par exemple ghcr.io/owner/app:latest.", @@ -8007,6 +8012,7 @@ "Use existing filesystem": "Utiliser le système de fichiers existant", "Use existing: mount without formatting": "Utiliser existant : monter sans formatage", "Use images only if the directory is on suitable storage.": "Utilisez des images uniquement si le répertoire se trouve sur un stockage approprié.", + "Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Utilisez un stockage géré pour /config et MariaDB. Pour /data, vous pouvez choisir un répertoire de l’hôte/NAS, qui nécessite sa propre sauvegarde.", "Use mp1/mp2/... for extra mount points.": "Utilisez mp1/mp2/... pour des points de montage supplémentaires.", "Use only when unprivileged containers cannot meet your needs": "À utiliser uniquement lorsque les conteneurs non privilégiés ne peuvent pas répondre à vos besoins", "Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Utilisez l'option 1 pour ajouter un disque local (comme stockage Proxmox et/ou comme montage hôte).", diff --git a/lang/it.json b/lang/it.json index d436d084..e52a5805 100644 --- a/lang/it.json +++ b/lang/it.json @@ -1644,6 +1644,7 @@ "Create scheduled backup job": "Crea attività di backup pianificata", "Create share directory:": "Crea directory condivisa:", "Create shared directory:": "Crea directory condivisa:", + "ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux genera la password dell'amministratore e la mostra alla fine dell'installazione. Cambiala dopo il primo accesso.", "Create this LXC in privileged mode?": "Creare questo LXC in modalità privilegiata?", "Create with create_user in the container console": "Crea l’utente con create_user nella console del container", "Create, send and sign documents with a self-hosted web app.": "Crea, invia e firma documenti con un'app web self-hosted.", @@ -3904,6 +3905,7 @@ "Linux/Mac path:": "Percorso Linux/Mac:", "LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin con passthrough GPU opzionale", "LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB richiede un utente, un database e una password", + "LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud di LinuxServer con MariaDB e Redis", "List Available Disks": "Elenca i dischi disponibili", "List IOMMU group mapping": "Elenca la mappatura dei gruppi IOMMU", "List NVMe devices": "Elenca i dispositivi NVMe", @@ -4484,6 +4486,7 @@ "Next Step Required": "Passaggio successivo obbligatorio", "Next Steps:": "Passaggi successivi:", "Next step: stop that VM first, then run": "Passaggio successivo: arresta prima la VM, quindi esegui", + "Nextcloud Web UI": "Interfaccia web di Nextcloud", "Nextcloud configuration cancelled": "Configurazione di Nextcloud annullata", "Nextcloud gives you access to all your files wherever you are.": "Nextcloud ti dà accesso a tutti i tuoi file, ovunque ti trovi.", "Nextcloud volume size in GB": "Dimensione volume Nextcloud in GB", @@ -5605,6 +5608,7 @@ "Recreation prepared": "Ricreazione preparata", "Recursive DNS resolver.": "Resolver DNS ricorsivo.", "Recursive and authoritative DNS server.": "Server DNS ricorsivo e autorevole.", + "Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Il blocco dei file con Redis viene configurato automaticamente. I file di configurazione esistenti di Nextcloud vengono conservati.", "Redmine": "Redmine", "Refresh APT index and verify repositories:": "Aggiorna l'indice APT e verifica i repository:", "Refresh catalog": "Aggiorna catalogo", @@ -7995,6 +7999,7 @@ "Use a privileged LXC for NFS server/client workflows.": "Usare un LXC privilegiato per le operazioni server/client NFS.", "Use a privileged LXC for Samba client/server workflows.": "Usare un LXC privilegiato per le operazioni client/server Samba.", "Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Utilizza un nome host del registro, ad esempio ghcr.io o registry.example.com:5000.", + "Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Usa un proxy inverso HTTPS con un certificato attendibile. Aggiorna Nextcloud alla versione principale successiva, senza saltarne nessuna.", "Use an existing SSH private key file on this host": "Usa un file di chiave privata SSH esistente su questo host", "Use an existing keyfile": "Usa file di chiavi esistente", "Use an image reference, for example ghcr.io/owner/app:latest.": "Utilizza un riferimento a un'immagine, ad esempio ghcr.io/owner/app:latest.", @@ -8008,6 +8013,7 @@ "Use existing filesystem": "Usa file system esistente", "Use existing: mount without formatting": "Usa esistente: monta senza formattare", "Use images only if the directory is on suitable storage.": "Usare images solo se la directory è su uno storage adatto.", + "Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Usa lo storage gestito per /config e MariaDB. Per /data puoi scegliere una directory dell’host/NAS, che richiede un backup separato.", "Use mp1/mp2/... for extra mount points.": "Usare mp1/mp2/... per mount aggiuntivi.", "Use only when unprivileged containers cannot meet your needs": "Usare solo se i container non privilegiati non soddisfano le esigenze", "Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Usare l’opzione 1 per aggiungere un disco locale (come storage Proxmox e/o mount host).", diff --git a/lang/pt.json b/lang/pt.json index 2031b6d6..74e5d456 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -1644,6 +1644,7 @@ "Create scheduled backup job": "Criar tarefa de backup agendada", "Create share directory:": "Crie um diretório de compartilhamento:", "Create shared directory:": "Crie um diretório compartilhado:", + "ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "O ProxMenux gera a senha do administrador e mostra-a no fim da instalação. Altere-a após o primeiro login.", "Create this LXC in privileged mode?": "Criar este LXC em modo privilegiado?", "Create with create_user in the container console": "Crie o utilizador com create_user na consola do contentor", "Create, send and sign documents with a self-hosted web app.": "Crie, envie e assine documentos com uma aplicação web autoalojada.", @@ -3904,6 +3905,7 @@ "Linux/Mac path:": "Caminho Linux/Mac:", "LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin com passagem opcional de GPU", "LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requires um usuário, banco de dados e senha", + "LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud da LinuxServer com MariaDB e Redis", "List Available Disks": "Listar discos disponíveis", "List IOMMU group mapping": "Listar mapeamento de grupo IOMMU", "List NVMe devices": "Listar dispositivos NVMe", @@ -4484,6 +4486,7 @@ "Next Step Required": "Próxima etapa obrigatória", "Next Steps:": "Próximas etapas:", "Next step: stop that VM first, then run": "Próxima etapa: pare a VM primeiro e depois execute", + "Nextcloud Web UI": "Interface web do Nextcloud", "Nextcloud configuration cancelled": "Configuração do Nextcloud cancelada", "Nextcloud gives you access to all your files wherever you are.": "O Nextcloud dá-lhe acesso a todos os seus ficheiros onde quer que esteja.", "Nextcloud volume size in GB": "Tamanho do volume Nextcloud em GB", @@ -5605,6 +5608,7 @@ "Recreation prepared": "Recreação preparada", "Recursive DNS resolver.": "Resolvedor DNS recursivo.", "Recursive and authoritative DNS server.": "Servidor DNS recursivo e autoritativo.", + "Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "O bloqueio de ficheiros com Redis é configurado automaticamente. Os ficheiros de configuração existentes do Nextcloud são preservados.", "Redmine": "Redmine", "Refresh APT index and verify repositories:": "Atualize o índice APT e verifique os repositórios:", "Refresh catalog": "Atualizar catálogo", @@ -7995,6 +7999,7 @@ "Use a privileged LXC for NFS server/client workflows.": "Use um LXC privilegiado para fluxos de trabalho de servidor/cliente NFS.", "Use a privileged LXC for Samba client/server workflows.": "Use um LXC privilegiado para fluxos de trabalho cliente/servidor Samba.", "Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Use um nome de host de registro, por exemplo ghcr.io ou registry.example.com:5000.", + "Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Use um proxy inverso HTTPS com um certificado de confiança. Atualize o Nextcloud para a versão principal seguinte, sem saltar nenhuma.", "Use an existing SSH private key file on this host": "Use um arquivo de chave privada SSH existente neste host", "Use an existing keyfile": "Use um arquivo-chave existente", "Use an image reference, for example ghcr.io/owner/app:latest.": "Use uma referência de imagem, por exemplo ghcr.io/owner/app:latest.", @@ -8008,6 +8013,7 @@ "Use existing filesystem": "Use o sistema de arquivos existente", "Use existing: mount without formatting": "Use existente: monte sem formatação", "Use images only if the directory is on suitable storage.": "Use imagens somente se o diretório estiver em um armazenamento adequado.", + "Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Use armazenamento gerido para /config e MariaDB. Para /data pode escolher um diretório do host/NAS, que precisa de uma cópia de segurança separada.", "Use mp1/mp2/... for extra mount points.": "Use mp1/mp2/... para pontos de montagem extras.", "Use only when unprivileged containers cannot meet your needs": "Use somente quando contêineres sem privilégios não atenderem às suas necessidades", "Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Use a opção 1 para adicionar um disco local (como armazenamento Proxmox e/ou como montagem de host).", diff --git a/lang/sk.json b/lang/sk.json index cba030bb..c786b1c8 100644 --- a/lang/sk.json +++ b/lang/sk.json @@ -1644,6 +1644,7 @@ "Create scheduled backup job": "Vytvoriť naplánovanú úlohu zálohy", "Create share directory:": "Vytvoriť zdieľaný priečinok:", "Create shared directory:": "Vytvoriť zdieľaný priečinok:", + "ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux vygeneruje heslo správcu a zobrazí ho na konci inštalácie. Po prvom prihlásení ho zmeňte.", "Create this LXC in privileged mode?": "Vytvoriť tento LXC v privilegovanom režime?", "Create with create_user in the container console": "Používateľa vytvorte príkazom create_user v konzole kontajnera", "Create, send and sign documents with a self-hosted web app.": "Vytvárajte, posielajte a podpisujte dokumenty vo webovej aplikácii prevádzkovanej vo vlastnej réžii.", @@ -3904,6 +3905,7 @@ "Linux/Mac path:": "Cesta pre Linux/Mac:", "LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin s voliteľným GPU priechodom", "LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB vyžaduje používateľa, databázu a heslo", + "LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud od LinuxServer s MariaDB a Redis", "List Available Disks": "Zobraziť dostupné disky", "List IOMMU group mapping": "Zobraziť mapovanie IOMMU skupín", "List NVMe devices": "Zobraziť NVMe zariadenia", @@ -4484,6 +4486,7 @@ "Next Step Required": "Je potrebný ďalší krok", "Next Steps:": "Ďalšie kroky:", "Next step: stop that VM first, then run": "Ďalší krok: najprv zastavte tú VM, potom spustite", + "Nextcloud Web UI": "Webové rozhranie Nextcloud", "Nextcloud configuration cancelled": "Konfigurácia Nextcloud zrušená", "Nextcloud gives you access to all your files wherever you are.": "Nextcloud vám umožní prístup ku všetkým súborom kdekoľvek ste.", "Nextcloud volume size in GB": "Veľkosť dátového zväzku Nextcloud v GB", @@ -5607,6 +5610,7 @@ "Recreation prepared": "Pripravené rekreácie", "Recursive DNS resolver.": "Rekurzívny DNS resolver.", "Recursive and authoritative DNS server.": "Rekurzívny a autoritatívny DNS server.", + "Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Zamykanie súborov pomocou Redis sa nastaví automaticky. Existujúce konfiguračné súbory Nextcloud sa zachovajú.", "Redmine": "Redmine", "Refresh APT index and verify repositories:": "Obnovte APT index a overte repozitáre:", "Refresh catalog": "Aktualizovať katalóg", @@ -7995,6 +7999,7 @@ "Use a privileged LXC for NFS server/client workflows.": "Pre NFS server/klient používajte privilegovaný LXC.", "Use a privileged LXC for Samba client/server workflows.": "Pre Samba klient/server používajte privilegovaný LXC.", "Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Použite názov hostiteľa registra, napríklad ghcr.io alebo registry.example.com:5000.", + "Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Použite reverzný proxy server HTTPS s dôveryhodným certifikátom. Nextcloud aktualizujte vždy na nasledujúcu hlavnú verziu, žiadnu nepreskakujte.", "Use an existing SSH private key file on this host": "Použiť existujúci súbor súkromného SSH kľúča na tomto hostovi", "Use an existing keyfile": "Použiť existujúci keyfile", "Use an image reference, for example ghcr.io/owner/app:latest.": "Použite odkaz na obraz, napríklad ghcr.io/owner/app:latest.", @@ -8008,6 +8013,7 @@ "Use existing filesystem": "Použiť existujúci súborový systém", "Use existing: mount without formatting": "Použiť existujúci: pripojiť bez formátovania", "Use images only if the directory is on suitable storage.": "Typ images používajte iba vtedy, ak je priečinok na vhodnom úložisku.", + "Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Pre /config a MariaDB použite spravované úložisko. Pre /data môžete vybrať adresár hostiteľa/NAS, ktorý vyžaduje samostatné zálohovanie.", "Use mp1/mp2/... for extra mount points.": "Pre ďalšie mount pointy použite mp1/mp2/...", "Use only when unprivileged containers cannot meet your needs": "Použite iba vtedy, keď neprivilegované kontajnery nestačia vašim potrebám", "Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Použite možnosť 1 na pridanie lokálneho disku (ako úložisko Proxmoxu a/alebo ako mount na hostovi).", diff --git a/lang/sv.json b/lang/sv.json index 4d8c8aed..f62d3bcf 100644 --- a/lang/sv.json +++ b/lang/sv.json @@ -1644,6 +1644,7 @@ "Create scheduled backup job": "Skapa schemalagt säkerhetskopieringsjobb", "Create share directory:": "Skapa delningskatalog:", "Create shared directory:": "Skapa delad katalog:", + "ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux genererar administratörslösenordet och visar det i slutet av installationen. Ändra det efter första inloggningen.", "Create this LXC in privileged mode?": "Skapa denna LXC i privilegierat läge?", "Create with create_user in the container console": "Skapa användaren med create_user i containerns konsol", "Create, send and sign documents with a self-hosted web app.": "Skapa, skicka och signera dokument med en webbapp som du driftar själv.", @@ -3904,6 +3905,7 @@ "Linux/Mac path:": "Linux/Mac sökväg:", "LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin med valfri GPU genomgång", "LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requires en användare, databas och lösenord", + "LinuxServer Nextcloud with MariaDB and Redis": "LinuxServer Nextcloud med MariaDB och Redis", "List Available Disks": "Lista tillgängliga diskar", "List IOMMU group mapping": "Lista IOMMU-gruppkartläggning", "List NVMe devices": "Lista NVMe-enheter", @@ -4484,6 +4486,7 @@ "Next Step Required": "Nästa steg krävs", "Next Steps:": "Nästa steg:", "Next step: stop that VM first, then run": "Nästa steg: stoppa den virtuella datorn först och kör sedan", + "Nextcloud Web UI": "Nextclouds webbgränssnitt", "Nextcloud configuration cancelled": "Nextcloud konfiguration annullerad", "Nextcloud gives you access to all your files wherever you are.": "Nextcloud ger dig tillgång till alla dina filer var du än är.", "Nextcloud volume size in GB": "Nextcloud volymstorlek i GB", @@ -5605,6 +5608,7 @@ "Recreation prepared": "Rekreation förberedd", "Recursive DNS resolver.": "Rekursiv DNS-resolver.", "Recursive and authoritative DNS server.": "Rekursiv och auktoritativ DNS-server.", + "Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Fillåsning med Redis konfigureras automatiskt. Befintliga konfigurationsfiler för Nextcloud bevaras.", "Redmine": "Redmine", "Refresh APT index and verify repositories:": "Uppdatera APT-index och verifiera förråd:", "Refresh catalog": "Uppdatera katalogen", @@ -7995,6 +7999,7 @@ "Use a privileged LXC for NFS server/client workflows.": "Använd en privilegierad LXC för NFS-server/klient-arbetsflöden.", "Use a privileged LXC for Samba client/server workflows.": "Använd en privilegierad LXC för Samba klient/server arbetsflöden.", "Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Använd ett registervärdnamn, till exempel ghcr.io eller registry.example.com:5000.", + "Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Använd en omvänd HTTPS-proxy med ett betrott certifikat. Uppgradera Nextcloud till nästa huvudversion utan att hoppa över någon.", "Use an existing SSH private key file on this host": "Använd en befintlig privat SSH-nyckelfil på denna värd", "Use an existing keyfile": "Använd en befintlig nyckelfil", "Use an image reference, for example ghcr.io/owner/app:latest.": "Använd en bildreferens, till exempel ghcr.io/owner/app:latest.", @@ -8008,6 +8013,7 @@ "Use existing filesystem": "Använd befintligt filsystem", "Use existing: mount without formatting": "Använd befintlig: montera utan formatering", "Use images only if the directory is on suitable storage.": "Använd endast bilder om katalogen finns på lämplig lagring.", + "Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Använd hanterad lagring för /config och MariaDB. För /data kan du välja en katalog på värden/NAS som behöver säkerhetskopieras separat.", "Use mp1/mp2/... for extra mount points.": "Använd mp1/mp2/... för extra monteringspunkter.", "Use only when unprivileged containers cannot meet your needs": "Använd endast när oprivilegierade behållare inte kan uppfylla dina behov", "Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Använd alternativ 1 för att lägga till en lokal disk (som Proxmox-lagring och/eller som värdmontering).", diff --git a/oci/VALIDATION.md b/oci/VALIDATION.md index ad2a6f97..c49f0f21 100644 --- a/oci/VALIDATION.md +++ b/oci/VALIDATION.md @@ -2,7 +2,7 @@ -52 of 554 applications in the OCI catalog have been tested for real: 49 in the ProxMenux lab and 3 by the community. The OCI installer shows them as verified, with a ✓ in the lists. +52 of 555 applications in the OCI catalog have been tested for real: 49 in the ProxMenux lab and 3 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/nextcloud-mariadb.json b/oci/catalog/apps/nextcloud-mariadb.json new file mode 100644 index 00000000..4593927a --- /dev/null +++ b/oci/catalog/apps/nextcloud-mariadb.json @@ -0,0 +1,720 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-nextcloud-mariadb", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Nextcloud MariaDB" + }, + "tagline": { + "en_US": "LinuxServer Nextcloud with MariaDB and Redis" + }, + "description": { + "en_US": "LinuxServer Nextcloud, MariaDB 10.11 and Redis 7 in three native OCI LXC containers. /config and /data are separate; user files can use a host/NAS directory while database state stays in local managed storage." + }, + "category": "productivity", + "category_label": "Productivity & Workflows", + "author": "LinuxServer.io", + "developer": "Nextcloud", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/nextcloud.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "https", + "port": 443, + "path": "/" + }, + "website": "https://nextcloud.com/", + "documentation": "https://docs.linuxserver.io/images/docker-nextcloud/", + "repository": "https://github.com/linuxserver/docker-nextcloud", + "tips": [ + "ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.", + "Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.", + "Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.", + "Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "linuxserver", + "repository": "https://github.com/linuxserver/docker-nextcloud", + "revision": "bde257b20aa3ea653bf6900d22356c15cede5cc8", + "image_repository_url": "https://github.com/linuxserver/docker-nextcloud/pkgs/container/nextcloud", + "readme_pushed_at": "", + "compose_sha256": "1edca1fd2290a583ab28748343f8313bf0cf4e8806e534604c1f1ace41cc1539", + "generated_at": "2026-11-03T22:32:36+00:00" + }, + "container_contract": { + "service_name": "nextcloud", + "container_name": "nextcloud", + "image": { + "reference": "lscr.io/linuxserver/nextcloud:latest", + "registry": "lscr.io", + "repository": "lscr.io/linuxserver/nextcloud", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-written-reference-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "MYSQL_DATABASE", + "example": "nextcloud", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "MYSQL_HOST", + "example": "db", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "MYSQL_PASSWORD", + "example": "${GENERATED_GENERATED_DB_PASSWORD}", + "required": true, + "sensitive": true, + "source": "docker-compose" + }, + { + "name": "MYSQL_USER", + "example": "nextcloud", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "NEXTCLOUD_ADMIN_PASSWORD", + "example": "${GENERATED_ADMIN_PASSWORD}", + "required": true, + "sensitive": true, + "source": "docker-compose" + }, + { + "name": "PGID", + "example": "${PGID}", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "PUID", + "example": "${PUID}", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "TZ", + "example": "${TZ}", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/config", + "compose_source_example": "config", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 8 + } + }, + { + "id": "volume-1", + "container_path": "/data", + "compose_source_example": "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": 443, + "published_example": 443, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [ + { + "name": "db", + "image": "mariadb:10.11" + }, + { + "name": "redis", + "image": "redis:7-alpine" + } + ], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "name: nextcloud\nservices:\n db:\n environment:\n MYSQL_DATABASE: nextcloud\n MYSQL_PASSWORD: ${GENERATED_DB_PASSWORD}\n MYSQL_ROOT_PASSWORD: ${GENERATED_DB_ROOT_PASSWORD}\n MYSQL_USER: nextcloud\n TZ: ${TZ}\n image: mariadb:10.11\n restart: unless-stopped\n volumes:\n - read_only: false\n source: database\n target: /var/lib/mysql\n mem_limit: 1g\n healthcheck:\n test:\n - CMD\n - healthcheck.sh\n - --connect\n - --innodb_initialized\n interval: 10s\n timeout: 5s\n retries: 30\n nextcloud:\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n entrypoint:\n - /bin/sh\n - -ec\n - umask 077; printf %s PD9waHAKLy8gUHJlcGFyZSBhIGZyZXNoIExpbnV4U2VydmVyIE5leHRjbG91ZCB3aXRob3V0IHJlcGxhY2luZyBwZXJzaXN0ZW50IHVzZXIgc2V0dGluZ3MuCiRkaXIgPSAnL2NvbmZpZy93d3cvbmV4dGNsb3VkL2NvbmZpZyc7CmlmICghaXNfZGlyKCRkaXIpICYmICFta2RpcigkZGlyLCAwNzcwLCB0cnVlKSkgeyB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbignQ2Fubm90IGNyZWF0ZSB0aGUgTmV4dGNsb3VkIGNvbmZpZyBkaXJlY3RvcnknKTsgfQppZiAoIWlzX2ZpbGUoJGRpciAuICcvY29uZmlnLnBocCcpICYmICFpc19maWxlKCRkaXIgLiAnL2F1dG9jb25maWcucGhwJykpIHsKICAgIGZvcmVhY2ggKFsnTVlTUUxfSE9TVCcsICdNWVNRTF9EQVRBQkFTRScsICdNWVNRTF9VU0VSJywgJ01ZU1FMX1BBU1NXT1JEJ10gYXMgJG5hbWUpIHsKICAgICAgICBpZiAoZ2V0ZW52KCRuYW1lKSA9PT0gZmFsc2UgfHwgZ2V0ZW52KCRuYW1lKSA9PT0gJycpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ01pc3NpbmcgTmV4dGNsb3VkIGRhdGFiYXNlIHNldHRpbmc6ICcgLiAkbmFtZSk7IH0KICAgIH0KICAgIC8vIEtlZXAgdGhlIGRlZmF1bHRzIHRoYXQgTGludXhTZXJ2ZXIgY29waWVzIG9ubHkgaW50byBhbiBlbXB0eSBjb25maWcgZGlyZWN0b3J5LgogICAgJGRlZmF1bHRzID0gJy9hcHAvd3d3L3NyYy9jb25maWcnOwogICAgaWYgKGlzX2RpcigkZGVmYXVsdHMpKSB7CiAgICAgICAgZm9yZWFjaCAobmV3IERpcmVjdG9yeUl0ZXJhdG9yKCRkZWZhdWx0cykgYXMgJGZpbGUpIHsKICAgICAgICAgICAgaWYgKCRmaWxlLT5pc0RvdCgpIHx8ICEkZmlsZS0+aXNGaWxlKCkpIHsgY29udGludWU7IH0KICAgICAgICAgICAgJHRhcmdldCA9ICRkaXIgLiAnLycgLiAkZmlsZS0+Z2V0RmlsZW5hbWUoKTsKICAgICAgICAgICAgaWYgKCFmaWxlX2V4aXN0cygkdGFyZ2V0KSAmJiAhY29weSgkZmlsZS0+Z2V0UGF0aG5hbWUoKSwgJHRhcmdldCkpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ0Nhbm5vdCBzZWVkIHRoZSBOZXh0Y2xvdWQgY29uZmlndXJhdGlvbicpOyB9CiAgICAgICAgfQogICAgfQogICAgJHNldHRpbmdzID0gWydkYnR5cGUnID0+ICdteXNxbCcsICdkYmhvc3QnID0+IGdldGVudignTVlTUUxfSE9TVCcpLCAnZGJuYW1lJyA9PiBnZXRlbnYoJ01ZU1FMX0RBVEFCQVNFJyksICdkYnVzZXInID0+IGdldGVudignTVlTUUxfVVNFUicpLCAnZGJwYXNzJyA9PiBnZXRlbnYoJ01ZU1FMX1BBU1NXT1JEJyksICdkaXJlY3RvcnknID0+ICcvZGF0YSddOwogICAgJHBhdGggPSAkZGlyIC4gJy9hdXRvY29uZmlnLnBocCc7CiAgICBpZiAoZmlsZV9wdXRfY29udGVudHMoJHBhdGgsICI8P3BocFxuXCRBVVRPQ09ORklHID0gIiAuIHZhcl9leHBvcnQoJHNldHRpbmdzLCB0cnVlKSAuICI7XG4iLCBMT0NLX0VYKSA9PT0gZmFsc2UpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ0Nhbm5vdCB3cml0ZSB0aGUgTmV4dGNsb3VkIGRhdGFiYXNlIGNvbmZpZ3VyYXRpb24nKTsgfQogICAgY2htb2QoJHBhdGgsIDA2MDApOwogICAgLy8gRXhpc3RpbmcgaW5zdGFsbGF0aW9ucyBza2lwIExpbnV4U2VydmVyJ3MgZmlyc3QtcnVuIG93bmVyc2hpcCBzZXR1cC4KICAgIGlmICghY2hvd24oJHBhdGgsIGZpbGVvd25lcigkZGlyKSkgfHwgIWNoZ3JwKCRwYXRoLCBmaWxlZ3JvdXAoJGRpcikpKSB7IHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCdDYW5ub3Qgc2V0IE5leHRjbG91ZCBjb25maWd1cmF0aW9uIG93bmVyc2hpcCcpOyB9Cn0KJHBhdGggPSAkZGlyIC4gJy9wcm94bWVudXgtcmVkaXMuY29uZmlnLnBocCc7Ci8vIEluc3RhbGxlZCBpbnN0YW5jZXMga2VlcCB0aGVpciBleGlzdGluZyBjYWNoZSBjb25maWd1cmF0aW9uIHVuY2hhbmdlZC4KaWYgKCFpc19maWxlKCRwYXRoKSAmJiAhaXNfZmlsZSgkZGlyIC4gJy9jb25maWcucGhwJykpIHsKICAgICRzZXR0aW5ncyA9IFsnZmlsZWxvY2tpbmcuZW5hYmxlZCcgPT4gdHJ1ZSwgJ21lbWNhY2hlLmxvY2FsJyA9PiAnXE9DXE1lbWNhY2hlXEFQQ3UnLCAnbWVtY2FjaGUubG9ja2luZycgPT4gJ1xPQ1xNZW1jYWNoZVxSZWRpcycsICdyZWRpcycgPT4gWydob3N0JyA9PiAncmVkaXMnLCAncG9ydCcgPT4gNjM3OSwgJ3RpbWVvdXQnID0+IDAuMF1dOwogICAgaWYgKGZpbGVfcHV0X2NvbnRlbnRzKCRwYXRoLCAiPD9waHBcblwkQ09ORklHID0gIiAuIHZhcl9leHBvcnQoJHNldHRpbmdzLCB0cnVlKSAuICI7XG4iLCBMT0NLX0VYKSA9PT0gZmFsc2UpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ0Nhbm5vdCB3cml0ZSB0aGUgTmV4dGNsb3VkIFJlZGlzIGNvbmZpZ3VyYXRpb24nKTsgfQogICAgY2htb2QoJHBhdGgsIDA2MDApOwogICAgLy8gRXhpc3RpbmcgaW5zdGFsbGF0aW9ucyBza2lwIExpbnV4U2VydmVyJ3MgZmlyc3QtcnVuIG93bmVyc2hpcCBzZXR1cC4KICAgIGlmICghY2hvd24oJHBhdGgsIGZpbGVvd25lcigkZGlyKSkgfHwgIWNoZ3JwKCRwYXRoLCBmaWxlZ3JvdXAoJGRpcikpKSB7IHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCdDYW5ub3Qgc2V0IE5leHRjbG91ZCBjb25maWd1cmF0aW9uIG93bmVyc2hpcCcpOyB9Cn0K\n | base64 -d | php; exec /init\n environment:\n MYSQL_DATABASE: nextcloud\n MYSQL_HOST: db\n MYSQL_PASSWORD: ${GENERATED_DB_PASSWORD}\n MYSQL_USER: nextcloud\n PGID: ${PGID}\n PUID: ${PUID}\n TZ: ${TZ}\n image: lscr.io/linuxserver/nextcloud:latest\n ports:\n - 443:443\n restart: unless-stopped\n volumes:\n - read_only: false\n source: config\n target: /config\n - read_only: false\n source: data\n target: /data\n mem_limit: 2g\n redis:\n image: redis:7-alpine\n restart: unless-stopped\n volumes:\n - read_only: false\n source: redis\n target: /data\n mem_limit: 512m\n healthcheck:\n test:\n - CMD\n - redis-cli\n - ping\n interval: 10s\n timeout: 5s\n retries: 30\nvolumes:\n config: {}\n data: {}\n database: {}\n redis: {}\n" + }, + "compose_stack": { + "project_name": "nextcloud", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "nextcloud", + "service_count": 3, + "services": [ + { + "name": "db", + "image": "mariadb:10.11", + "is_main": false, + "role": "dependency", + "vmid_offset": 1, + "depends_on": [], + "frontend_network": false, + "private_network": true, + "compose": { + "environment": { + "MYSQL_DATABASE": "nextcloud", + "MYSQL_USER": "nextcloud", + "MYSQL_PASSWORD": "${GENERATED_DB_PASSWORD}", + "MYSQL_ROOT_PASSWORD": "${GENERATED_DB_ROOT_PASSWORD}", + "TZ": "${TZ}" + }, + "image": "mariadb:10.11", + "restart": "unless-stopped", + "volumes": [ + { + "source": "database", + "target": "/var/lib/mysql", + "read_only": false + } + ], + "mem_limit": "1g", + "healthcheck": { + "test": [ + "CMD", + "healthcheck.sh", + "--connect", + "--innodb_initialized" + ], + "interval": "10s", + "timeout": "5s", + "retries": 30 + } + } + }, + { + "name": "redis", + "image": "redis:7-alpine", + "is_main": false, + "role": "dependency", + "vmid_offset": 2, + "depends_on": [], + "frontend_network": false, + "private_network": true, + "compose": { + "image": "redis:7-alpine", + "restart": "unless-stopped", + "volumes": [ + { + "source": "redis", + "target": "/data", + "read_only": false + } + ], + "mem_limit": "512m", + "healthcheck": { + "test": [ + "CMD", + "redis-cli", + "ping" + ], + "interval": "10s", + "timeout": "5s", + "retries": 30 + } + } + }, + { + "name": "nextcloud", + "image": "lscr.io/linuxserver/nextcloud:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [ + "db", + "redis" + ], + "frontend_network": true, + "private_network": true, + "compose": { + "depends_on": { + "db": { + "condition": "service_healthy" + }, + "redis": { + "condition": "service_healthy" + } + }, + "entrypoint": [ + "/bin/sh", + "-ec", + "(umask 077; printf %s PD9waHAKLy8gUHJlcGFyZSBhIGZyZXNoIExpbnV4U2VydmVyIE5leHRjbG91ZCB3aXRob3V0IHJlcGxhY2luZyBwZXJzaXN0ZW50IHVzZXIgc2V0dGluZ3MuCiRkaXIgPSAnL2NvbmZpZy93d3cvbmV4dGNsb3VkL2NvbmZpZyc7CnVtYXNrKDAwNzcpOwppZiAoIWlzX2RpcigkZGlyKSAmJiAhbWtkaXIoJGRpciwgMDc3MCwgdHJ1ZSkpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ0Nhbm5vdCBjcmVhdGUgdGhlIE5leHRjbG91ZCBjb25maWcgZGlyZWN0b3J5Jyk7IH0KLy8gVGhlIGRpcmVjdG9yeSBiZWxvbmdzIHRvIHRoZSBhcHBsaWNhdGlvbiB1c2VyLiBDcmVhdGUgZWFjaCBmaWxlIHdpdGhvdXQKLy8gZm9sbG93aW5nIGEgbGluayBwbGFjZWQgdGhlcmUsIGFuZCBnaXZlIGl0IHRvIHRoYXQgdXNlciB3aXRob3V0IGZvbGxvd2luZyBvbmUuCmZ1bmN0aW9uIGNyZWF0ZV9wcml2YXRlKCRwYXRoLCAkY29udGVudCwgJG93bmVyKSB7CiAgICAkaGFuZGxlID0gQGZvcGVuKCRwYXRoLCAneCcpOwogICAgaWYgKCRoYW5kbGUgPT09IGZhbHNlIHx8IGZ3cml0ZSgkaGFuZGxlLCAkY29udGVudCkgIT09IHN0cmxlbigkY29udGVudCkgfHwgIWZjbG9zZSgkaGFuZGxlKSkgeyB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbignQ2Fubm90IHdyaXRlICcgLiBiYXNlbmFtZSgkcGF0aCkpOyB9CiAgICBpZiAoJG93bmVyICYmICghbGNob3duKCRwYXRoLCBmaWxlb3duZXIoJG93bmVyKSkgfHwgIWxjaGdycCgkcGF0aCwgZmlsZWdyb3VwKCRvd25lcikpKSkgeyB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbignQ2Fubm90IHNldCBOZXh0Y2xvdWQgY29uZmlndXJhdGlvbiBvd25lcnNoaXAnKTsgfQp9CmlmICghaXNfZmlsZSgkZGlyIC4gJy9jb25maWcucGhwJykgJiYgIWlzX2ZpbGUoJGRpciAuICcvYXV0b2NvbmZpZy5waHAnKSkgewogICAgZm9yZWFjaCAoWydNWVNRTF9IT1NUJywgJ01ZU1FMX0RBVEFCQVNFJywgJ01ZU1FMX1VTRVInLCAnTVlTUUxfUEFTU1dPUkQnLCAnTkVYVENMT1VEX0FETUlOX1BBU1NXT1JEJ10gYXMgJG5hbWUpIHsKICAgICAgICBpZiAoZ2V0ZW52KCRuYW1lKSA9PT0gZmFsc2UgfHwgZ2V0ZW52KCRuYW1lKSA9PT0gJycpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ01pc3NpbmcgTmV4dGNsb3VkIHNldHRpbmc6ICcgLiAkbmFtZSk7IH0KICAgIH0KICAgIC8vIEtlZXAgdGhlIGRlZmF1bHRzIHRoYXQgTGludXhTZXJ2ZXIgY29waWVzIG9ubHkgaW50byBhbiBlbXB0eSBjb25maWcgZGlyZWN0b3J5LgogICAgJGRlZmF1bHRzID0gJy9hcHAvd3d3L3NyYy9jb25maWcnOwogICAgaWYgKGlzX2RpcigkZGVmYXVsdHMpKSB7CiAgICAgICAgZm9yZWFjaCAobmV3IERpcmVjdG9yeUl0ZXJhdG9yKCRkZWZhdWx0cykgYXMgJGZpbGUpIHsKICAgICAgICAgICAgaWYgKCRmaWxlLT5pc0RvdCgpIHx8ICEkZmlsZS0+aXNGaWxlKCkpIHsgY29udGludWU7IH0KICAgICAgICAgICAgJHRhcmdldCA9ICRkaXIgLiAnLycgLiAkZmlsZS0+Z2V0RmlsZW5hbWUoKTsKICAgICAgICAgICAgaWYgKCFmaWxlX2V4aXN0cygkdGFyZ2V0KSAmJiAhaXNfbGluaygkdGFyZ2V0KSkgeyBjcmVhdGVfcHJpdmF0ZSgkdGFyZ2V0LCBmaWxlX2dldF9jb250ZW50cygkZmlsZS0+Z2V0UGF0aG5hbWUoKSksIG51bGwpOyB9CiAgICAgICAgfQogICAgfQogICAgLy8gV2l0aCB0aGUgYWRtaW5pc3RyYXRvciBpbmNsdWRlZCwgTmV4dGNsb3VkIGluc3RhbGxzIGl0c2VsZiBvbiB0aGUgZmlyc3QKICAgIC8vIHJlcXVlc3QsIHNvIG5vYm9keSBlbHNlIG9uIHRoZSBuZXR3b3JrIGNhbiBjbGFpbSB0aGUgc2V0dXAgcGFnZS4KICAgICRzZXR0aW5ncyA9IFsnZGJ0eXBlJyA9PiAnbXlzcWwnLCAnZGJob3N0JyA9PiBnZXRlbnYoJ01ZU1FMX0hPU1QnKSwgJ2RibmFtZScgPT4gZ2V0ZW52KCdNWVNRTF9EQVRBQkFTRScpLCAnZGJ1c2VyJyA9PiBnZXRlbnYoJ01ZU1FMX1VTRVInKSwgJ2RicGFzcycgPT4gZ2V0ZW52KCdNWVNRTF9QQVNTV09SRCcpLCAnZGlyZWN0b3J5JyA9PiAnL2RhdGEnLCAnYWRtaW5sb2dpbicgPT4gJ2FkbWluJywgJ2FkbWlucGFzcycgPT4gZ2V0ZW52KCdORVhUQ0xPVURfQURNSU5fUEFTU1dPUkQnKV07CiAgICAvLyBFeGlzdGluZyBpbnN0YWxsYXRpb25zIHNraXAgTGludXhTZXJ2ZXIncyBmaXJzdC1ydW4gb3duZXJzaGlwIHNldHVwLgogICAgY3JlYXRlX3ByaXZhdGUoJGRpciAuICcvYXV0b2NvbmZpZy5waHAnLCAiPD9waHBcblwkQVVUT0NPTkZJRyA9ICIgLiB2YXJfZXhwb3J0KCRzZXR0aW5ncywgdHJ1ZSkgLiAiO1xuIiwgJGRpcik7Cn0KJHBhdGggPSAkZGlyIC4gJy9wcm94bWVudXgtcmVkaXMuY29uZmlnLnBocCc7Ci8vIEluc3RhbGxlZCBpbnN0YW5jZXMga2VlcCB0aGVpciBleGlzdGluZyBjYWNoZSBjb25maWd1cmF0aW9uIHVuY2hhbmdlZC4KaWYgKCFpc19maWxlKCRwYXRoKSAmJiAhaXNfbGluaygkcGF0aCkgJiYgIWlzX2ZpbGUoJGRpciAuICcvY29uZmlnLnBocCcpKSB7CiAgICAkc2V0dGluZ3MgPSBbJ2ZpbGVsb2NraW5nLmVuYWJsZWQnID0+IHRydWUsICdtZW1jYWNoZS5sb2NhbCcgPT4gJ1xPQ1xNZW1jYWNoZVxBUEN1JywgJ21lbWNhY2hlLmxvY2tpbmcnID0+ICdcT0NcTWVtY2FjaGVcUmVkaXMnLCAncmVkaXMnID0+IFsnaG9zdCcgPT4gJ3JlZGlzJywgJ3BvcnQnID0+IDYzNzksICd0aW1lb3V0JyA9PiAwLjBdXTsKICAgIGNyZWF0ZV9wcml2YXRlKCRwYXRoLCAiPD9waHBcblwkQ09ORklHID0gIiAuIHZhcl9leHBvcnQoJHNldHRpbmdzLCB0cnVlKSAuICI7XG4iLCAkZGlyKTsKfQo= | base64 -d | php); exec /init" + ], + "environment": { + "PUID": "${PUID}", + "PGID": "${PGID}", + "TZ": "${TZ}", + "MYSQL_HOST": "db", + "MYSQL_DATABASE": "nextcloud", + "MYSQL_USER": "nextcloud", + "MYSQL_PASSWORD": "${GENERATED_DB_PASSWORD}", + "NEXTCLOUD_ADMIN_PASSWORD": "${GENERATED_ADMIN_PASSWORD}" + }, + "image": "lscr.io/linuxserver/nextcloud:latest", + "ports": [ + "443:443" + ], + "restart": "unless-stopped", + "volumes": [ + { + "source": "config", + "target": "/config", + "read_only": false + }, + { + "source": "data", + "target": "/data", + "read_only": false + } + ], + "mem_limit": "2g" + } + } + ], + "top_level": { + "name": "nextcloud", + "volumes": { + "config": {}, + "data": {}, + "database": {}, + "redis": {} + } + }, + "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": "db-volume-0", + "service": "db", + "container_path": "/var/lib/mysql", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "nextcloud-volume-0", + "service": "nextcloud", + "container_path": "/config", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "nextcloud-volume-1", + "service": "nextcloud", + "container_path": "/data", + "mode": "user-selectable", + "user_selectable": true, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "redis-volume-0", + "service": "redis", + "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": 3, + "start_order": [ + "db", + "redis", + "nextcloud" + ], + "stop_order": [ + "nextcloud", + "redis", + "db" + ], + "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": "nextcloud", + "environment_variable": "NEXTCLOUD_ADMIN_PASSWORD" + } + ] + }, + { + "id": "generated-db-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "db", + "environment_variable": "MYSQL_PASSWORD" + }, + { + "service": "nextcloud", + "environment_variable": "MYSQL_PASSWORD" + } + ] + }, + { + "id": "generated-db-root-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "db", + "environment_variable": "MYSQL_ROOT_PASSWORD" + } + ] + } + ] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Nextcloud Web UI", + "scheme": "https", + "port": 443, + "path": "/", + "source": "linuxserver-nextcloud-documentation" + } + ], + "credentials": [ + { + "label": "Generated administrator login", + "type": "runtime-generated", + "username": "admin", + "password": null, + "password_environment": "NEXTCLOUD_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": 2048, + "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": 30 + }, + "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" + }, + "installer_profile": { + "stack_driver": "generic-multi-lxc-stack", + "volume_preparations": [ + { + "container_path": "/config", + "owner_strategy": "mapped-root", + "remove_lost_found": true, + "only_when_mount_type": "managed-volume" + }, + { + "container_path": "/data", + "owner_strategy": "mapped-application-user", + "remove_lost_found": true + } + ] + }, + "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": "pending-per-application" + }, + { + "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" + } + ] + }, + "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", + "stop_signal", + "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": "passed-at-generation", + "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, + "dependency_lifecycle": { + "implementation": "proxmox-hookscript", + "trigger": "main-lxc-pre-start", + "waits_for_dependency_healthchecks": true, + "stops_dependencies_with_main": false + } + } +} diff --git a/oci/catalog/curated/nextcloud-mariadb.json b/oci/catalog/curated/nextcloud-mariadb.json new file mode 100644 index 00000000..4593927a --- /dev/null +++ b/oci/catalog/curated/nextcloud-mariadb.json @@ -0,0 +1,720 @@ +{ + "schema_version": "0.5.0", + "kind": "proxmenux.oci-template", + "id": "image-nextcloud-mariadb", + "status": "generated-unvalidated", + "catalog_ui": { + "title": { + "en_US": "Nextcloud MariaDB" + }, + "tagline": { + "en_US": "LinuxServer Nextcloud with MariaDB and Redis" + }, + "description": { + "en_US": "LinuxServer Nextcloud, MariaDB 10.11 and Redis 7 in three native OCI LXC containers. /config and /data are separate; user files can use a host/NAS directory while database state stays in local managed storage." + }, + "category": "productivity", + "category_label": "Productivity & Workflows", + "author": "LinuxServer.io", + "developer": "Nextcloud", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/nextcloud.webp", + "thumbnail": null, + "screenshots": [], + "architectures": [ + "amd64", + "arm64" + ], + "launch": { + "scheme": "https", + "port": 443, + "path": "/" + }, + "website": "https://nextcloud.com/", + "documentation": "https://docs.linuxserver.io/images/docker-nextcloud/", + "repository": "https://github.com/linuxserver/docker-nextcloud", + "tips": [ + "ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.", + "Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.", + "Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.", + "Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time." + ], + "mini_changelog": [], + "display_version": null, + "updated_at": null + }, + "source": { + "provider": "linuxserver", + "repository": "https://github.com/linuxserver/docker-nextcloud", + "revision": "bde257b20aa3ea653bf6900d22356c15cede5cc8", + "image_repository_url": "https://github.com/linuxserver/docker-nextcloud/pkgs/container/nextcloud", + "readme_pushed_at": "", + "compose_sha256": "1edca1fd2290a583ab28748343f8313bf0cf4e8806e534604c1f1ace41cc1539", + "generated_at": "2026-11-03T22:32:36+00:00" + }, + "container_contract": { + "service_name": "nextcloud", + "container_name": "nextcloud", + "image": { + "reference": "lscr.io/linuxserver/nextcloud:latest", + "registry": "lscr.io", + "repository": "lscr.io/linuxserver/nextcloud", + "tag": "latest", + "digest": null, + "pull_policy": "resolve-written-reference-to-architecture-digest-at-install" + }, + "environment": [ + { + "name": "MYSQL_DATABASE", + "example": "nextcloud", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "MYSQL_HOST", + "example": "db", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "MYSQL_PASSWORD", + "example": "${GENERATED_GENERATED_DB_PASSWORD}", + "required": true, + "sensitive": true, + "source": "docker-compose" + }, + { + "name": "MYSQL_USER", + "example": "nextcloud", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "NEXTCLOUD_ADMIN_PASSWORD", + "example": "${GENERATED_ADMIN_PASSWORD}", + "required": true, + "sensitive": true, + "source": "docker-compose" + }, + { + "name": "PGID", + "example": "${PGID}", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "PUID", + "example": "${PUID}", + "required": true, + "sensitive": false, + "source": "docker-compose" + }, + { + "name": "TZ", + "example": "${TZ}", + "required": true, + "sensitive": false, + "source": "docker-compose" + } + ], + "volumes": [ + { + "id": "volume-0", + "container_path": "/config", + "compose_source_example": "config", + "read_only": false, + "required": true, + "installation_choice": [ + "managed-volume" + ], + "default": "managed-volume", + "managed_volume": { + "backup": true, + "default_size_gb": 8 + } + }, + { + "id": "volume-1", + "container_path": "/data", + "compose_source_example": "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": 443, + "published_example": 443, + "protocol": "tcp", + "required": true, + "proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat" + } + ], + "related_services": [ + { + "name": "db", + "image": "mariadb:10.11" + }, + { + "name": "redis", + "image": "redis:7-alpine" + } + ], + "restart": "unless-stopped", + "stop_grace_period": null, + "original_compose": "name: nextcloud\nservices:\n db:\n environment:\n MYSQL_DATABASE: nextcloud\n MYSQL_PASSWORD: ${GENERATED_DB_PASSWORD}\n MYSQL_ROOT_PASSWORD: ${GENERATED_DB_ROOT_PASSWORD}\n MYSQL_USER: nextcloud\n TZ: ${TZ}\n image: mariadb:10.11\n restart: unless-stopped\n volumes:\n - read_only: false\n source: database\n target: /var/lib/mysql\n mem_limit: 1g\n healthcheck:\n test:\n - CMD\n - healthcheck.sh\n - --connect\n - --innodb_initialized\n interval: 10s\n timeout: 5s\n retries: 30\n nextcloud:\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n entrypoint:\n - /bin/sh\n - -ec\n - umask 077; printf %s PD9waHAKLy8gUHJlcGFyZSBhIGZyZXNoIExpbnV4U2VydmVyIE5leHRjbG91ZCB3aXRob3V0IHJlcGxhY2luZyBwZXJzaXN0ZW50IHVzZXIgc2V0dGluZ3MuCiRkaXIgPSAnL2NvbmZpZy93d3cvbmV4dGNsb3VkL2NvbmZpZyc7CmlmICghaXNfZGlyKCRkaXIpICYmICFta2RpcigkZGlyLCAwNzcwLCB0cnVlKSkgeyB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbignQ2Fubm90IGNyZWF0ZSB0aGUgTmV4dGNsb3VkIGNvbmZpZyBkaXJlY3RvcnknKTsgfQppZiAoIWlzX2ZpbGUoJGRpciAuICcvY29uZmlnLnBocCcpICYmICFpc19maWxlKCRkaXIgLiAnL2F1dG9jb25maWcucGhwJykpIHsKICAgIGZvcmVhY2ggKFsnTVlTUUxfSE9TVCcsICdNWVNRTF9EQVRBQkFTRScsICdNWVNRTF9VU0VSJywgJ01ZU1FMX1BBU1NXT1JEJ10gYXMgJG5hbWUpIHsKICAgICAgICBpZiAoZ2V0ZW52KCRuYW1lKSA9PT0gZmFsc2UgfHwgZ2V0ZW52KCRuYW1lKSA9PT0gJycpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ01pc3NpbmcgTmV4dGNsb3VkIGRhdGFiYXNlIHNldHRpbmc6ICcgLiAkbmFtZSk7IH0KICAgIH0KICAgIC8vIEtlZXAgdGhlIGRlZmF1bHRzIHRoYXQgTGludXhTZXJ2ZXIgY29waWVzIG9ubHkgaW50byBhbiBlbXB0eSBjb25maWcgZGlyZWN0b3J5LgogICAgJGRlZmF1bHRzID0gJy9hcHAvd3d3L3NyYy9jb25maWcnOwogICAgaWYgKGlzX2RpcigkZGVmYXVsdHMpKSB7CiAgICAgICAgZm9yZWFjaCAobmV3IERpcmVjdG9yeUl0ZXJhdG9yKCRkZWZhdWx0cykgYXMgJGZpbGUpIHsKICAgICAgICAgICAgaWYgKCRmaWxlLT5pc0RvdCgpIHx8ICEkZmlsZS0+aXNGaWxlKCkpIHsgY29udGludWU7IH0KICAgICAgICAgICAgJHRhcmdldCA9ICRkaXIgLiAnLycgLiAkZmlsZS0+Z2V0RmlsZW5hbWUoKTsKICAgICAgICAgICAgaWYgKCFmaWxlX2V4aXN0cygkdGFyZ2V0KSAmJiAhY29weSgkZmlsZS0+Z2V0UGF0aG5hbWUoKSwgJHRhcmdldCkpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ0Nhbm5vdCBzZWVkIHRoZSBOZXh0Y2xvdWQgY29uZmlndXJhdGlvbicpOyB9CiAgICAgICAgfQogICAgfQogICAgJHNldHRpbmdzID0gWydkYnR5cGUnID0+ICdteXNxbCcsICdkYmhvc3QnID0+IGdldGVudignTVlTUUxfSE9TVCcpLCAnZGJuYW1lJyA9PiBnZXRlbnYoJ01ZU1FMX0RBVEFCQVNFJyksICdkYnVzZXInID0+IGdldGVudignTVlTUUxfVVNFUicpLCAnZGJwYXNzJyA9PiBnZXRlbnYoJ01ZU1FMX1BBU1NXT1JEJyksICdkaXJlY3RvcnknID0+ICcvZGF0YSddOwogICAgJHBhdGggPSAkZGlyIC4gJy9hdXRvY29uZmlnLnBocCc7CiAgICBpZiAoZmlsZV9wdXRfY29udGVudHMoJHBhdGgsICI8P3BocFxuXCRBVVRPQ09ORklHID0gIiAuIHZhcl9leHBvcnQoJHNldHRpbmdzLCB0cnVlKSAuICI7XG4iLCBMT0NLX0VYKSA9PT0gZmFsc2UpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ0Nhbm5vdCB3cml0ZSB0aGUgTmV4dGNsb3VkIGRhdGFiYXNlIGNvbmZpZ3VyYXRpb24nKTsgfQogICAgY2htb2QoJHBhdGgsIDA2MDApOwogICAgLy8gRXhpc3RpbmcgaW5zdGFsbGF0aW9ucyBza2lwIExpbnV4U2VydmVyJ3MgZmlyc3QtcnVuIG93bmVyc2hpcCBzZXR1cC4KICAgIGlmICghY2hvd24oJHBhdGgsIGZpbGVvd25lcigkZGlyKSkgfHwgIWNoZ3JwKCRwYXRoLCBmaWxlZ3JvdXAoJGRpcikpKSB7IHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCdDYW5ub3Qgc2V0IE5leHRjbG91ZCBjb25maWd1cmF0aW9uIG93bmVyc2hpcCcpOyB9Cn0KJHBhdGggPSAkZGlyIC4gJy9wcm94bWVudXgtcmVkaXMuY29uZmlnLnBocCc7Ci8vIEluc3RhbGxlZCBpbnN0YW5jZXMga2VlcCB0aGVpciBleGlzdGluZyBjYWNoZSBjb25maWd1cmF0aW9uIHVuY2hhbmdlZC4KaWYgKCFpc19maWxlKCRwYXRoKSAmJiAhaXNfZmlsZSgkZGlyIC4gJy9jb25maWcucGhwJykpIHsKICAgICRzZXR0aW5ncyA9IFsnZmlsZWxvY2tpbmcuZW5hYmxlZCcgPT4gdHJ1ZSwgJ21lbWNhY2hlLmxvY2FsJyA9PiAnXE9DXE1lbWNhY2hlXEFQQ3UnLCAnbWVtY2FjaGUubG9ja2luZycgPT4gJ1xPQ1xNZW1jYWNoZVxSZWRpcycsICdyZWRpcycgPT4gWydob3N0JyA9PiAncmVkaXMnLCAncG9ydCcgPT4gNjM3OSwgJ3RpbWVvdXQnID0+IDAuMF1dOwogICAgaWYgKGZpbGVfcHV0X2NvbnRlbnRzKCRwYXRoLCAiPD9waHBcblwkQ09ORklHID0gIiAuIHZhcl9leHBvcnQoJHNldHRpbmdzLCB0cnVlKSAuICI7XG4iLCBMT0NLX0VYKSA9PT0gZmFsc2UpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ0Nhbm5vdCB3cml0ZSB0aGUgTmV4dGNsb3VkIFJlZGlzIGNvbmZpZ3VyYXRpb24nKTsgfQogICAgY2htb2QoJHBhdGgsIDA2MDApOwogICAgLy8gRXhpc3RpbmcgaW5zdGFsbGF0aW9ucyBza2lwIExpbnV4U2VydmVyJ3MgZmlyc3QtcnVuIG93bmVyc2hpcCBzZXR1cC4KICAgIGlmICghY2hvd24oJHBhdGgsIGZpbGVvd25lcigkZGlyKSkgfHwgIWNoZ3JwKCRwYXRoLCBmaWxlZ3JvdXAoJGRpcikpKSB7IHRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCdDYW5ub3Qgc2V0IE5leHRjbG91ZCBjb25maWd1cmF0aW9uIG93bmVyc2hpcCcpOyB9Cn0K\n | base64 -d | php; exec /init\n environment:\n MYSQL_DATABASE: nextcloud\n MYSQL_HOST: db\n MYSQL_PASSWORD: ${GENERATED_DB_PASSWORD}\n MYSQL_USER: nextcloud\n PGID: ${PGID}\n PUID: ${PUID}\n TZ: ${TZ}\n image: lscr.io/linuxserver/nextcloud:latest\n ports:\n - 443:443\n restart: unless-stopped\n volumes:\n - read_only: false\n source: config\n target: /config\n - read_only: false\n source: data\n target: /data\n mem_limit: 2g\n redis:\n image: redis:7-alpine\n restart: unless-stopped\n volumes:\n - read_only: false\n source: redis\n target: /data\n mem_limit: 512m\n healthcheck:\n test:\n - CMD\n - redis-cli\n - ping\n interval: 10s\n timeout: 5s\n retries: 30\nvolumes:\n config: {}\n data: {}\n database: {}\n redis: {}\n" + }, + "compose_stack": { + "project_name": "nextcloud", + "deployment_model": "one-native-oci-lxc-per-compose-service", + "user_experience": "single-application-install", + "main_service": "nextcloud", + "service_count": 3, + "services": [ + { + "name": "db", + "image": "mariadb:10.11", + "is_main": false, + "role": "dependency", + "vmid_offset": 1, + "depends_on": [], + "frontend_network": false, + "private_network": true, + "compose": { + "environment": { + "MYSQL_DATABASE": "nextcloud", + "MYSQL_USER": "nextcloud", + "MYSQL_PASSWORD": "${GENERATED_DB_PASSWORD}", + "MYSQL_ROOT_PASSWORD": "${GENERATED_DB_ROOT_PASSWORD}", + "TZ": "${TZ}" + }, + "image": "mariadb:10.11", + "restart": "unless-stopped", + "volumes": [ + { + "source": "database", + "target": "/var/lib/mysql", + "read_only": false + } + ], + "mem_limit": "1g", + "healthcheck": { + "test": [ + "CMD", + "healthcheck.sh", + "--connect", + "--innodb_initialized" + ], + "interval": "10s", + "timeout": "5s", + "retries": 30 + } + } + }, + { + "name": "redis", + "image": "redis:7-alpine", + "is_main": false, + "role": "dependency", + "vmid_offset": 2, + "depends_on": [], + "frontend_network": false, + "private_network": true, + "compose": { + "image": "redis:7-alpine", + "restart": "unless-stopped", + "volumes": [ + { + "source": "redis", + "target": "/data", + "read_only": false + } + ], + "mem_limit": "512m", + "healthcheck": { + "test": [ + "CMD", + "redis-cli", + "ping" + ], + "interval": "10s", + "timeout": "5s", + "retries": 30 + } + } + }, + { + "name": "nextcloud", + "image": "lscr.io/linuxserver/nextcloud:latest", + "is_main": true, + "role": "frontend", + "vmid_offset": 0, + "depends_on": [ + "db", + "redis" + ], + "frontend_network": true, + "private_network": true, + "compose": { + "depends_on": { + "db": { + "condition": "service_healthy" + }, + "redis": { + "condition": "service_healthy" + } + }, + "entrypoint": [ + "/bin/sh", + "-ec", + "(umask 077; printf %s PD9waHAKLy8gUHJlcGFyZSBhIGZyZXNoIExpbnV4U2VydmVyIE5leHRjbG91ZCB3aXRob3V0IHJlcGxhY2luZyBwZXJzaXN0ZW50IHVzZXIgc2V0dGluZ3MuCiRkaXIgPSAnL2NvbmZpZy93d3cvbmV4dGNsb3VkL2NvbmZpZyc7CnVtYXNrKDAwNzcpOwppZiAoIWlzX2RpcigkZGlyKSAmJiAhbWtkaXIoJGRpciwgMDc3MCwgdHJ1ZSkpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ0Nhbm5vdCBjcmVhdGUgdGhlIE5leHRjbG91ZCBjb25maWcgZGlyZWN0b3J5Jyk7IH0KLy8gVGhlIGRpcmVjdG9yeSBiZWxvbmdzIHRvIHRoZSBhcHBsaWNhdGlvbiB1c2VyLiBDcmVhdGUgZWFjaCBmaWxlIHdpdGhvdXQKLy8gZm9sbG93aW5nIGEgbGluayBwbGFjZWQgdGhlcmUsIGFuZCBnaXZlIGl0IHRvIHRoYXQgdXNlciB3aXRob3V0IGZvbGxvd2luZyBvbmUuCmZ1bmN0aW9uIGNyZWF0ZV9wcml2YXRlKCRwYXRoLCAkY29udGVudCwgJG93bmVyKSB7CiAgICAkaGFuZGxlID0gQGZvcGVuKCRwYXRoLCAneCcpOwogICAgaWYgKCRoYW5kbGUgPT09IGZhbHNlIHx8IGZ3cml0ZSgkaGFuZGxlLCAkY29udGVudCkgIT09IHN0cmxlbigkY29udGVudCkgfHwgIWZjbG9zZSgkaGFuZGxlKSkgeyB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbignQ2Fubm90IHdyaXRlICcgLiBiYXNlbmFtZSgkcGF0aCkpOyB9CiAgICBpZiAoJG93bmVyICYmICghbGNob3duKCRwYXRoLCBmaWxlb3duZXIoJG93bmVyKSkgfHwgIWxjaGdycCgkcGF0aCwgZmlsZWdyb3VwKCRvd25lcikpKSkgeyB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbignQ2Fubm90IHNldCBOZXh0Y2xvdWQgY29uZmlndXJhdGlvbiBvd25lcnNoaXAnKTsgfQp9CmlmICghaXNfZmlsZSgkZGlyIC4gJy9jb25maWcucGhwJykgJiYgIWlzX2ZpbGUoJGRpciAuICcvYXV0b2NvbmZpZy5waHAnKSkgewogICAgZm9yZWFjaCAoWydNWVNRTF9IT1NUJywgJ01ZU1FMX0RBVEFCQVNFJywgJ01ZU1FMX1VTRVInLCAnTVlTUUxfUEFTU1dPUkQnLCAnTkVYVENMT1VEX0FETUlOX1BBU1NXT1JEJ10gYXMgJG5hbWUpIHsKICAgICAgICBpZiAoZ2V0ZW52KCRuYW1lKSA9PT0gZmFsc2UgfHwgZ2V0ZW52KCRuYW1lKSA9PT0gJycpIHsgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oJ01pc3NpbmcgTmV4dGNsb3VkIHNldHRpbmc6ICcgLiAkbmFtZSk7IH0KICAgIH0KICAgIC8vIEtlZXAgdGhlIGRlZmF1bHRzIHRoYXQgTGludXhTZXJ2ZXIgY29waWVzIG9ubHkgaW50byBhbiBlbXB0eSBjb25maWcgZGlyZWN0b3J5LgogICAgJGRlZmF1bHRzID0gJy9hcHAvd3d3L3NyYy9jb25maWcnOwogICAgaWYgKGlzX2RpcigkZGVmYXVsdHMpKSB7CiAgICAgICAgZm9yZWFjaCAobmV3IERpcmVjdG9yeUl0ZXJhdG9yKCRkZWZhdWx0cykgYXMgJGZpbGUpIHsKICAgICAgICAgICAgaWYgKCRmaWxlLT5pc0RvdCgpIHx8ICEkZmlsZS0+aXNGaWxlKCkpIHsgY29udGludWU7IH0KICAgICAgICAgICAgJHRhcmdldCA9ICRkaXIgLiAnLycgLiAkZmlsZS0+Z2V0RmlsZW5hbWUoKTsKICAgICAgICAgICAgaWYgKCFmaWxlX2V4aXN0cygkdGFyZ2V0KSAmJiAhaXNfbGluaygkdGFyZ2V0KSkgeyBjcmVhdGVfcHJpdmF0ZSgkdGFyZ2V0LCBmaWxlX2dldF9jb250ZW50cygkZmlsZS0+Z2V0UGF0aG5hbWUoKSksIG51bGwpOyB9CiAgICAgICAgfQogICAgfQogICAgLy8gV2l0aCB0aGUgYWRtaW5pc3RyYXRvciBpbmNsdWRlZCwgTmV4dGNsb3VkIGluc3RhbGxzIGl0c2VsZiBvbiB0aGUgZmlyc3QKICAgIC8vIHJlcXVlc3QsIHNvIG5vYm9keSBlbHNlIG9uIHRoZSBuZXR3b3JrIGNhbiBjbGFpbSB0aGUgc2V0dXAgcGFnZS4KICAgICRzZXR0aW5ncyA9IFsnZGJ0eXBlJyA9PiAnbXlzcWwnLCAnZGJob3N0JyA9PiBnZXRlbnYoJ01ZU1FMX0hPU1QnKSwgJ2RibmFtZScgPT4gZ2V0ZW52KCdNWVNRTF9EQVRBQkFTRScpLCAnZGJ1c2VyJyA9PiBnZXRlbnYoJ01ZU1FMX1VTRVInKSwgJ2RicGFzcycgPT4gZ2V0ZW52KCdNWVNRTF9QQVNTV09SRCcpLCAnZGlyZWN0b3J5JyA9PiAnL2RhdGEnLCAnYWRtaW5sb2dpbicgPT4gJ2FkbWluJywgJ2FkbWlucGFzcycgPT4gZ2V0ZW52KCdORVhUQ0xPVURfQURNSU5fUEFTU1dPUkQnKV07CiAgICAvLyBFeGlzdGluZyBpbnN0YWxsYXRpb25zIHNraXAgTGludXhTZXJ2ZXIncyBmaXJzdC1ydW4gb3duZXJzaGlwIHNldHVwLgogICAgY3JlYXRlX3ByaXZhdGUoJGRpciAuICcvYXV0b2NvbmZpZy5waHAnLCAiPD9waHBcblwkQVVUT0NPTkZJRyA9ICIgLiB2YXJfZXhwb3J0KCRzZXR0aW5ncywgdHJ1ZSkgLiAiO1xuIiwgJGRpcik7Cn0KJHBhdGggPSAkZGlyIC4gJy9wcm94bWVudXgtcmVkaXMuY29uZmlnLnBocCc7Ci8vIEluc3RhbGxlZCBpbnN0YW5jZXMga2VlcCB0aGVpciBleGlzdGluZyBjYWNoZSBjb25maWd1cmF0aW9uIHVuY2hhbmdlZC4KaWYgKCFpc19maWxlKCRwYXRoKSAmJiAhaXNfbGluaygkcGF0aCkgJiYgIWlzX2ZpbGUoJGRpciAuICcvY29uZmlnLnBocCcpKSB7CiAgICAkc2V0dGluZ3MgPSBbJ2ZpbGVsb2NraW5nLmVuYWJsZWQnID0+IHRydWUsICdtZW1jYWNoZS5sb2NhbCcgPT4gJ1xPQ1xNZW1jYWNoZVxBUEN1JywgJ21lbWNhY2hlLmxvY2tpbmcnID0+ICdcT0NcTWVtY2FjaGVcUmVkaXMnLCAncmVkaXMnID0+IFsnaG9zdCcgPT4gJ3JlZGlzJywgJ3BvcnQnID0+IDYzNzksICd0aW1lb3V0JyA9PiAwLjBdXTsKICAgIGNyZWF0ZV9wcml2YXRlKCRwYXRoLCAiPD9waHBcblwkQ09ORklHID0gIiAuIHZhcl9leHBvcnQoJHNldHRpbmdzLCB0cnVlKSAuICI7XG4iLCAkZGlyKTsKfQo= | base64 -d | php); exec /init" + ], + "environment": { + "PUID": "${PUID}", + "PGID": "${PGID}", + "TZ": "${TZ}", + "MYSQL_HOST": "db", + "MYSQL_DATABASE": "nextcloud", + "MYSQL_USER": "nextcloud", + "MYSQL_PASSWORD": "${GENERATED_DB_PASSWORD}", + "NEXTCLOUD_ADMIN_PASSWORD": "${GENERATED_ADMIN_PASSWORD}" + }, + "image": "lscr.io/linuxserver/nextcloud:latest", + "ports": [ + "443:443" + ], + "restart": "unless-stopped", + "volumes": [ + { + "source": "config", + "target": "/config", + "read_only": false + }, + { + "source": "data", + "target": "/data", + "read_only": false + } + ], + "mem_limit": "2g" + } + } + ], + "top_level": { + "name": "nextcloud", + "volumes": { + "config": {}, + "data": {}, + "database": {}, + "redis": {} + } + }, + "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": "db-volume-0", + "service": "db", + "container_path": "/var/lib/mysql", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "nextcloud-volume-0", + "service": "nextcloud", + "container_path": "/config", + "mode": "managed-volume", + "user_selectable": false, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "nextcloud-volume-1", + "service": "nextcloud", + "container_path": "/data", + "mode": "user-selectable", + "user_selectable": true, + "backup": true, + "shared_with_other_lxc": false, + "source_path": null, + "source_path_prompt": null + }, + { + "id": "redis-volume-0", + "service": "redis", + "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": 3, + "start_order": [ + "db", + "redis", + "nextcloud" + ], + "stop_order": [ + "nextcloud", + "redis", + "db" + ], + "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": "nextcloud", + "environment_variable": "NEXTCLOUD_ADMIN_PASSWORD" + } + ] + }, + { + "id": "generated-db-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "db", + "environment_variable": "MYSQL_PASSWORD" + }, + { + "service": "nextcloud", + "environment_variable": "MYSQL_PASSWORD" + } + ] + }, + { + "id": "generated-db-root-password", + "strategy": "generate-cryptographically-random-at-install", + "bindings": [ + { + "service": "db", + "environment_variable": "MYSQL_ROOT_PASSWORD" + } + ] + } + ] + } + }, + "first_run": { + "endpoints": [ + { + "label": "Nextcloud Web UI", + "scheme": "https", + "port": 443, + "path": "/", + "source": "linuxserver-nextcloud-documentation" + } + ], + "credentials": [ + { + "label": "Generated administrator login", + "type": "runtime-generated", + "username": "admin", + "password": null, + "password_environment": "NEXTCLOUD_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": 2048, + "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": 30 + }, + "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" + }, + "installer_profile": { + "stack_driver": "generic-multi-lxc-stack", + "volume_preparations": [ + { + "container_path": "/config", + "owner_strategy": "mapped-root", + "remove_lost_found": true, + "only_when_mount_type": "managed-volume" + }, + { + "container_path": "/data", + "owner_strategy": "mapped-application-user", + "remove_lost_found": true + } + ] + }, + "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": "pending-per-application" + }, + { + "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" + } + ] + }, + "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", + "stop_signal", + "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": "passed-at-generation", + "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, + "dependency_lifecycle": { + "implementation": "proxmox-hookscript", + "trigger": "main-lxc-pre-start", + "waits_for_dependency_healthchecks": true, + "stops_dependencies_with_main": false + } + } +} diff --git a/oci/catalog/index.json b/oci/catalog/index.json index ea0111ef..7952303a 100644 --- a/oci/catalog/index.json +++ b/oci/catalog/index.json @@ -19414,6 +19414,38 @@ "optional_relaxed_confinement": false, "requires_security_confirmation": false, "hidden": false + }, + { + "id": "nextcloud-mariadb", + "provider": "linuxserver", + "template_family": "curated-profile", + "title": "Nextcloud MariaDB", + "repository": "https://github.com/linuxserver/docker-nextcloud", + "description": "LinuxServer Nextcloud, MariaDB 10.11 and Redis 7 in three native OCI LXC containers. /config and /data are separate; user files can use a host/NAS directory while database state stays in local managed storage.", + "website": "https://nextcloud.com/", + "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/nextcloud.webp", + "architectures": [ + "amd64", + "arm64" + ], + "updated_at": null, + "main_image": "lscr.io/linuxserver/nextcloud:latest", + "category": "productivity", + "category_label": "Productivity & Workflows", + "replaces_discovered_ids": [], + "curated_path": "catalog/curated/nextcloud-mariadb.json", + "template_id": "image-nextcloud-mariadb", + "template": "apps/nextcloud-mariadb.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 } ], "discovery": { diff --git a/oci/catalog/volume-policy.json b/oci/catalog/volume-policy.json index 467a9a19..65ca8225 100644 --- a/oci/catalog/volume-policy.json +++ b/oci/catalog/volume-policy.json @@ -161,6 +161,9 @@ ], "wordcraft": [ "/storage" + ], + "nextcloud-mariadb": [ + "/data" ] }, "sizes": { diff --git a/oci/examples/nextcloud-mariadb-bootstrap.php b/oci/examples/nextcloud-mariadb-bootstrap.php new file mode 100644 index 00000000..e4cf476f --- /dev/null +++ b/oci/examples/nextcloud-mariadb-bootstrap.php @@ -0,0 +1,37 @@ +isDot() || !$file->isFile()) { continue; } + $target = $dir . '/' . $file->getFilename(); + if (!file_exists($target) && !is_link($target)) { create_private($target, file_get_contents($file->getPathname()), null); } + } + } + // With the administrator included, Nextcloud installs itself on the first + // request, so nobody else on the network can claim the setup page. + $settings = ['dbtype' => 'mysql', 'dbhost' => getenv('MYSQL_HOST'), 'dbname' => getenv('MYSQL_DATABASE'), 'dbuser' => getenv('MYSQL_USER'), 'dbpass' => getenv('MYSQL_PASSWORD'), 'directory' => '/data', 'adminlogin' => 'admin', 'adminpass' => getenv('NEXTCLOUD_ADMIN_PASSWORD')]; + // Existing installations skip LinuxServer's first-run ownership setup. + create_private($dir . '/autoconfig.php', " true, 'memcache.local' => '\OC\Memcache\APCu', 'memcache.locking' => '\OC\Memcache\Redis', 'redis' => ['host' => 'redis', 'port' => 6379, 'timeout' => 0.0]]; + create_private($path, " true];') + subprocess.run(['/bin/sh', '-ec', script], env=env, check=True, capture_output=True) + self.assertFalse(autoconfig.exists()) + self.assertFalse((folder / 'CAN_INSTALL').exists()) + + @unittest.skipUnless(shutil.which('php'), 'PHP CLI is needed to execute the bootstrap contract') + def test_bootstrap_refuses_links_and_needs_the_administrator_password(self): + source = (ROOT / 'examples/nextcloud-mariadb-bootstrap.php').read_text() + base = dict(os.environ, MYSQL_HOST='db', MYSQL_DATABASE='nextcloud', MYSQL_USER='nextcloud', MYSQL_PASSWORD='x') + with tempfile.TemporaryDirectory() as temp: + folder = Path(temp) / 'config' + folder.mkdir() + target = Path(temp) / 'outside' + (folder / 'autoconfig.php').symlink_to(target) + script = source.replace('/config/www/nextcloud/config', str(folder)).replace('/app/www/src/config', str(Path(temp) / 'none')) + done = subprocess.run(['php'], input=script.encode(), env=dict(base, NEXTCLOUD_ADMIN_PASSWORD='y'), capture_output=True) + self.assertNotEqual(done.returncode, 0) + self.assertFalse(target.exists()) + (folder / 'autoconfig.php').unlink() + done = subprocess.run(['php'], input=script.encode(), env=base, capture_output=True) + self.assertNotEqual(done.returncode, 0) + self.assertFalse((folder / 'autoconfig.php').exists()) + + @unittest.skipUnless(sys.platform.startswith('linux') and os.geteuid() == 0 and shutil.which('php'), + 'Linux root is needed to reproduce existing-volume ownership') + def test_existing_config_volume_can_read_new_redis_configuration_as_its_app_user(self): + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) + root.chmod(0o755) + folder = root / 'config' + folder.mkdir(mode=0o755) + os.chown(folder, 1001, 1001) + installed = folder / 'autoconfig.php' + installed.write_text(' true];') + installed.chmod(0o640) + os.chown(installed, 1001, 1001) + source = (ROOT / 'examples/nextcloud-mariadb-bootstrap.php').read_text() + source = source.replace('/config/www/nextcloud/config', str(folder)) + subprocess.run(['php'], input=source.encode(), check=True, capture_output=True) + redis = folder / 'proxmenux-redis.config.php' + self.assertEqual((redis.stat().st_uid, redis.stat().st_gid), (1001, 1001)) + self.assertEqual(redis.stat().st_mode & 0o777, 0o600) + def app_user(): + os.setgroups([]) + os.setgid(1001) + os.setuid(1001) + result = subprocess.check_output(['php', '-r', + 'require $argv[1]; echo json_encode($CONFIG);', str(redis)], preexec_fn=app_user) + self.assertEqual(json.loads(result)['redis']['host'], 'redis') + self.assertEqual(installed.read_text(), ' true];') + self.assertFalse((folder / 'config.php').exists()) + + @unittest.skipUnless(shutil.which('php'), 'PHP CLI needed for the installed-instance contract') + def test_existing_installation_does_not_override_user_cache_settings(self): + with tempfile.TemporaryDirectory() as temp: + folder = Path(temp) / 'config' + folder.mkdir() + config = folder / 'config.php' + content = ' true, "redis" => ["host" => "user-cache", "timeout" => 3]];' + config.write_text(content) + source = (ROOT / 'examples/nextcloud-mariadb-bootstrap.php').read_text() + source = source.replace('/config/www/nextcloud/config', str(folder)) + subprocess.run(['php'], input=source.encode(), check=True, capture_output=True) + self.assertEqual(config.read_text(), content) + self.assertFalse((folder / 'proxmenux-redis.config.php').exists()) + self.assertFalse((folder / 'autoconfig.php').exists()) + +if __name__ == '__main__': + unittest.main()