Merge pull request #433 from MacRimi/oci-catalog-review

OCI catalog review, search in the main menu and Helper-Scripts addons in LXC
This commit is contained in:
MacRimi
2026-10-11 14:02:42 +02:00
committed by GitHub
135 changed files with 3336 additions and 175 deletions
@@ -0,0 +1,108 @@
"""An addon of the Helper-Scripts runs where its catalog says it belongs: on
the Proxmox host, inside a container, or wherever the user chooses when it
can be both. Until this, every addon ran on the host."""
from pathlib import Path
import subprocess
import textwrap
import unittest
ROOT = Path(__file__).resolve().parents[3]
MENU = ROOT / "scripts/menus/menu_Helper_Scripts.sh"
PLAIN = ROOT / "scripts/menus/helper_plain_text.py"
# Only the functions under test are loaded, not the menu or its catalog.
PRELUDE = textwrap.dedent(f"""
set -uo pipefail
eval "$(sed -n '/^download_script() {{/,/^RETURN_TO_MAIN=false/p' '{MENU}' | sed '$d')"
translate() {{ printf '%s' "$1"; }}
clear() {{ :; }}
dialog() {{ :; }}
pmx_lxc_is_oci() {{ [[ "$1" == 100 ]]; }}
MENU_HEIGHT=22; MENU_ROWS=14
""")
def bash(script):
return subprocess.run(["bash", "-c", PRELUDE + textwrap.dedent(script)], capture_output=True, text=True)
class TargetChoiceTests(unittest.TestCase):
def choice(self, kind, places):
return bash(f'helper_target_choice {kind} "{places}"').stdout.strip()
def test_an_addon_for_the_host_runs_on_the_host(self):
self.assertEqual(self.choice("addon", "pve"), "host")
def test_an_addon_for_containers_runs_in_one(self):
self.assertEqual(self.choice("addon", "lxc vm"), "lxc")
self.assertEqual(self.choice("addon", "lxc"), "lxc")
def test_an_addon_for_both_asks_where(self):
self.assertEqual(self.choice("addon", "pve vm lxc"), "ask")
self.assertEqual(self.choice("addon", ""), "ask")
def test_what_is_not_an_addon_runs_on_the_host(self):
# A script that creates a container or a VM belongs on the host,
# whatever the catalog lists for the application it installs.
self.assertEqual(self.choice("lxc", "lxc"), "host")
self.assertEqual(self.choice("vm", "vm"), "host")
self.assertEqual(self.choice("pve", "pve"), "host")
class ContainerListTests(unittest.TestCase):
def test_oci_containers_are_left_out_and_a_lock_is_shown(self):
result = bash(r"""
pct() { printf 'VMID Status Lock Name\n100 running chromium\n109 running ordinary\n110 stopped stopped-one\n112 stopped backup locked-one\n'; }
helper_lxc_rows
""")
self.assertEqual(result.stdout,
"109\tordinary · running\n110\tstopped-one · stopped\n112\tlocked-one · stopped · backup\n")
class RunTests(unittest.TestCase):
def test_the_script_runs_on_the_host_or_inside_the_container_chosen(self):
result = bash(r"""
curl() { printf 'printf on-host'; }
pct() { [[ "$1" == exec && "$2" == 109 && "$3" == --keep-env && "$4" == 0 && "$5" == -- ]] && printf 'in-lxc:%s' "${*: -1}"; }
HELPER_LXC_TARGET=''; download_script https://example.invalid/a; echo
HELPER_LXC_TARGET=109; download_script https://example.invalid/a; echo
""")
self.assertEqual(result.stdout, "on-host\nin-lxc:printf on-host\n")
def test_a_failed_or_empty_download_runs_nothing(self):
result = bash(r"""
bash() { echo RAN; }
pct() { echo RAN; }
HELPER_LXC_TARGET=109
curl() { return 22; }; download_script https://example.invalid/a && echo UNEXPECTED
curl() { printf ' \n'; }; download_script https://example.invalid/a && echo UNEXPECTED
echo done
""")
self.assertEqual(result.stdout, "done\n")
def test_cancelling_the_choice_leaves_no_target(self):
result = bash(r"""
dialog() { return 1; }
select_helper_target Test ask && echo UNEXPECTED
printf '[%s]\n' "$HELPER_LXC_TARGET"
""")
self.assertEqual(result.stdout, "[]\n")
def test_the_host_needs_no_question(self):
result = bash(r"""
dialog() { echo ASKED; return 1; }
select_helper_target Test host && printf 'ok[%s]\n' "$HELPER_LXC_TARGET"
""")
self.assertEqual(result.stdout, "ok[]\n")
class PlainTextTests(unittest.TestCase):
def test_html_becomes_text_and_commands_are_kept(self):
result = subprocess.run(["python3", str(PLAIN)], capture_output=True, text=True,
input="<p>Run <code>ls -la &amp;&amp; pwd</code></p><ul><li>one</li><li>two</li></ul>")
self.assertEqual(result.stdout, "Run ls -la && pwd\n\n• one\n\n• two")
if __name__ == "__main__":
unittest.main()
+155
View File
@@ -0,0 +1,155 @@
"""The search of the main menu finds an option of ProxMenux, an OCI application
or a Helper-Script by its name or by related words, and opens it where it
lives: the scripts it launches are the ones the menus launch."""
import importlib.util
import json
from pathlib import Path
import re
import unittest
ROOT = Path(__file__).resolve().parents[3]
SCRIPTS = ROOT / "scripts"
def load():
spec = importlib.util.spec_from_file_location("search_menu", SCRIPTS / "menus/search_menu.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# The repository in the place of the installed copy.
module.BASE, module.SCRIPTS = ROOT, SCRIPTS
module.OCI_INDEX = ROOT / "oci/catalog/index.json"
module.HELPERS_CACHE = ROOT / "json/helpers_cache.json"
module._translations = {}
return module
class IndexTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.index = json.loads((SCRIPTS / "menus/search_index.json").read_text(encoding="utf-8"))
cls.spanish = json.loads((ROOT / "lang/es.json").read_text(encoding="utf-8"))
def test_every_entry_opens_a_script_that_exists(self):
missing = sorted({item["script"] for item in self.index if not (SCRIPTS / item["script"]).is_file()})
self.assertEqual(missing, [])
def test_every_title_is_a_text_the_menus_already_translate(self):
names = {"ZimaOS", "Synology DSM"}
unknown = [item["title"] for item in self.index
if item["title"] not in self.spanish and item["title"] not in names]
self.assertEqual(unknown, [])
self.assertEqual([item["menu"] for item in self.index if item["menu"] not in self.spanish], [])
def test_every_script_a_menu_launches_can_be_found(self):
indexed = {item["script"] for item in self.index}
launched = set()
for menu in sorted((SCRIPTS / "menus").glob("*.sh")):
if menu.name in ("main_menu.sh", "lxc_menu.sh"):
continue
launched |= set(re.findall(r'bash "\$LOCAL_SCRIPTS/([A-Za-z0-9_./-]+\.sh)"', menu.read_text()))
launched -= {"menus/main_menu.sh"}
# Opened from their own menu, which is what the index points at.
launched -= {"post_install/auto_post_install.sh", "utilities/proxmox_update.sh", "utilities/upgrade_pve8_to_pve9.sh"}
self.assertEqual(sorted(launched - indexed), [])
def test_the_main_menu_offers_the_search_and_opens_what_it_hands_back(self):
menu = (SCRIPTS / "menus/main_menu.sh").read_text()
self.assertIn('search "$(translate "Search options and applications")"', menu)
self.assertIn('search_menu.py" --handoff "$handoff"', menu)
self.assertIn('[[ "${target[0]:-}" == "$LOCAL_SCRIPTS"/* && -f "${target[0]}" ]]', menu)
self.assertIn('exec bash "${target[@]}"', menu)
def test_an_option_inside_a_menu_names_one_that_menu_has(self):
for item in self.index:
argument = item.get("argument")
if not argument:
continue
script = (SCRIPTS / item["script"]).read_text()
self.assertIn("PRESELECTED_OPTION", script, item["script"])
if not argument.isdigit():
self.assertIn(argument, script, f"{item['script']}: {argument}")
class CatalogTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.search = load()
cls.items = cls.search.catalog(refresh=False)
def found(self, query):
return self.search.search(self.items, query)
def test_the_three_sources_are_in_the_catalog(self):
self.assertEqual({item["source"] for item in self.items}, set(self.search.SOURCES))
def test_proxmenux_comes_first_then_oci_then_helper_scripts(self):
sources = [item["source"] for item in self.found("samba")]
self.assertEqual(sources, sorted(sources, key=self.search.SOURCES.index))
self.assertEqual(sources[0], "ProxMenux")
def test_a_name_is_found_by_the_start_of_any_of_its_words(self):
self.assertIn("Jellyfin", [item["title"] for item in self.found("jelly")])
self.assertTrue(any(item["source"] == "OCI Manager" for item in self.found("plex")))
def test_accents_and_case_do_not_matter(self):
self.assertEqual([item["title"] for item in self.found("NVIDIA")],
[item["title"] for item in self.found("nvidia")])
def test_related_words_find_an_option(self):
self.assertTrue(any("NFS" in item["title"] for item in self.found("nfs storage")))
self.assertTrue(any(item["action"][-1].endswith("fail2ban_installer.sh") for item in self.found("fail2ban")))
def test_a_match_by_category_comes_after_the_names(self):
matches = self.found("vpn")
self.assertTrue(any(item["title"] == "Tailscale" for item in matches))
by_category = False
for item in matches:
words = re.findall(r"[a-z0-9]+", self.search.fold(item["terms"]))
in_name = any(word.startswith("vpn") for word in words)
self.assertFalse(in_name and by_category)
by_category = by_category or not in_name
def test_an_application_is_not_found_by_what_its_description_mentions(self):
titles = [item["title"] for item in self.found("plex")]
self.assertNotIn("Jellyfin", titles)
self.assertTrue(all("plex" in title.casefold() for title in titles))
def test_nothing_matches_nothing(self):
self.assertEqual(self.found("zzqqxx"), [])
self.assertEqual(self.found(" "), [])
def test_a_sub_menu_is_handed_back_to_the_main_menu(self):
by_script = {item["action"][1]: item for item in self.items if item["source"] == "ProxMenux"}
self.assertTrue(by_script[str(SCRIPTS / "menus/network_menu.sh")]["handoff"])
self.assertFalse(by_script[str(SCRIPTS / "storage/format-disk.sh")]["handoff"])
def test_an_option_inside_a_menu_is_given_to_that_menu(self):
zfs = next(item for item in self.items if item["action"][1:] == [str(SCRIPTS / "help_info_menu.sh"), "7"])
self.assertFalse(zfs["handoff"])
language = next(item for item in self.items if item["action"][-1] == "change_language")
self.assertEqual(language["action"][1], str(SCRIPTS / "menus/config_menu.sh"))
self.assertTrue(language["handoff"])
class OpenedInPlaceTests(unittest.TestCase):
def test_an_option_of_the_post_install_comes_selected(self):
script = (SCRIPTS / "post_install/customizable_post_install.sh").read_text()
self.assertIn('PRESELECTED_OPTION="${1:-}"', script)
self.assertIn('--default-item "${preselected_item:-1}"', script)
def test_a_utility_comes_selected(self):
script = (SCRIPTS / "utilities/system_utils.sh").read_text()
self.assertIn('PRESELECTED_UTILITY="${1:-}"', script)
def test_a_helper_script_is_opened_on_its_own(self):
script = (SCRIPTS / "menus/menu_Helper_Scripts.sh").read_text()
self.assertIn('run_script_by_slug "$1"', script)
def test_an_oci_application_opens_its_page(self):
cli = (ROOT / "oci/src/proxmenux_oci/cli.py").read_text()
self.assertIn('subparsers.add_parser("open"', cli)
if __name__ == "__main__":
unittest.main()
+60
View File
@@ -191,9 +191,12 @@
"Access bridge for Tandoor": "Puente de acceso para Tandoor",
"Access could not be granted completely; the application may be unable to write to:": "No se pudo conceder el acceso por completo; puede que la aplicación no pueda escribir en:",
"Access granted to the application on:": "Acceso concedido a la aplicación en:",
"Access password of the web interface (optional)": "Contraseña de acceso a la interfaz web (opcional)",
"Access profile:": "Perfil de acceso:",
"Access token of the Jupyter Lab web interface": "Token de acceso de la interfaz web de Jupyter Lab",
"Access token of the connector, from the Twingate admin console": "Token de acceso del conector, de la consola de administración de Twingate",
"Account is not locked": "La cuenta no está bloqueada",
"Account token from the settings of https://app.foldingathome.org": "Token de la cuenta, de los ajustes de https://app.foldingathome.org",
"Action cancelled due to previous xshok-proxmox modifications.": "Acción cancelada debido a modificaciones anteriores de xshok-proxmox.",
"Action:": "Acción:",
"Activate Monitor": "Activar Monitor",
@@ -279,7 +282,16 @@
"Additional audio function(s) to be added": "Funciones de audio adicionales que se agregarán",
"Additional media/GPU GIDs, comma-separated": "GID adicionales de medios/GPU, separados por comas",
"Additional paths for": "Rutas adicionales para",
"Address BookStack will be opened at (for example http://192.168.1.50:6875)": "Dirección en la que se abrirá BookStack (por ejemplo http://192.168.1.50:6875)",
"Address Healthchecks will be opened at (for example http://192.168.1.50:8000)": "Dirección en la que se abrirá Healthchecks (por ejemplo http://192.168.1.50:8000)",
"Address Speedtest Tracker will be opened at (for example http://192.168.1.50)": "Dirección en la que se abrirá Speedtest Tracker (por ejemplo http://192.168.1.50)",
"Address of Redis or Valkey (for example redis://192.168.1.20:6379/1)": "Dirección de Redis o Valkey (por ejemplo redis://192.168.1.20:6379/1)",
"Address of the Compose file": "Dirección del archivo Compose",
"Address of the MariaDB server": "Dirección del servidor MariaDB",
"Address of the NetBird management server": "Dirección del servidor de gestión de NetBird",
"Address of the PostgreSQL server": "Dirección del servidor PostgreSQL",
"Address of the Redis or Valkey server": "Dirección del servidor Redis o Valkey",
"Address of the database server (mysql and pgsql only)": "Dirección del servidor de base de datos (solo mysql y pgsql)",
"Address to reach Pydio Cells (https://domain or https://IP:8080)": "Dirección para acceder a Pydio Cells (https://dominio o https://IP:8080)",
"Address used to reach wallabag (http://IP or https://wallabag.example.com)": "Dirección usada para acceder a wallabag (http://IP o https://wallabag.example.com)",
"Addresses to update: ipv4, ipv6 or both (uses an external service)": "Direcciones que se actualizan: ipv4, ipv6 o both (usa un servicio externo)",
@@ -994,6 +1006,7 @@
"Configuration has been stopped due to high reset risk.": "La configuración se ha detenido debido al alto riesgo de reinicio.",
"Configuration has been stopped to prevent an unusable VM state.": "La configuración se ha detenido para evitar un estado de VM inutilizable.",
"Configuration has been stopped to prevent leaving the VM in an unusable state.": "La configuración se ha detenido para evitar dejar la máquina virtual en un estado inutilizable.",
"Configuration in JSON on one line (optional)": "Configuración en JSON en una sola línea (opcional)",
"Configuration name:": "Nombre de configuración:",
"Configuration saved": "Configuración guardada",
"Configuration sections that will be REMOVED": "Secciones de configuración que serán ELIMINADAS",
@@ -1558,8 +1571,11 @@
"Data volumes protected": "Volúmenes de datos protegidos",
"Data wipe complete.": "Borrado de datos completo.",
"Data wiped from": "Datos borrados de",
"Database (a SQLite file, or postgresql://user:password@address:5432/name)": "Base de datos (un archivo SQLite, o postgresql://usuario:contraseña@dirección:5432/nombre)",
"Database file for sqlite, or database name for mysql and pgsql": "Archivo de base de datos para sqlite, o nombre de la base de datos para mysql y pgsql",
"Database management in a single PHP file": "Gestión de bases de datos en un solo archivo PHP",
"Database server proposed on the login page (empty = typed at each login)": "Servidor de base de datos propuesto en la página de inicio de sesión (vacío = se escribe en cada inicio de sesión)",
"Database type (sqlite, mysql or pgsql)": "Tipo de base de datos (sqlite, mysql o pgsql)",
"Databases": "Databases",
"Datastore name:": "Nombre del almacén de datos:",
"Davos is an FTP automation tool that periodically scans given host locations for new files. It can be configured for various purposes, including listening for specific files to appear in the host location, ready for it to download and then move, if required. It also supports completion notifications as well as downstream API calls, to further the workflow.": "Davos es una herramienta de automatización de FTP que examina periódicamente ubicaciones de un servidor en busca de archivos nuevos. Se puede configurar para distintos fines, como esperar a que aparezcan archivos concretos para descargarlos y, si hace falta, moverlos. También admite notificaciones de finalización y llamadas a API posteriores para continuar el flujo de trabajo.",
@@ -1888,6 +1904,8 @@
"Email address for certificate expiry notices (required by ZeroSSL)": "Dirección de correo para los avisos de caducidad del certificado (obligatoria con ZeroSSL)",
"Email address of the LibreDB Studio administrator": "Dirección de correo del administrador de LibreDB Studio",
"Email address of the NetBox admin account": "Dirección de correo de la cuenta de administrador de NetBox",
"Email address of the admin account": "Correo electrónico de la cuenta admin",
"Email address of the superuser account": "Correo electrónico de la cuenta de superusuario",
"Emby WebUI": "Emby WebUI",
"Emby organizes video, music, live TV, and photos from personal media libraries and streams them to smart TVs, streaming boxes and mobile devices. This container is packaged as a standalone emby Media Server.": "Emby organiza vídeo, música, TV en directo y fotos de bibliotecas multimedia personales y los transmite a televisores inteligentes, reproductores de streaming y dispositivos móviles. Este contenedor se distribuye como un Emby Media Server independiente.",
"Emergency Proxmox System Repair": "Reparación de emergencia del sistema Proxmox",
@@ -2162,6 +2180,7 @@
"External credential is empty or spans multiple lines": "La credencial externa está vacía o abarca varias líneas",
"External disk for backup": "Disco externo para backup",
"External field not reserved:": "Campo externo no reservado:",
"Extra parameters for minisatip (optional)": "Parámetros adicionales para minisatip (opcional)",
"Extra paths": "Rutas extra",
"Extra paths to keep (unmark one to remove it)": "Rutas extra que se mantienen (desmarca una para eliminarla)",
"Extracting NVIDIA installer on host...": "Extrayendo el instalador de NVIDIA en el host...",
@@ -2893,6 +2912,7 @@
"Importing disk": "Importando disco",
"Importing:": "Importador:",
"Improve log rotation and limit log size to save space and extend disk life": "Mejorar la rotación de logs y limitar su tamaño para ahorrar espacio y alargar la vida del disco",
"In an LXC": "En un LXC",
"In the loader interface, follow the instructions to select your Synology model": "En la interfaz del cargador, siga las instrucciones para seleccionar su modelo de Synology",
"In use": "En uso",
"In use by VM/LXC config": "En uso por la configuración de VM/LXC",
@@ -3462,6 +3482,7 @@
"Listing relevant CT users and their mapped UID/GID on host...": "Listado de usuarios CT relevantes y su UID/GID asignado en el host...",
"Load and verify the WireGuard module on the Proxmox host": "Cargar y verificar el módulo WireGuard en el host Proxmox",
"Loading modules...": "Cargando módulos...",
"Loading the Helper-Scripts catalog...": "Cargando el catálogo de Helper-Scripts...",
"Loading the host kernel module:": "Carga el módulo del kernel host:",
"Local Disk Manager - Proxmox Host": "Administrador de discos locales - Proxmox Host",
"Local Disk Storages": "Almacenamientos en disco local",
@@ -3533,6 +3554,7 @@
"Machine type: q35": "Tipo de máquina: q35",
"Machine: q35": "Máquina: q35",
"Main endpoint not yet defined": "Punto final principal aún no definido",
"Main menu": "Menú principal",
"Major version differs:": "La versión principal difiere:",
"Make sure IOMMU is properly enabled and the system has been rebooted after activation.": "Asegúrese de que IOMMU esté habilitado correctamente y que el sistema se haya reiniciado después de la activación.",
"Make sure there are no critical services running as they will be interrupted. Ensure your server can be safely rebooted.": "Asegúrese de que no haya servicios críticos en ejecución, ya que se interrumpirán. Asegúrese de que su servidor pueda reiniciarse de forma segura.",
@@ -3858,16 +3880,22 @@
"NZBGet web interface": "Interfaz web de NZBGet",
"Name": "Nombre",
"Name for this application": "Nombre de esta aplicación",
"Name for this machine in Folding@home (no spaces)": "Nombre de esta máquina en Folding@home (sin espacios)",
"Name for this target:": "Nombre para este destino:",
"Name of the PostgreSQL user created on the first start": "Nombre del usuario de PostgreSQL creado en el primer arranque",
"Name of the Twingate network (the part before .twingate.com)": "Nombre de la red de Twingate (la parte anterior a .twingate.com)",
"Name of the database created on the first start": "Nombre de la base de datos creada en el primer arranque",
"Name of the database on the MariaDB server": "Nombre de la base de datos en el servidor MariaDB",
"Name of the directory to share (lowercase letters, digits, - or _)": "Nombre del directorio a compartir (minúsculas, números, - o _)",
"Name of the internal worker node": "Nombre del nodo worker interno",
"Name of this wallabag instance, shown in the interface and in 2FA codes": "Nombre de esta instancia de wallabag, mostrado en la interfaz y en los códigos 2FA",
"Name or address NetBox will be opened at (for example netbox.example.com)": "Nombre o dirección en la que se abrirá NetBox (por ejemplo netbox.example.com)",
"Name or part of the description of the application": "Nombre o parte de la descripción de la aplicación",
"Name or part of the option or of the application": "Nombre o parte de la opción o de la aplicación",
"Name:": "Nombre:",
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Las cuentas con nombre necesitan el modo privado. Detén el contenedor, pon public: false en /config/config.js, vuelve a arrancarlo y crea cada usuario con: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>",
"Needed:": "Necesario:",
"Needs": "Necesita",
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "No se encontraron /etc/kernel/cmdline ni /etc/default/grub.",
"Nesting feature enabled": "Función de anidamiento habilitada",
"NetBIOS Service: RUNNING": "Servicio NetBIOS: EN EJECUCIÓN",
@@ -4142,6 +4170,7 @@
"No language selected.": "No se seleccionó ningún idioma.",
"No local disk storage configured.": "No hay almacenamiento en disco local configurado.",
"No main sources.list present (skipped)": "No hay sources.list principal (omitido)",
"No matches for:": "No hay coincidencias para:",
"No matching PVE vzdump jobs were found for the PBS backend.": "No se encontraron trabajos PVE vzdump coincidentes para el backend de PBS.",
"No matching PVE vzdump jobs were found for the local archive backend.": "No se encontraron trabajos PVE vzdump coincidentes para el backend del archivo local.",
"No mount point was specified.": "No se especificó ningún punto de montaje.",
@@ -4172,6 +4201,7 @@
"No recent Samba servers found.": "No se encontraron servidores Samba recientes.",
"No registered OCI containers are available for selection on this host.": "No hay contenedores OCI registrados disponibles para seleccionar en este host.",
"No restored OCI application is waiting to be recovered.": "No hay ninguna aplicación OCI restaurada pendiente de recuperar.",
"No results": "Sin resultados",
"No routing information found.": "No se encontró información de enrutamiento.",
"No scheduled backup jobs configured.": "No se han configurado trabajos de backup programados.",
"No scheduled backup jobs found.": "No se encontraron trabajos de backup programados.",
@@ -4263,6 +4293,7 @@
"Number of CPU cores (default: 2)": "Número de núcleos de CPU (predeterminado: 2)",
"Nzbget is a usenet downloader, written in C++ and designed with performance in mind to achieve maximum download speed by using very little system resources.": "Nzbget es un descargador de Usenet escrito en C++ y diseñado pensando en el rendimiento, para lograr la máxima velocidad de descarga con muy pocos recursos del sistema.",
"Nzbhydra2 is a meta search application for NZB indexers, the spiritual successor to NZBmegasearcH, and an evolution of the original application NZBHydra.": "Nzbhydra2 es una aplicación de metabúsqueda para indexadores NZB, sucesora espiritual de NZBmegasearcH y evolución de la aplicación original NZBHydra.",
"OCI application": "Aplicación OCI",
"OCI container, configuration kept. Remove its GPU from OCI manager Apps: CT": "Contenedor OCI, configuración conservada. Elimina su GPU desde OCI manager Apps: CT",
"OCI containers keep their configuration: they are stopped and their Start on boot is disabled. Their GPU is removed from OCI manager Apps.": "Los contenedores OCI conservan su configuración: se detienen y se desactiva su inicio automático. Su GPU se elimina desde OCI manager Apps.",
"OCI containers require Proxmox VE 9.1 or later.": "Los contenedores OCI requieren Proxmox VE 9.1 o posterior.",
@@ -4294,6 +4325,7 @@
"Observer is not responding on port 4357": "El observador no responde en el puerto 4357",
"Obsidian is a note-taking app that lets you create, link, and organize your notes on your device, with hundreds of plugins and themes to customize your workflow. You can also publish your notes online, access them offline, and sync them securely with end-to-end encryption.": "Obsidian es una aplicación de notas que te permite crear, enlazar y organizar tus notas en tu dispositivo, con cientos de plugins y temas para personalizar tu flujo de trabajo. También puedes publicar tus notas en línea, acceder a ellas sin conexión y sincronizarlas de forma segura con cifrado de extremo a extremo.",
"Offer as exit node?": "¿Oferta como nodo de salida?",
"Official Duplicati image: encrypted, incremental backups to local, network and cloud storage.": "Imagen oficial de Duplicati: backups cifrados e incrementales en almacenamiento local, de red y en la nube.",
"Official Emby Media Server image with optional VA-API or NVIDIA acceleration.": "Imagen oficial de Emby Media Server con aceleración VA-API o NVIDIA opcional.",
"Official Jellyfin image with optional VA-API or NVIDIA acceleration.": "Imagen oficial de Jellyfin con aceleración VA-API o NVIDIA opcional.",
"Official Linux Distributions": "Distribuciones oficiales de Linux",
@@ -4306,6 +4338,7 @@
"On a privileged CT the mount options carry the only permissions.": "En un CT privilegiado, las opciones de montaje tienen los únicos permisos.",
"On some systems, when starting the VM the host may slow down for several minutes until it stabilizes, or freeze completely.": "En algunos sistemas, al iniciar la máquina virtual, el host puede ralentizarse durante varios minutos hasta que se estabilice o se congele por completo.",
"On the Borg server, append the following line to:": "en el servidor Borg, agregue la siguiente línea a:",
"On the host": "En el host",
"Once finished, re-run 'PVE 8 to 9 check' to verify that all issues are resolved \n before executing the PVE 8 → PVE 9 upgrade.": "Una vez terminado, vuelva a ejecutar la 'verificación PVE 8 a 9' para verificar que todos los problemas estén resueltos. \n antes de ejecutar la actualización PVE 8 → PVE 9.",
"Once finished, re-run the script 'PVE 8 to 9 check' to verify that all issues are resolved \n before rebooting.": "Una vez terminado, vuelva a ejecutar el script 'PVE 8 to 9 check' para verificar que todos los problemas estén resueltos. \n antes de reiniciar.",
"Once finished, re-run the script 'PVE 8 to 9 check' to verify that all issues.": "Una vez terminado, vuelva a ejecutar el script 'PVE 8 to 9 check' para verificar que todos los problemas.",
@@ -4485,6 +4518,7 @@
"Password of the Etherpad admin user": "Contraseña del usuario administrador de Etherpad",
"Password of the FlexGet web interface": "Contraseña de la interfaz web de FlexGet",
"Password of the LibreDB Studio administrator": "Contraseña del administrador de LibreDB Studio",
"Password of the MariaDB user": "Contraseña del usuario de MariaDB",
"Password of the MineOS web interface user": "Contraseña del usuario de la interfaz web de MineOS",
"Password of the NetBox admin account": "Contraseña de la cuenta de administrador de NetBox",
"Password of the OpenList admin user": "Contraseña del usuario administrador de OpenList",
@@ -4492,8 +4526,10 @@
"Password of the PostgreSQL user": "Contraseña del usuario de PostgreSQL",
"Password of the ShareCoveX panel administrator (8 characters or more)": "Contraseña del administrador del panel de ShareCoveX (8 caracteres o más)",
"Password of the SnapOtter admin user": "Contraseña del usuario administrador de SnapOtter",
"Password of the admin account": "Contraseña de la cuenta admin",
"Password of the deprecated Flowise application login (only read by Flowise versions before 3.0.1)": "Contraseña del acceso antiguo de la aplicación Flowise (solo la leen las versiones de Flowise anteriores a 3.0.1)",
"Password of the main AdGuard Home": "Contraseña del AdGuard Home principal",
"Password of the superuser account": "Contraseña de la cuenta de superusuario",
"Password or API token secret:": "Contraseña o token secreto de API:",
"Password or secret": "Contraseña o secreto",
"Password reset completed.": "Restablecimiento de contraseña completado.",
@@ -4601,6 +4637,7 @@
"Pool:": "Pool",
"Port": "Puerto",
"Port must be a number between 1 and 65535.": "El puerto debe ser un número entre 1 y 65535.",
"Port of the database server (mysql and pgsql only)": "Puerto del servidor de base de datos (solo mysql y pgsql)",
"Port:": "Puerto:",
"Portal IP and port are correct": "La IP y el puerto del portal son correctos",
"Portal is reachable": "El portal es accesible",
@@ -4729,6 +4766,7 @@
"ProxMenux cannot override NFS server-side permissions from the host.": "ProxMenux no puede anular los permisos del lado del servidor NFS del host.",
"ProxMenux customizations removed from bashrc": "Personalizaciones de ProxMenux eliminadas de bashrc",
"ProxMenux does not give a container the system of its host.": "ProxMenux no le da a un contenedor el sistema de su host.",
"ProxMenux does not install them. The installation asks how to connect to them.": "ProxMenux no los instala. La instalación pide cómo conectarse a ellos.",
"ProxMenux does not validate the contents; any keyfile your PBS accepts is accepted here.": "ProxMenux no valida los contenidos; cualquier archivo de claves que acepte su PBS se acepta aquí.",
"ProxMenux files:": "Archivos ProxMenux:",
"ProxMenux logo applied": "Logotipo de ProxMenux aplicado",
@@ -4773,6 +4811,7 @@
"Proxmox web interface: Datacenter > Storage > Add > SMB/CIFS": "Interfaz web de Proxmox: Centro de datos > Almacenamiento > Agregar > SMB/CIFS",
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Interfaz web de Proxmox: Centro de datos > Almacenamiento > Agregar > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Interfaz web de Proxmox: Centro de datos > Almacenamiento > Agregar > iSCSI",
"Proxy address to reach the API (optional)": "Dirección del proxy para llegar a la API (opcional)",
"Public UDP port clients connect to": "Puerto UDP público al que se conectan los clientes",
"Public UDP port peers connect to": "Puerto UDP público al que se conectan los peers",
"Public URL of phpMyAdmin when it is served behind a reverse proxy": "URL pública de phpMyAdmin cuando se sirve detrás de un proxy inverso",
@@ -4917,6 +4956,7 @@
"Recreating the container...": "Recreando el contenedor...",
"Recreating the container:": "Recreando el contenedor:",
"Refresh APT index and verify repositories:": "Actualizar el índice APT y verificar los repositorios:",
"Refresh token of the connector, from the Twingate admin console": "Token de renovación del conector, de la consola de administración de Twingate",
"Refresh your browser (Ctrl+Shift+R) to see changes": "Actualiza tu navegador (Ctrl+Shift+R) para ver los cambios",
"Refresh your browser to see changes (server restart may be required)": "Actualice su navegador para ver los cambios (es posible que sea necesario reiniciar el servidor)",
"Refreshing apt cache...": "Actualizando caché de apt...",
@@ -5158,6 +5198,7 @@
"Restoring the stack records...": "Restaurando los registros de la pila...",
"Results will be saved automatically to:": "Los resultados se guardarán automáticamente en:",
"Results will be saved to:": "Los resultados se guardarán en:",
"Results:": "Resultados:",
"Retention": "Retención",
"Retention policy (prune-backups syntax).": "Política de retención (sintaxis de prune-backups).",
"RetroArch is a frontend for emulators, game engines and media players. It enables you to run classic games on a wide range of computers and consoles through its slick graphical interface.": "RetroArch es un frontend para emuladores, motores de juego y reproductores multimedia. Permite ejecutar juegos clásicos en una gran variedad de ordenadores y consolas con una interfaz gráfica muy cuidada.",
@@ -5334,6 +5375,7 @@
"Scanning network for Samba servers...": "Escaneando red en busca de servidores Samba...",
"Schedule": "Programación",
"Schedule of the automatic restart, in cron format (for example 0 6 * * * for every day at 6:00)": "Programación del reinicio automático, en formato cron (por ejemplo 0 6 * * * para todos los días a las 6:00)",
"Schedule of the tests in cron format": "Programación de las pruebas en formato cron",
"Schedule:": "Cronograma:",
"Scheduled backup job created": "Trabajo de backup programado creado",
"Scheduled backup jobs": "Trabajos de backup programados",
@@ -5348,8 +5390,10 @@
"Scripts in": "Scripts en",
"ScummVM is a program which allows you to run certain classic graphical adventure and role-playing games, provided you already have their data files. The clever part about this: ScummVM just replaces the executables shipped with the games, allowing you to play them on systems for which they were never designed! ScummVM is a complete rewrite of these games' executables and is not an emulator.": "ScummVM es un programa que permite ejecutar ciertas aventuras gráficas y juegos de rol clásicos, siempre que ya tengas sus archivos de datos. Lo ingenioso es que ScummVM sustituye los ejecutables de los juegos, de modo que puedes jugarlos en sistemas para los que nunca se diseñaron. ScummVM es una reescritura completa de esos ejecutables y no es un emulador.",
"Sealskin is a self-hosted, client-server platform that enables users to run powerful, containerized desktop applications streamed directly to a web browser. It uses a browser extension to intercept user actions—such as clicking a link or downloading a file and redirects them to a secure, isolated application environment running on a remote server.": "Sealskin es una plataforma cliente-servidor autoalojada que permite ejecutar potentes aplicaciones de escritorio en contenedores transmitidas directamente al navegador. Usa una extensión del navegador para interceptar acciones del usuario, como hacer clic en un enlace o descargar un archivo, y redirigirlas a un entorno de aplicación seguro y aislado en un servidor remoto.",
"Search": "Buscar",
"Search Results for:": "Resultados de búsqueda para:",
"Search applications": "Buscar aplicaciones",
"Search options and applications": "Buscar opciones y aplicaciones",
"Search results for:": "Resultados de la búsqueda para:",
"Search/Filter Scripts": "Buscar/filtrar scripts",
"Searchable document archive with OCR": "Archivo de documentos con búsqueda y OCR",
@@ -5487,6 +5531,7 @@
"Select the GPU to pass through to the VM:": "Seleccione la GPU para pasar a la VM:",
"Select the GPU(s) to add to LXC": "Seleccione las GPU para agregar a LXC",
"Select the LXC container:": "Seleccione el contenedor LXC:",
"Select the LXC. OCI containers are not included.": "Selecciona el LXC. Los contenedores OCI no se incluyen.",
"Select the Linux distribution to install:": "Seleccione la distribución de Linux para instalar:",
"Select the NAS system to install:": "Seleccione el sistema NAS a instalar:",
"Select the NVIDIA driver version to install:": "Seleccione la versión del controlador NVIDIA para instalar:",
@@ -5555,6 +5600,7 @@
"Sending backup to PBS...": "Enviando backup a PBS...",
"Server": "Servidor",
"Server (listen for incoming tests on TCP 5201)": "Servidor (espera pruebas entrantes en TCP 5201)",
"Server IDs to test against, separated by commas (optional)": "ID de los servidores contra los que probar, separados por comas (opcional)",
"Server IP/hostname is correct": "La IP/nombre de host del servidor es correcta",
"Server IP:": "IP del servidor:",
"Server is accessible:": "El servidor es accesible:",
@@ -5609,6 +5655,7 @@
"Settings": "Ajustes",
"Settings post-install Proxmox": "Configuración post instalación de Proxmox",
"Setup Persistent Network Names": "Configurar nombres de red persistentes",
"Setup key from the NetBird dashboard": "Clave de configuración (setup key) del panel de NetBird",
"Share Access Error": "Error de acceso al recurso compartido",
"Share Name": "Nombre compartido",
"Share Options": "Opciones para compartir",
@@ -5651,6 +5698,7 @@
"Should show 'unprivileged: 1' if it's unprivileged": "Debería mostrar 'sin privilegios: 1' si no tiene privilegios",
"Should show fewer or no issues": "Debería mostrar menos o ningún problema",
"Should show pve-manager/9.x.x": "Debería mostrar pve-manager/9.x.x",
"Shoutrrr addresses for the notifications (optional)": "Direcciones de Shoutrrr para las notificaciones (opcional)",
"Show All Scripts": "Mostrar todos los scripts",
"Show CT users in table format": "Mostrar usuarios de CT en formato de tabla",
"Show Container Privilege Status": "Mostrar estado de privilegios de los contenedores",
@@ -6056,7 +6104,10 @@
"The Immich startup was modified or cannot be reproduced": "La startup Immich fue modificada o no se puede reproducir",
"The LXC changed during verification; nothing was adopted": "El LXC cambió durante la verificación; no se ha incorporado nada",
"The LXC changed while reviewing; nothing was adopted": "El LXC cambió durante la revisión; no se ha incorporado nada",
"The LXC could not be started.": "No se pudo arrancar el LXC.",
"The LXC has no Bash to run this script with. The addon was not run.": "El LXC no tiene Bash disponible para ejecutar este script. No se ha ejecutado el addon.",
"The LXC has stopped": "El LXC ha parado",
"The LXC is stopped. Do you want to start it to run the addon?": "El LXC está detenido. ¿Quieres arrancarlo para ejecutar el addon?",
"The Lounge starts in public mode: anyone who reaches the address opens the client without logging in, and the IRC networks added are lost when the session ends.": "The Lounge arranca en modo público: cualquiera que llegue a la dirección abre el cliente sin iniciar sesión, y las redes IRC añadidas se pierden al terminar la sesión.",
"The MAC address of the container cannot be kept": "La dirección MAC del contenedor no se puede mantener",
"The NVIDIA Container Toolkit repository definition was empty.": "La definición del repositorio de NVIDIA Container Toolkit estaba vacía.",
@@ -6563,6 +6614,7 @@
"Then run this option again:": "Luego ejecute esta opción nuevamente:",
"Then update /etc/fstab on the host with the same options.": "Luego actualice /etc/fstab en el host con las mismas opciones.",
"There are extra disks or bind mounts outside the journal; the rootfs is not replaced": "Hay discos o bind mounts adicionales fuera del diario de la operación; el rootfs no se reemplaza",
"There are no LXC containers available. OCI containers are not included.": "No hay contenedores LXC disponibles. Los contenedores OCI no se incluyen.",
"There is no temporary container of this operation to keep the current disks": "No hay contenedor temporal de esta operación para mantener los discos actuales",
"There is no verified backup; a modified container is not touched": "No hay backup verificado; un contenedor modificado no se toca",
"These Proxmox resources were added outside ProxMenux:": "Se añadieron estos recursos en Proxmox fuera de ProxMenux:",
@@ -6575,6 +6627,7 @@
"These manual changes cannot be adopted safely:": "Estos cambios manuales no se pueden incorporar con seguridad:",
"These paths will not be restored live and will be extracted for manual recovery.": "Estas rutas no se restaurarán en vivo y se extraerán para su recuperación manual.",
"These values are asked during the installation:": "Estos valores se preguntan durante la instalación:",
"They are described in the image documentation:": "Están descritos en la documentación de la imagen:",
"They will be added to oci-compose before continuing. Unsupported or changed resources are not imported.": "Se añadirán al oci-compose antes de continuar. No se importarán recursos incompatibles o modificados.",
"This CIFS share is mounted with restrictive permissions.": "Este recurso compartido CIFS está montado con permisos restrictivos.",
"This GPU is considered incompatible with GPU passthrough to a VM in ProxMenux.": "Esta GPU se considera incompatible con el passthrough de GPU a una VM en ProxMenux.",
@@ -6584,6 +6637,7 @@
"This application cannot be recovered yet:": "Esta aplicación todavía no se puede recuperar:",
"This application cannot be recovered yet; nothing was changed:": "Esta aplicación todavía no se puede recuperar; no se ha cambiado nada:",
"This application is not an Immich installed by ProxMenux": "Esta aplicación no es un Immich instalado por ProxMenux",
"This application is not in the OCI catalog.": "Esta aplicación no está en el catálogo OCI.",
"This application is under watchdog: it is restarted automatically when it crashes. Turn the watchdog off?": "Esta aplicación está bajo vigilancia: se reinicia automáticamente cuando falla. ¿Desactivar la vigilancia?",
"This archive does not contain a recognized backup layout.": "Este archivo no contiene un diseño de backup reconocido.",
"This backup does not contain any restorable paths.": "Este backup no contiene rutas restaurables.",
@@ -7030,6 +7084,9 @@
"User name of the administrator of the web interface": "Nombre de usuario del administrador de la interfaz web",
"User name of the deprecated Flowise application login (only read by Flowise versions before 3.0.1)": "Nombre de usuario del acceso antiguo de la aplicación Flowise (solo lo leen las versiones de Flowise anteriores a 3.0.1)",
"User of the AdGuard Home that receives the settings": "Usuario del AdGuard Home que recibe la configuración",
"User of the MariaDB server": "Usuario del servidor MariaDB",
"User of the PostgreSQL server": "Usuario del servidor PostgreSQL",
"User of the database server (mysql and pgsql only)": "Usuario del servidor de base de datos (solo mysql y pgsql)",
"User of the main AdGuard Home": "Usuario del AdGuard Home principal",
"User-friendly WebUI for LLMs (Formerly Ollama WebUI)": "WebUI fácil de usar para LLM (antes Ollama WebUI)",
"Username": "Nombre de usuario",
@@ -7265,6 +7322,7 @@
"Where do you want to mount inside container?": "¿Dónde desea montar dentro del contenedor?",
"Where do you want to mount the NFS export?": "¿Dónde desea montar la exportación NFS?",
"Where do you want to mount the Samba share?": "¿Dónde quieres montar el recurso compartido Samba?",
"Where do you want to run this addon?": "¿Dónde quieres ejecutar este addon?",
"Where is the OVA/OVF file located?": "¿Dónde se encuentra el archivo OVA/OVF?",
"Where to mount inside container?": "¿Dónde montarlo dentro del contenedor?",
"Where to store": "Dónde almacenar",
@@ -7482,6 +7540,7 @@
"experimental on this GPU": "experimental en esta GPU",
"ext4 — Proxmox dir storage (recommended)": "ext4 — dir de Proxmox (recomendado)",
"ext4 — recommended, most compatible": "ext4 — recomendado, el más compatible",
"external, already running": "externo, ya en funcionamiento",
"fail2ban-client could not communicate with the server": "fail2ban-client no pudo comunicarse con el servidor",
"fail2ban-client successfully communicated with the server": "fail2ban-client se comunicó correctamente con el servidor",
"failed": "fallido",
@@ -7656,6 +7715,7 @@
"needs a privileged LXC": "necesita un LXC privilegiado",
"needs a relaxed AppArmor or seccomp profile": "necesita un perfil de AppArmor o seccomp relajado",
"needs stack review": "necesita revisión de pila",
"needs these external services, already running:": "necesita estos servicios externos, ya en funcionamiento:",
"never": "nunca",
"next free": "siguiente libre",
"next free block": "siguiente bloque libre",
+1 -1
View File
@@ -2,7 +2,7 @@
<!-- Generated from oci/catalog/verification.json by .github/scripts/oci_validation.py. Do not edit by hand. -->
43 of 336 applications in the OCI catalog have been tested for real: 41 in the ProxMenux lab and 2 by the community. The OCI installer shows them as verified, with a ✓ in the lists.
43 of 334 applications in the OCI catalog have been tested for real: 41 in the ProxMenux lab and 2 by the community. The OCI installer shows them as verified, with a ✓ in the lists.
Each test describes the scenario that was run and names the image it ran on. It does not cover every possible configuration of the application, and a newer image has not been tested until someone reports it.
+1 -1
View File
@@ -233,7 +233,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -210,7 +210,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -291,7 +291,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -170,7 +170,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -211,7 +211,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -513,7 +513,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -286,7 +286,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -214,7 +214,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+3 -1
View File
@@ -48,7 +48,9 @@
}
],
"display_version": null,
"updated_at": "2026-04-03"
"updated_at": "2026-04-03",
"hidden": true,
"hidden_reason": "Its image stops without closing the application cleanly, also under Docker; hidden until the image is fixed"
},
"source": {
"provider": "linuxserver.io",
+1 -1
View File
@@ -364,7 +364,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -226,7 +226,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -213,7 +213,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -237,7 +237,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 500,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -244,7 +244,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -211,7 +211,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -261,7 +261,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -371,7 +371,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+555
View File
@@ -0,0 +1,555 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-duplicati-official",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Duplicati Official"
},
"tagline": {
"en_US": "Official Duplicati image: encrypted, incremental backups to local, network and cloud storage."
},
"description": {
"en_US": "Official Duplicati image: encrypted, incremental backups to local, network and cloud storage."
},
"category": "backup",
"category_label": "Backup & Recovery",
"author": "Duplicati",
"developer": "Duplicati",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/duplicati.webp",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 8200,
"path": "/"
},
"website": "https://www.duplicati.com/",
"documentation": "https://docs.duplicati.com/",
"repository": "https://github.com/duplicati/duplicati",
"tips": [],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "duplicati",
"repository": "https://github.com/duplicati/duplicati",
"revision": "66c05069de88ccb6054907665ef7813e0cf664f4e1a2032cd943a1b8d72e8530",
"image_repository_url": "https://hub.docker.com/r/duplicati/duplicati",
"readme_pushed_at": "",
"compose_sha256": "66c05069de88ccb6054907665ef7813e0cf664f4e1a2032cd943a1b8d72e8530",
"generated_at": "2026-10-11T09:05:05+00:00"
},
"container_contract": {
"service_name": "duplicati",
"container_name": "duplicati",
"image": {
"reference": "duplicati/duplicati:latest",
"registry": "docker.io",
"repository": "duplicati/duplicati",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "SETTINGS_ENCRYPTION_KEY",
"example": "",
"required": true,
"sensitive": true,
"source": "docker-compose"
},
{
"name": "DUPLICATI__WEBSERVICE_PASSWORD",
"example": "",
"required": true,
"sensitive": true,
"source": "docker-compose",
"prompt": "Password of the Duplicati web interface"
}
],
"volumes": [
{
"id": "volume-0",
"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
}
},
{
"id": "volume-1",
"container_path": "/backups",
"compose_source_example": "./backups",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "volume-2",
"container_path": "/source",
"compose_source_example": "./source",
"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": 8200,
"published_example": 8200,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n duplicati:\n image: duplicati/duplicati:latest\n container_name: duplicati\n ports:\n - 8200:8200\n volumes:\n - ./data:/data\n - ./backups:/backups\n - ./source:/source\n environment:\n - SETTINGS_ENCRYPTION_KEY=${GENERATED_SETTINGS_ENCRYPTION_KEY}\n - DUPLICATI__WEBSERVICE_PASSWORD=${GENERATED_DUPLICATI_WEBSERVICE_PASSWORD}\n restart: unless-stopped\n"
},
"compose_stack": {
"project_name": "duplicati",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "duplicati",
"service_count": 1,
"services": [
{
"name": "duplicati",
"image": "duplicati/duplicati:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "duplicati/duplicati:latest",
"container_name": "duplicati",
"ports": [
"8200:8200"
],
"volumes": [
"./data:/data",
"./backups:/backups",
"./source:/source"
],
"environment": [
"SETTINGS_ENCRYPTION_KEY=${GENERATED_SETTINGS_ENCRYPTION_KEY}",
"DUPLICATI__WEBSERVICE_PASSWORD=${GENERATED_DUPLICATI_WEBSERVICE_PASSWORD}"
],
"restart": "unless-stopped"
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "duplicati-volume-0",
"service": "duplicati",
"container_path": "/data",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "duplicati-volume-1",
"service": "duplicati",
"container_path": "/backups",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "duplicati-volume-2",
"service": "duplicati",
"container_path": "/source",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"duplicati"
],
"stop_order": [
"duplicati"
],
"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": "duplicati-webservice-password",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "duplicati",
"environment_variable": "DUPLICATI__WEBSERVICE_PASSWORD"
}
]
},
{
"id": "settings-encryption-key",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "duplicati",
"environment_variable": "SETTINGS_ENCRYPTION_KEY"
}
]
}
]
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "http",
"port": 8200,
"path": "/",
"source": "compose-metadata"
}
],
"credentials": [
{
"label": "Duplicati web interface (password only)",
"type": "configured-or-installer-generated",
"username": "Not required (password only)",
"password": null,
"password_environment": "DUPLICATI__WEBSERVICE_PASSWORD",
"change_required": false,
"source": "duplicati-documentation",
"retrieval": null
}
]
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 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": {
"generated_sensitive_environment": {
"SETTINGS_ENCRYPTION_KEY": {
"strategy": "token-hex",
"bytes": 16,
"prompt": false
},
"DUPLICATI__WEBSERVICE_PASSWORD": {
"strategy": "token-hex",
"bytes": 12,
"prompt": true
}
},
"volume_preparations": [
{
"container_path": "/data",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/backups",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/source",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
}
]
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available."
},
"validation": {
"schema": "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
}
}
+1 -1
View File
@@ -238,7 +238,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+3 -1
View File
@@ -35,7 +35,9 @@
"tips": [],
"mini_changelog": [],
"display_version": null,
"updated_at": null
"updated_at": null,
"hidden": true,
"hidden_reason": "Its image no longer publishes a version for any architecture; hidden until it does"
},
"source": {
"provider": "linuxserver.io",
+1 -1
View File
@@ -231,7 +231,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -318,7 +318,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -173,7 +173,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -249,7 +249,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -237,7 +237,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -300,7 +300,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -211,7 +211,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -242,7 +242,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -243,7 +243,7 @@
"unprivileged": false,
"ostype": "unmanaged",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -211,7 +211,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -288,7 +288,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -247,7 +247,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -407,7 +407,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -254,7 +254,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -294,7 +294,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -237,7 +237,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -296,7 +296,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -467,7 +467,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -275,7 +275,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -207,7 +207,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -389,7 +389,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -238,7 +238,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -230,7 +230,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 320,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -247,7 +247,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -223,7 +223,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -267,7 +267,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -211,7 +211,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -321,7 +321,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -233,7 +233,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -249,7 +249,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -233,7 +233,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -353,7 +353,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -242,7 +242,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -175,7 +175,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -209,7 +209,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -297,7 +297,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -221,7 +221,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -281,7 +281,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -288,7 +288,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -269,7 +269,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -252,7 +252,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -267,7 +267,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -232,7 +232,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -278,7 +278,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -307,7 +307,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -281,7 +281,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -302,7 +302,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -181,7 +181,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -542,7 +542,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+4 -2
View File
@@ -35,7 +35,9 @@
"tips": [],
"mini_changelog": [],
"display_version": null,
"updated_at": null
"updated_at": null,
"hidden": true,
"hidden_reason": "Its image no longer publishes a version for any architecture; hidden until it does"
},
"source": {
"provider": "linuxserver.io",
@@ -302,7 +304,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -231,7 +231,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
@@ -296,7 +296,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -244,7 +244,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -425,7 +425,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -213,7 +213,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -216,7 +216,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 500,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -342,7 +342,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -211,7 +211,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -260,7 +260,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -231,7 +231,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -221,7 +221,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -242,7 +242,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -890,7 +890,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 128,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -382,7 +382,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 256,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+555
View File
@@ -0,0 +1,555 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-duplicati-official",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Duplicati Official"
},
"tagline": {
"en_US": "Official Duplicati image: encrypted, incremental backups to local, network and cloud storage."
},
"description": {
"en_US": "Official Duplicati image: encrypted, incremental backups to local, network and cloud storage."
},
"category": "backup",
"category_label": "Backup & Recovery",
"author": "Duplicati",
"developer": "Duplicati",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/duplicati.webp",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 8200,
"path": "/"
},
"website": "https://www.duplicati.com/",
"documentation": "https://docs.duplicati.com/",
"repository": "https://github.com/duplicati/duplicati",
"tips": [],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "duplicati",
"repository": "https://github.com/duplicati/duplicati",
"revision": "66c05069de88ccb6054907665ef7813e0cf664f4e1a2032cd943a1b8d72e8530",
"image_repository_url": "https://hub.docker.com/r/duplicati/duplicati",
"readme_pushed_at": "",
"compose_sha256": "66c05069de88ccb6054907665ef7813e0cf664f4e1a2032cd943a1b8d72e8530",
"generated_at": "2026-10-11T09:05:05+00:00"
},
"container_contract": {
"service_name": "duplicati",
"container_name": "duplicati",
"image": {
"reference": "duplicati/duplicati:latest",
"registry": "docker.io",
"repository": "duplicati/duplicati",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "SETTINGS_ENCRYPTION_KEY",
"example": "",
"required": true,
"sensitive": true,
"source": "docker-compose"
},
{
"name": "DUPLICATI__WEBSERVICE_PASSWORD",
"example": "",
"required": true,
"sensitive": true,
"source": "docker-compose",
"prompt": "Password of the Duplicati web interface"
}
],
"volumes": [
{
"id": "volume-0",
"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
}
},
{
"id": "volume-1",
"container_path": "/backups",
"compose_source_example": "./backups",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "volume-2",
"container_path": "/source",
"compose_source_example": "./source",
"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": 8200,
"published_example": 8200,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n duplicati:\n image: duplicati/duplicati:latest\n container_name: duplicati\n ports:\n - 8200:8200\n volumes:\n - ./data:/data\n - ./backups:/backups\n - ./source:/source\n environment:\n - SETTINGS_ENCRYPTION_KEY=${GENERATED_SETTINGS_ENCRYPTION_KEY}\n - DUPLICATI__WEBSERVICE_PASSWORD=${GENERATED_DUPLICATI_WEBSERVICE_PASSWORD}\n restart: unless-stopped\n"
},
"compose_stack": {
"project_name": "duplicati",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "duplicati",
"service_count": 1,
"services": [
{
"name": "duplicati",
"image": "duplicati/duplicati:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "duplicati/duplicati:latest",
"container_name": "duplicati",
"ports": [
"8200:8200"
],
"volumes": [
"./data:/data",
"./backups:/backups",
"./source:/source"
],
"environment": [
"SETTINGS_ENCRYPTION_KEY=${GENERATED_SETTINGS_ENCRYPTION_KEY}",
"DUPLICATI__WEBSERVICE_PASSWORD=${GENERATED_DUPLICATI_WEBSERVICE_PASSWORD}"
],
"restart": "unless-stopped"
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "duplicati-volume-0",
"service": "duplicati",
"container_path": "/data",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "duplicati-volume-1",
"service": "duplicati",
"container_path": "/backups",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "duplicati-volume-2",
"service": "duplicati",
"container_path": "/source",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"duplicati"
],
"stop_order": [
"duplicati"
],
"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": "duplicati-webservice-password",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "duplicati",
"environment_variable": "DUPLICATI__WEBSERVICE_PASSWORD"
}
]
},
{
"id": "settings-encryption-key",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "duplicati",
"environment_variable": "SETTINGS_ENCRYPTION_KEY"
}
]
}
]
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "http",
"port": 8200,
"path": "/",
"source": "compose-metadata"
}
],
"credentials": [
{
"label": "Duplicati web interface (password only)",
"type": "configured-or-installer-generated",
"username": "Not required (password only)",
"password": null,
"password_environment": "DUPLICATI__WEBSERVICE_PASSWORD",
"change_required": false,
"source": "duplicati-documentation",
"retrieval": null
}
]
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 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": {
"generated_sensitive_environment": {
"SETTINGS_ENCRYPTION_KEY": {
"strategy": "token-hex",
"bytes": 16,
"prompt": false
},
"DUPLICATI__WEBSERVICE_PASSWORD": {
"strategy": "token-hex",
"bytes": 12,
"prompt": true
}
},
"volume_preparations": [
{
"container_path": "/data",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/backups",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/source",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
}
]
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available."
},
"validation": {
"schema": "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
}
}
+1 -1
View File
@@ -233,7 +233,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -249,7 +249,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+1 -1
View File
@@ -233,7 +233,7 @@
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
+2 -1
View File
@@ -1,5 +1,6 @@
{
"generated": [
"duplicati-official",
"emby-official",
"fileflows",
"frigate",
@@ -21,7 +22,7 @@
"stremio",
"tandoor"
],
"generated_count": 20,
"generated_count": 21,
"failed": [],
"failed_count": 0
}
+35 -3
View File
@@ -921,7 +921,7 @@
"requires_relaxed_confinement": false,
"optional_relaxed_confinement": false,
"requires_security_confirmation": false,
"hidden": false,
"hidden": true,
"template_id": "linuxserver-bitcoin-knots"
},
{
@@ -2608,6 +2608,38 @@
"hidden": false,
"template_id": "linuxserver-duplicati"
},
{
"id": "duplicati-official",
"provider": "duplicati",
"template_family": "curated-profile",
"title": "Duplicati Official",
"repository": "https://github.com/duplicati/duplicati",
"description": "Official Duplicati image: encrypted, incremental backups to local, network and cloud storage.",
"website": "https://www.duplicati.com/",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/duplicati.webp",
"architectures": [
"amd64",
"arm64"
],
"updated_at": null,
"main_image": "duplicati/duplicati:latest",
"category": "backup",
"category_label": "Backup & Recovery",
"replaces_discovered_ids": [],
"curated_path": "catalog/curated/duplicati-official.json",
"template": "apps/duplicati-official.json",
"template_status": "generated-unvalidated",
"automatic_install_candidate": true,
"untranslated_blockers": [],
"requires_privileged_lxc": false,
"optional_privileged_lxc": false,
"requires_host_pid_namespace": false,
"requires_relaxed_confinement": false,
"optional_relaxed_confinement": false,
"requires_security_confirmation": false,
"hidden": false,
"template_id": "image-duplicati-official"
},
{
"id": "eden",
"provider": "linuxserver.io",
@@ -2775,7 +2807,7 @@
"requires_relaxed_confinement": false,
"optional_relaxed_confinement": false,
"requires_security_confirmation": false,
"hidden": false,
"hidden": true,
"template_id": "image-emulatorjs"
},
{
@@ -9861,7 +9893,7 @@
"requires_relaxed_confinement": false,
"optional_relaxed_confinement": false,
"requires_security_confirmation": false,
"hidden": false,
"hidden": true,
"template_id": "image-sickchill"
},
{
+4
View File
@@ -1,4 +1,8 @@
{
"catalog_ui": {
"hidden": true,
"hidden_reason": "Its image stops without closing the application cleanly, also under Docker; hidden until the image is fixed"
},
"proxmox": {
"installer_profile": {
"volume_preparations": [
+20
View File
@@ -109,7 +109,27 @@
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
}
],
"external_services": [
"MariaDB"
]
}
},
"environment_overrides": {
"APP_URL": {
"prompt": "Address BookStack will be opened at (for example http://192.168.1.50:6875)"
},
"DB_HOST": {
"prompt": "Address of the MariaDB server"
},
"DB_USERNAME": {
"prompt": "User of the MariaDB server"
},
"DB_DATABASE": {
"prompt": "Name of the database on the MariaDB server"
},
"DB_PASSWORD": {
"prompt": "Password of the MariaDB user"
}
}
}
@@ -0,0 +1,12 @@
{
"environment_overrides": {
"CODE": {
"required": false,
"prompt": "Access password of the web interface (optional)"
},
"PROXY_URL": {
"required": false,
"prompt": "Proxy address to reach the API (optional)"
}
}
}
+12
View File
@@ -0,0 +1,12 @@
{
"environment_overrides": {
"CONFIG": {
"required": false,
"prompt": "Configuration in JSON on one line (optional)"
},
"SHOUTRRR_ADDRESSES": {
"required": false,
"prompt": "Shoutrrr addresses for the notifications (optional)"
}
}
}
+4
View File
@@ -1,4 +1,8 @@
{
"catalog_ui": {
"hidden": true,
"hidden_reason": "Its image no longer publishes a version for any architecture; hidden until it does"
},
"proxmox": {
"installer_profile": {
"volume_preparations": [
+8
View File
@@ -10,5 +10,13 @@
}
]
}
},
"environment_overrides": {
"ACCOUNT_TOKEN": {
"prompt": "Account token from the settings of https://app.foldingathome.org"
},
"MACHINE_NAME": {
"prompt": "Name for this machine in Folding@home (no spaces)"
}
}
}

Some files were not shown because too many files have changed in this diff Show More