Merge remote-tracking branch 'origin/develop' into HEAD

This commit is contained in:
MacRimi
2026-10-18 13:51:44 +02:00
321 changed files with 37751 additions and 1090 deletions
@@ -1,12 +1,13 @@
{
"meta": {
"title": "Código de conducta | ProxMenux Documentation",
"title": "Código de conducta | Documentación de ProxMenux",
"description": "Código de conducta y buenas prácticas de ProxMenux para colaboradores, testers y usuarios.",
"ogTitle": "Código de conducta | ProxMenux Documentation",
"ogTitle": "Código de conducta | Documentación de ProxMenux",
"ogDescription": "Expectativas sobre responsabilidad del código, divulgación de problemas de seguridad y alcance de los PRs para el proyecto ProxMenux."
},
"errors": {
"notFound": "Error: archivo CODE_OF_CONDUCT.md no encontrado.",
"loadFailed": "Error: no se pudo cargar el contenido del código de conducta."
}
},
"contentMarkdown": "# 📝 Código de conducta y buenas prácticas\n\nEste documento define los **principios y las pautas** de uso de **ProxMenux** para promover el **respeto, la colaboración y la seguridad** durante el desarrollo.\n\n## 📌 1. Autoría del código y reconocimiento\n\n- Si se utilizan **scripts, fragmentos de código o ideas** de otros repositorios o desarrolladores, se reconocerá siempre la autoría original.\n- Se añadirá un comentario en el código o la documentación que indique la fuente y, si es posible, enlace al repositorio original.\n- Al utilizar código con una **licencia** concreta, se deben respetar sus condiciones.\n\n### ✅ Ejemplo de reconocimiento de autoría en el código:\n\n```bash\n# Script basado en el trabajo de [Autor] en [Enlace al repositorio]\n```\n\n## 🔒 2. Seguridad y responsabilidad del código\n\n- Todo el código de este repositorio sigue las buenas prácticas de desarrollo seguro.\n- No se permiten contribuciones que introduzcan vulnerabilidades intencionadas o prácticas inseguras.\n- Los scripts nunca deben comprometer la seguridad del sistema ni los datos de los usuarios.\n- Las contribuciones deben revisarse antes de implementarlas para comprobar su seguridad y estabilidad.\n\n### ⚠️ Divulgación responsable de vulnerabilidades\n\nSi descubres una vulnerabilidad de seguridad, NO la notifiques en incidencias o foros públicos.\n\nComunícala en privado por correo electrónico:\n\n📧 proxmenux@macrimi.pro\n\nPara más información sobre las vulnerabilidades y cómo notificarlas, consulta nuestra [política de seguridad](./SECURITY.md).\n\n## 🤝 3. Normas de la comunidad\n\nPara mantener un entorno respetuoso y profesional, todos los usuarios deben seguir estas pautas:\n\n- ✅ Sé respetuoso y constructivo en las discusiones.\n- ❌ No se tolerarán el acoso, el discurso de odio ni las conductas ofensivas.\n- ✅ Aporta comentarios de forma profesional, sin ataques personales.\n- ❌ El incumplimiento puede dar lugar a advertencias o expulsiones, según la gravedad.\n\n##\n\nEste documento promueve un uso ético del código, la conciencia de seguridad y una comunidad respetuosa.\n\n📢 ¡Construyamos algo grande juntos!\n"
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"meta": {
"title": "Contribuir a ProxMenux | ProxMenux Documentation",
"title": "Contribuir a ProxMenux | Documentación de ProxMenux",
"description": "Cómo contribuir a ProxMenux — modelo de ramas (main / develop / feature/*), flujo de pull requests, plantilla de cabecera de script con atribución de autor y enlace opcional de patrocinio, política de diseño UI en dos fases, funciones de mensajes y el camino desde una rama de función hasta un release estable.",
"ogTitle": "Contribuir a ProxMenux",
"ogDescription": "Modelo de ramas, flujo de trabajo, atribución en la cabecera del script y política de diseño UI en dos fases que los colaboradores deben seguir."
@@ -129,7 +129,7 @@
"intro": "Todas definidas en <code>utils.sh</code>. Úsalas como el valor por defecto para cualquier salida visible para el usuario — visuales coherentes entre scripts es la idea. Si tu script necesita una función nueva que no encaja en el conjunto existente (un nuevo nivel de severidad, un nuevo helper de layout, etc.), propónla en tu Pull Request — se revisará y se añadirá a <code>utils.sh</code> si es útil de forma amplia.",
"headerFunction": "Función",
"headerWhen": "Cuándo usar",
"headerSpinner": "Spinner",
"headerSpinner": "Indicador de progreso",
"rows": [
{
"function": "msg_info \"text\"",
@@ -163,7 +163,7 @@
},
{
"function": "msg_success \"text\"",
"whenRich": "Prompt final \"Press Enter to return\" al final de la fase 2.",
"whenRich": "Mensaje final «Press Enter to return» al terminar la fase 2.",
"spinner": "Para"
},
{
+9 -9
View File
@@ -1,32 +1,32 @@
{
"meta": {
"title": "Colaboradores | ProxMenux Documentation",
"description": "Reconocimiento a las personas que hacen posible ProxMenux — testers, revisores y desarrolladores que dan forma a cada release.",
"ogTitle": "Colaboradores | ProxMenux Documentation",
"title": "Colaboradores | Documentación de ProxMenux",
"description": "Reconocimiento a las personas que hacen posible ProxMenux: quienes prueban, revisan y desarrollan cada versión.",
"ogTitle": "Colaboradores | Documentación de ProxMenux",
"ogDescription": "Conoce a los colaboradores detrás de ProxMenux."
},
"header": {
"title": "Colaboradores",
"description": "El proyecto ProxMenux crece y prospera gracias a la contribución de sus colaboradores. Este es el merecido reconocimiento a su trabajo — probando builds antes del release, cazando regresiones, revisando PRs y dando forma a la dirección de las nuevas funciones.",
"description": "ProxMenux crece gracias a sus colaboradores. Esta página reconoce su trabajo: probar versiones antes de publicarlas, detectar regresiones, revisar PR y ayudar a orientar las nuevas funciones.",
"section": "Acerca de"
},
"beyond": {
"title": "Más allá de esta lista",
"body": "Mucha más gente contribuye vía reportes de bugs, ideas de funciones en Discussions, pruebas beta y traducciones. La lista completa de colaboradores de código vive en el <extlink>grafo de colaboradores de GitHub</extlink>. La página de abajo destaca a las personas que han estado más activamente involucradas en probar y revisar releases de ProxMenux."
"body": "Muchas más personas contribuyen notificando errores, proponiendo funciones en Discussions, probando versiones beta y traduciendo el proyecto. La lista completa de colaboradores del código está en el <extlink>gráfico de colaboradores de GitHub</extlink>. Esta página destaca a quienes participan más activamente en las pruebas y la revisión de las versiones de ProxMenux."
},
"testers": {
"heading": "Testers y revisores",
"intro": "Estas personas fueron de las primeras en contribuir al proyecto, probando, reportando incidencias y proponiendo mejoras que ayudaron a que ProxMenux haya crecido hasta convertirse en lo que es hoy.",
"heading": "Pruebas y revisión",
"intro": "Estas personas estuvieron entre las primeras en contribuir al proyecto. Sus pruebas, avisos de errores y propuestas de mejora ayudaron a convertir ProxMenux en lo que es hoy.",
"roles": {
"testing": "Pruebas",
"testingReviewer": "Pruebas y revisor"
"testingReviewer": "Pruebas y revisión"
},
"youtube": "YouTube"
},
"contribute": {
"heading": "¿Quieres colaborar?",
"intro": "Cualquier contribución es bienvenida — código, pruebas, diseño, documentación o simplemente compartir tus ideas:",
"tester": "<strong>Tester</strong> — prueba el <beta>canal beta</beta> y reporta qué funciona y qué no antes de los releases estables.",
"tester": "<strong>Pruebas</strong>: prueba el <beta>canal beta</beta> y comunica qué funciona y qué no antes de que se publiquen las versiones estables.",
"developer": "<strong>Desarrollador</strong> — Bash + Next.js (TypeScript) + un poco de Python para el venv de traducción. Los PRs son bienvenidos en <gh>GitHub</gh>.",
"designer": "<strong>Diseñador</strong> — mejoras de UI, iconos, capturas para la documentación.",
"ideas": "<strong>Ideas</strong> — abre un hilo en <disc>GitHub Discussions</disc> antes de abrir una incidencia de petición de función."
+13 -13
View File
@@ -1,8 +1,8 @@
{
"meta": {
"title": "FAQ | ProxMenux Documentation",
"title": "Preguntas frecuentes | Documentación de ProxMenux",
"description": "Preguntas frecuentes sobre ProxMenux: qué es, instalación, compatibilidad (solo PVE 8+), personalización, actualizaciones, seguridad, uso en producción, seguridad de archivos del sistema, contribuir, desinstalación.",
"ogTitle": "FAQ | ProxMenux Documentation",
"ogTitle": "Preguntas frecuentes | Documentación de ProxMenux",
"ogDescription": "Preguntas frecuentes sobre instalación, compatibilidad, seguridad y contribución a ProxMenux."
},
"header": {
@@ -24,7 +24,7 @@
"q1": {
"question": "¿Qué es ProxMenux y para qué sirve?",
"p1Rich": "<strong>ProxMenux</strong> es una herramienta interactiva basada en menús diseñada para hacer <strong>Proxmox VE</strong> accesible a todos los usuarios, independientemente de su experiencia técnica. Simplifica la ejecución de comandos, permitiendo a los usuarios realizar acciones en su sistema sin necesidad de conocimientos avanzados de Linux.",
"p2": "Para usuarios menos experimentados, ProxMenux ofrece una forma intuitiva de ejecutar comandos mediante una interfaz de menús estructurada, reduciendo la necesidad de entrada manual por terminal. Para administradores con experiencia, recorta pulsaciones para flujos repetitivos (hardening post-instalación, passthrough de GPU, importación de VMs OVF, rotaciones de snapshots ZFS).",
"p2": "Para quienes tienen menos experiencia, ProxMenux ofrece menús estructurados que reducen la necesidad de escribir comandos a mano. A los administradores con experiencia les ahorra pasos en tareas repetitivas: reforzar la seguridad tras instalar, pasar una GPU, importar VM en formato OVF o gestionar la rotación de snapshots ZFS.",
"p3": "Proxmox VE se usa ampliamente para:",
"items": [
"Virtualización de nivel empresarial",
@@ -34,7 +34,7 @@
},
"q2": {
"question": "¿Cómo instalo ProxMenux?",
"p1Rich": "Sigue la <installlink>guía de instalación</installlink>. En corto:",
"p1Rich": "Sigue la <installlink>guía de instalación</installlink>. En resumen:",
"stableInstall": "bash -c \"$(wget -qLO - https://raw.githubusercontent.com/MacRimi/ProxMenux/main/install_proxmenux.sh)\"",
"p2": "Una vez instalado, simplemente arráncalo con:",
"menuCmd": "menu"
@@ -45,7 +45,7 @@
},
"q4": {
"question": "¿Puedo personalizar ProxMenux?",
"p1Rich": "Los scripts del núcleo no se pueden modificar directamente porque están alojados en GitHub y se refrescan con el flujo de auto-actualización. Lo que <em>sí</em> puedes personalizar:",
"p1Rich": "Las actualizaciones pueden sobrescribir los cambios locales en los scripts principales, así que evita editar esos archivos directamente. Lo que <em>sí</em> puedes personalizar:",
"items": [
"El banner de la consola vía la herramienta <strong>FastFetch</strong> en las opciones de post-instalación.",
"Qué componentes opcionales se instalan (Monitor, Fail2Ban, Lynis…) — elige durante la instalación o vía el menú correspondiente más tarde."
@@ -53,8 +53,8 @@
},
"q5": {
"question": "¿Cómo actualizo ProxMenux?",
"p1Rich": "Cuando hay una nueva versión disponible, ProxMenux la detecta en el siguiente lanzamiento de <code>menu</code> y te pide actualizar. Aceptar reemplaza los archivos de utilidad y las configuraciones en sitio. No hace falta descarga manual.",
"p2Rich": "Los usuarios estables reciben releases estables; los usuarios beta reciben releases beta. Cuando se publica una versión estable, ProxMenux notifica a los usuarios beta en el siguiente lanzamiento y ofrece cambiar automáticamente — mira la página del <betalink>programa beta</betalink>."
"p1Rich": "Cuando hay una nueva versión, ProxMenux la detecta la próxima vez que ejecutas <code>menu</code> y te propone actualizar. Si aceptas, sustituye los archivos de la herramienta y su configuración en la instalación existente; no necesitas descargar nada a mano.",
"p2Rich": "Los usuarios de la versión estable reciben las actualizaciones estables y los de la beta, las actualizaciones beta. Cuando se publica una versión estable, la beta avisa al volver a abrir el menú y ofrece cambiar automáticamente a la estable. Consulta el <betalink>programa beta</betalink>."
},
"q6": {
"question": "¿Dónde puedo reportar incidencias?",
@@ -63,19 +63,19 @@
},
"q7": {
"question": "¿Puedo contribuir a ProxMenux?",
"p1Rich": "<strong>Absolutamente.</strong> ProxMenux es de código abierto y colaborativo. Las contribuciones pueden ser código (bash, Next.js / TypeScript, el venv de Python de traducción), pruebas, documentación, diseño o simplemente ideas.",
"p1Rich": "<strong>Por supuesto.</strong> ProxMenux es un proyecto de código abierto y colaborativo. Puedes contribuir con código (Bash, Next.js/TypeScript y herramientas de traducción en Python), pruebas, documentación, diseño o ideas.",
"item1Rich": "Discute ideas en <discusslink>GitHub Discussions</discusslink> antes de abrir una petición de función.",
"item2Rich": "Para PRs, lee primero el <coclink>código de conducta y buenas prácticas</coclink>.",
"item3Rich": "Mira la <contriblink>página de colaboradores</contriblink> para los testers y revisores actuales."
},
"q8": {
"question": "¿ProxMenux modifica archivos críticos del sistema?",
"p1Rich": "<strong>No.</strong> ProxMenux instala:",
"item1Rich": "Dependencias vía apt: <code>dialog</code>, <code>curl</code>, <code>jq</code>, <code>git</code> (y <code>python3</code> + <code>googletrans</code> en la instalación con traducción).",
"p1Rich": "<strong>La instalación de ProxMenux añade los siguientes componentes.</strong>",
"item1Rich": "Dependencias mediante apt: <code>dialog</code>, <code>curl</code>, <code>jq</code> y <code>git</code>. Las traducciones usan catálogos JSON pregenerados; el instalador no añade al host un entorno virtual de traducción.",
"item2Rich": "El árbol de scripts en <code>/usr/local/share/proxmenux/</code>.",
"item3Rich": "El lanzador en <code>/usr/local/bin/menu</code>.",
"item4Rich": "Opcional: el servicio systemd del Monitor en <code>proxmenux-monitor.service</code>.",
"p2Rich": "ProxMenux <em>no</em> toca la configuración del núcleo de Proxmox a menos que se lo pidas explícitamente vía un menú dedicado (p. ej. el flujo de reparación de red edita <code>/etc/network/interfaces</code> — pero solo después de que confirmes y se haga un backup)."
"p2Rich": "ProxMenux <em>no</em> modifica la configuración principal de Proxmox salvo que lo solicites expresamente desde un menú específico. Por ejemplo, la reparación de red edita <code>/etc/network/interfaces</code>, pero solo después de tu confirmación y de hacer un backup."
},
"q9": {
"question": "¿Es seguro usar ProxMenux en producción?",
@@ -83,12 +83,12 @@
},
"q10": {
"question": "¿Cómo desinstalo ProxMenux?",
"p1Rich": "Desde dentro de ProxMenux: <strong>Settings → Desinstalar ProxMenux</strong>. El desinstalador elimina el árbol de scripts, el lanzador y el servicio del Monitor, opcionalmente elimina las dependencias seleccionadas y restaura los backups de <code>/root/.bashrc</code> y <code>/etc/motd</code> tomados en el momento de la instalación.",
"p1Rich": "Desde ProxMenux: <strong>Ajustes → Desinstalar ProxMenux</strong>. El desinstalador elimina el árbol de scripts, el lanzador y el servicio Monitor, permite eliminar dependencias seleccionadas y restaura <code>/root/.bashrc</code> y <code>/etc/motd</code> desde los backups hechos al instalar, si existen.",
"p2Rich": "Paso a paso completo: <uninstalllink>Desinstalar ProxMenux</uninstalllink>."
},
"q11": {
"question": "VirusTotal marca la URL de instalación — ¿es seguro?",
"p1Rich": "Una detección 1/95 por motores heurísticos (p. ej. <em>Chong Lua Dao</em>) es un falso positivo conocido. El instalador usa el patrón estándar <code>curl | bash</code> y descarga binarios legítimos (como <code>jq</code> desde su release oficial en GitHub), que los escáneres agresivos marcan basándose en el <em>comportamiento</em> y no en código realmente malicioso.",
"p1Rich": "El resultado de 1/95 notificado en el issue #162, de <em>Chong Lua Dao</em>, fue identificado por el mantenedor como un falso positivo. El instalador usa el patrón <code>curl | bash</code> y puede descargar <code>jq</code> desde su versión oficial de GitHub. Este <em>comportamiento</em> puede activar análisis heurísticos; aquel informe histórico no determina la seguridad de futuras descargas.",
"p2Rich": "ProxMenux es 100% código abierto y el script de instalación es revisable línea por línea: <scriptlink>install_proxmenux.sh</scriptlink>. Más contexto en la <issuelink>Issue #162</issuelink>."
}
}
+4 -4
View File
@@ -1,8 +1,8 @@
{
"meta": {
"title": "Acerca de | ProxMenux Documentation",
"title": "Acerca del proyecto | Documentación de ProxMenux",
"description": "Acerca de ProxMenux: objetivos del proyecto, colaboradores, FAQ y código de conducta. Herramienta de gestión basada en menús, de código abierto, para Proxmox VE 8+, construida y mantenida por MacRimi con un pequeño equipo de testers y colaboradores.",
"ogTitle": "Acerca de | ProxMenux Documentation",
"ogTitle": "Acerca del proyecto | Documentación de ProxMenux",
"ogDescription": "Acerca de ProxMenux — herramienta de gestión basada en menús, de código abierto, para Proxmox VE 8+."
},
"header": {
@@ -27,7 +27,7 @@
"icon": "Users",
"href": "/docs/about/contributors",
"title": "Colaboradores",
"description": "Reconocimiento a las personas que hacen posible ProxMenux — testers, revisores y desarrolladores que dan forma a cada release."
"description": "Reconocimiento a las personas que hacen posible ProxMenux: quienes prueban, revisan y desarrollan cada versión."
},
{
"icon": "ScrollText",
@@ -38,7 +38,7 @@
]
},
"involved": {
"heading": "Implicarse",
"heading": "Participa",
"intro": "Tres lugares para participar en el proyecto:",
"cards": [
{
@@ -157,7 +157,7 @@
"<strong>Filesystems runtime del kernel y sistema</strong> — <code>/proc</code>, <code>/sys</code>, <code>/dev</code> y <code>/run</code> son pseudo-filesystems que produce el kernel y udev; no se persisten en ningún sitio.",
"<strong>Binarios de paquetes bajo <code>/usr/bin</code>, <code>/usr/lib</code>, <code>/lib</code>, <code>/sbin</code></strong> — los reinstala el APT del destino a partir de <code>packages.manual.list</code>.",
"<strong><code>/var/log/</code>, <code>/var/tmp/</code>, <code>/var/cache/</code></strong> — estado runtime por host, no se restaura.",
"<strong><code>/home/USUARIO</code></strong> — no está en el perfil por defecto. Añadirlo como ruta custom cuando un sistema tenga directorios home de usuario que deban sobrevivir a una restauración."
"<strong><code>/home/USER</code></strong> — no está en el perfil por defecto. Añadirlo como ruta custom cuando un sistema tenga directorios home de usuario que deban sobrevivir a una restauración."
],
"customPathsTitle": "Cómo se tratan las rutas custom",
"customPathsBody": "Una ruta custom añadida en línea en modo Custom o persistida en <code>backup-extra-paths.txt</code> pasa por el mismo pipeline de <code>rsync</code> que las rutas del perfil por defecto. Se aplican las exclusiones globales. Si la ruta custom está bajo <code>/root/</code> o <code>/usr/local/share/proxmenux/</code>, siguen aplicando las exclusiones específicas de arriba. Cada ruta archivada — default o custom — queda registrada en <code>metadata/paths_archived.txt</code>. Las rutas que no existen en el origen se registran en <code>metadata/missing_paths.txt</code> sin detener la copia."
@@ -14,7 +14,7 @@
},
"intro": {
"title": "Cada salto de kernel se maneja de forma distinta",
"body": "Cuando la restauración detecta que la copia y el destino tienen versiones mayores distintas de kernel, el flujo se ramifica en función de la dirección del salto — si la copia es más antigua o más reciente que el destino — porque los dos casos tienen modos de fallo opuestos. Las copias más recientes que el destino se restauran limpiamente tal cual (verificado empíricamente en múltiples pruebas de banco). Las copias más antiguas que el destino necesitan un filtro para evitar romper el arranque del destino con configuración escrita para un kernel que desde entonces ha cambiado."
"body": "El kernel de un host Proxmox se identifica mediante una versión como <code>6.17.13-2-pve</code>. Los dos primeros números (<strong>6.17</strong> en este ejemplo) definen la versión principal: cuando cambian, algunos archivos de configuración del kernel anterior podrían no ser válidos para el nuevo. Si la restauración detecta versiones principales distintas en la copia y en el destino, el proceso toma un camino u otro según la dirección del salto: si el kernel de la copia es anterior o posterior al del destino. Los dos casos presentan riesgos opuestos. Las copias con un kernel más reciente que el del destino se restauran tal cual, sin problemas según las pruebas realizadas con varios saltos de kernel. Las copias con un kernel anterior al del destino necesitan un filtro para evitar que una configuración del kernel antiguo impida arrancar el sistema de destino."
},
"directionCheck": {
"heading": "La comprobación de dirección",
@@ -78,7 +78,7 @@
"intro": "Para desarrolladores que quieran trazar o extender el comportamiento cross-kernel:",
"rows": [
{ "component": "Detección de dirección", "location": "<code>hb_compat_check</code> en <code>lib_host_backup_common.sh</code>. Fija <code>HB_COMPAT_KERNEL_DIRECTION</code>." },
{ "component": "Lista de rutas del subconjunto seguro", "location": "<code>hb_unsafe_paths_cross_version</code> en <code>lib_host_backup_common.sh</code>. Emite líneas <code>path\\tmotivo</code> usadas tanto por el filtro CLI como por el endpoint Web <code>/api/host-backups/restore/prepare</code>." },
{ "component": "Lista de rutas del subconjunto seguro", "location": "<code>hb_unsafe_paths_cross_version</code> en <code>lib_host_backup_common.sh</code>. Emite líneas <code>path\\treason</code> usadas tanto por el filtro CLI como por el endpoint Web <code>/api/host-backups/restore/prepare</code>." },
{ "component": "Fases de hidratación", "location": "<code>_rs_hyd_grub</code>, <code>_rs_hyd_kernel_cmdline</code>, <code>_rs_hyd_modules</code>, <code>_rs_hyd_files</code> en <code>backup_host.sh</code>. Orquestados por <code>_rs_apply_bk_older_hydration</code>." },
{ "component": "Forzado de reflow post-arranque", "location": "<code>apply_pending_restore.sh</code> lee <code>HB_HYDRATION_APPLIED</code> de <code>plan.env</code> y fuerza <code>NEEDS_INITRAMFS=1</code>/<code>NEEDS_GRUB=1</code>." },
{ "component": "Preview Web", "location": "<code>/api/host-backups/restore/prepare</code> en <code>flask_server.py</code>. Fuentea la librería helper, ejecuta <code>_rs_apply_bk_older_hydration</code> en modo plan, devuelve las acciones al modal Web." }
@@ -76,7 +76,7 @@
},
"sameArchive": {
"heading": "El contenido interno de la copia es el mismo en cualquier destino",
"body": "Con independencia de dónde se guarde la copia, dentro siempre están los mismos tres bloques descritos en <em>Cómo funciona</em>: el sistema de ficheros (<code>rootfs/</code>), los metadatos (<code>metadata/</code>) y el manifiesto (<code>manifest.json</code>). Al extraer una copia local <code>.tar.zst</code>, restaurar un archivo <code>.pxar</code> desde PBS o descomprimir un archivo Borg, el árbol de directorios resultante es idéntico en los tres casos. Esto significa que el proceso de restauración lee siempre los mismos ficheros y no le importa desde qué destino provenga la copia."
"body": "Los tres destinos contienen la misma estructura <code>rootfs/</code> + <code>metadata/</code> + <code>manifest.json</code> descrita en <em>Cómo funciona</em>. Extraer un <code>.tar.zst</code> de un archivo local, restaurar un <code>.pxar</code> desde PBS o extraer un archivo de Borg con <code>borg extract</code> produce el mismo árbol de directorios. El proceso de restauración (<code>_rs_check_layout</code>, <code>_rs_apply</code>, <code>_rs_prepare_pending_restore</code>) lee los mismos tres componentes sin necesitar saber de qué destino proceden."
},
"extractStandalone": {
"heading": "Extraer una copia fuera de ProxMenux",
@@ -23,7 +23,7 @@
},
"repoSelection": {
"heading": "Selección del repositorio",
"intro": "ProxMenux descubre repositorios PBS desde dos fuentes en cada copia. El usuario elige uno desde un menú unificado; esa elección determina, para esa ejecución concreta, contra qué servidor y datastore se envía la copia, con qué contraseña se autentica y con qué huella (<em>fingerprint</em>) valida el certificado.",
"intro": "ProxMenux descubre los repositorios de PBS a partir de dos fuentes en cada copia de seguridad. El usuario elige uno en un menú unificado; esa elección determina los valores de <code>HB_PBS_REPOSITORY</code>, <code>HB_PBS_SECRET</code> y <code>HB_PBS_FINGERPRINT</code> para esa ejecución.",
"sourceRows": [
{
"source": "storage.cfg de Proxmox (auto-descubierto)",
@@ -46,7 +46,7 @@
"backupIdTitle": "Nombrado del backup ID",
"backupIdBody": "El backup ID por defecto es <code>hostcfg-HOSTNAME</code>. Se pide al usuario que lo confirme o edite antes de la subida; cualquier carácter fuera de <code>[A-Za-z0-9_-]</code> se elimina y los guiones finales se recortan. Reutilizar el mismo ID entre ejecuciones es intencional — PBS trata el ID como un <em>grupo</em>, y cada copia posterior aparece como un nuevo backup dentro de ese grupo, compartiendo dedup con las ejecuciones previas.",
"pxarTitle": "Qué se incluye dentro del archivo .pxar",
"pxarBody": "Al construir el archivo <code>.pxar</code> se empaqueta el directorio de trabajo completo: el sistema de ficheros del host (<code>rootfs/</code>), los metadatos (<code>metadata/</code>) y el manifiesto (<code>manifest.json</code>). Al restaurar, ProxMenux compara la información del manifiesto con la del host destino para detectar si son equivalentes, si cambia el hardware o si se trata de un equipo distinto, y ajustar el proceso en consecuencia. Las copias antiguas —hechas con versiones anteriores de ProxMenux que empaquetaban solo el sistema de ficheros— siguen restaurándose sin problema: el flujo de restauración detecta ese formato heredado y lo reorganiza automáticamente."
"pxarBody": "El origen del <code>.pxar</code> es todo el directorio <code>staging_root</code>, con <code>rootfs/</code>, <code>metadata/</code> y <code>manifest.json</code> juntos. Las versiones anteriores utilizaban <code>$staging_root/rootfs</code> como origen; esto dejaba <code>metadata/</code> fuera del archivo y la comprobación de compatibilidad de la restauración no tenía datos que leer, por lo que mostraba advertencias de restauración entre hosts incluso al restaurar en el mismo host. Las copias antiguas creadas solo a partir de rootfs siguen restaurándose correctamente mediante la rama del caso 3 de <code>_rs_check_layout</code>, que vuelve a colocar el árbol plano <code>etc/var/root/usr</code> dentro de una estructura <code>rootfs/</code>."
},
"encryption": {
"heading": "Cifrado del lado del cliente",
@@ -61,9 +61,9 @@
"modesSharedTitle": "Clave compartida (importar la misma en cada host)",
"modesSharedBody": "Se genera una única clave y se importa en todos los hosts mediante la opción <em>Usar una clave existente</em>. La gestión es más sencilla: hay un solo secreto que proteger, y cualquier host puede leer las copias de cualquier otro (útil para verificación centralizada, ejercicios de restauración cruzada o consolidación). A cambio, si la clave compartida se filtra queda expuesto todo el conjunto de hosts a la vez. Recomendado para laboratorios personales y entornos donde todos los hosts pertenecen al mismo responsable y comparten el mismo nivel de confianza.",
"recoveryTitle": "¿Subir la clave a PBS? — el usuario decide",
"recoveryBody": "Justo después de elegir la clave, ProxMenux pregunta si se quiere subir una copia de esa clave a PBS como red de seguridad, con dos opciones. <strong>No</strong> (por defecto) mantiene la clave solo en el host; ProxMenux no toca PBS con nada relacionado con la recuperación y el usuario gestiona por su cuenta la copia externa (desde el Monitor, la acción <em>Descargar</em> en la fila del destino PBS la exporta en el acto). <strong>Sí</strong> pide una passphrase de recuperación —dos veces, para comprobar que coincidan—; con esa passphrase, la clave se envuelve localmente con AES-256-CBC y PBKDF2 (600 000 iteraciones, sal aleatoria) en un fichero <code>pbs-key.recovery.enc</code>. A partir de ese momento, cada copia cifrada sube también ese fichero envuelto a PBS. Ni la passphrase ni la clave en claro salen del host. La respuesta se puede cambiar después desde el Monitor en cualquier momento; el interruptor está inline en la fila del destino PBS y el botón que aparece se adapta al estado (empezar a subir, dejar de subir, o cambiar la passphrase).",
"recoveryBody": "Justo después de elegir la clave, ProxMenux hace una única pregunta explícita — <em>¿Subir clave a PBS?</em> — con dos respuestas. <strong>No se sube nada a PBS hasta que el usuario responde Sí.</strong> La opción por defecto es <em>No, mantener solo local</em>: la clave se queda solo en su ruta local, ProxMenux no toca PBS con nada relacionado con la recuperación y el usuario gestiona por su cuenta la copia externa (desde el Monitor, el botón <em>Descargar archivo clave</em> de la fila del destino PBS la exporta en el acto). Al elegir <em>Sí, subir</em> se pide una passphrase de recuperación —dos veces, para comprobar que coincidan— y ProxMenux envuelve la clave con esa passphrase usando AES-256-CBC y PBKDF2 (600 000 iteraciones, sal aleatoria) en un fichero <code>pbs-key.recovery.enc</code>. A partir de ese momento, cada backup cifrado sube también ese fichero envuelto a PBS como un grupo de backup asociado. Ni la passphrase ni la clave en claro salen del host. La respuesta se puede cambiar después desde el Monitor en cualquier momento: el interruptor de la fila del destino PBS cambia entre Sí y No y se aplica al momento (empezar a subir, dejar de subir o cambiar la passphrase, según el estado).",
"blobUploadTitle": "Grupo emparejado en PBS",
"blobUploadBody1": "Cuando el usuario ha respondido Sí, ProxMenux sube el sobre de recuperación a PBS después de cada copia cifrada como un segundo grupo emparejado, con el mismo nombre que el del host pero terminado en <code>-keyrecovery</code>. Los dos grupos aparecen juntos en el listado del datastore: uno con las copias del host, otro con los sobres. <strong>El sobre nunca sale del host en claro</strong>: se cifra en el host con AES-256-CBC y PBKDF2 antes de enviar un solo byte (<code>openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -salt</code>). PBS solo recibe el sobre ya cifrado.",
"blobUploadBody1": "Cuando la custodia está configurada como <em>Sí, subir</em>, ProxMenux sube el archivo de recuperación protegido a PBS después de cada copia cifrada. Lo guarda en un segundo grupo de copia asociado, con el mismo nombre que el grupo del host y el sufijo <code>-keyrecovery</code>. Los dos grupos aparecen juntos en la lista del almacén de datos: uno para las copias del host y otro para los archivos de recuperación. <strong>El archivo de recuperación nunca sale del host en texto plano</strong>: se cifra en el propio host con AES-256-CBC y PBKDF2 antes de enviar ningún dato (<code>openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -salt</code>). PBS solo recibe el archivo ya cifrado.",
"envelopeSecurityTitle": "¿No es un riesgo subir el archivo keyrecovery a PBS?",
"envelopeSecurityBody": "El sobre viaja y se guarda cifrado en todo momento. La passphrase de recuperación no sale nunca del host: el cifrado ocurre en local antes de la subida y PBS solo recibe el resultado ya cifrado. Un administrador de PBS —o cualquiera con acceso al datastore— puede descargar el sobre, pero sin la passphrase no puede leer la clave que contiene: son solo bytes cifrados. Para reconstruir la clave hacen falta las dos cosas a la vez, el sobre y la passphrase, y solo el usuario tiene ambas.",
"blobUploadConstraintTitle": "Por qué dos grupos y no uno solo cifrado",
@@ -73,7 +73,7 @@
"recoverTitle": "Recuperación en un equipo recién instalado",
"recoverBody": "Cuando la clave no está en su sitio —tras reinstalar el host desde cero o después de eliminarla a propósito— el flujo de restauración prueba tres fuentes en orden y se queda con la primera que produce una clave usable. Primero, si el repositorio PBS elegido tiene una clave gestionada por PVE en <code>/etc/pve/priv/storage/&lt;NAME&gt;.enc</code>, se copia sola a la ruta canónica. Segundo, si en PBS hay un grupo <code>-keyrecovery</code>, se descarga la copia más reciente y se pide la passphrase de recuperación para abrirla. Tercero, si ninguna de las dos anteriores funciona o el usuario las descarta, el diálogo pide la ruta absoluta donde ha dejado la clave en este host, y se copia a la ruta canónica. El Monitor expone el mismo flujo dentro del modal de la copia. Si al Restaurar, Descargar o Ver contenido falta la clave, aparece un panel ámbar arriba del modal con las mismas tres vías de importación. Si la clave está instalada pero no es la correcta para esa copia, PBS devuelve un error de tipo <code>wrong key — manifest's key XX does not match provided key YY</code> y el modal muestra un panel estructurado con el fingerprint que PBS espera (el que quedó grabado en el manifest de la copia), para que el usuario sepa qué clave concreta necesita importar.",
"monitorManagementTitle": "Gestionar la clave desde el Monitor",
"monitorManagementBody": "En la página de configuración de copias, la fila de cada destino PBS incluye los controles de la clave. Tres acciones directas: <em>Descargar</em> exporta la clave actual al navegador. <em>Subir</em> reemplaza la clave instalada por otra que aporta el usuario (la anterior solo se sobrescribe cuando la nueva ha llegado correctamente a su sitio). <em>Eliminar</em> retira la clave del host. Justo al lado está el interruptor del sobre de recuperación: un Sí/No para subir o no la clave a PBS, un campo de passphrase que aparece al elegir Sí, y un botón que se adapta al estado actual (empezar a subir, dejar de subir, o cambiar la passphrase). Los controles del Monitor y el diálogo del shell hacen lo mismo por dentro, así que el resultado en disco y en PBS es idéntico se use la que se use."
"monitorManagementBody": "El Monitor muestra los controles del archivo de clave en cada fila de destino PBS de la página de configuración de copias. Hay tres acciones: <em>Descargar</em> envía el archivo de clave actual al navegador del usuario; <em>Subir</em> sustituye el archivo de clave instalado por uno proporcionado por el usuario (el anterior solo se sobrescribe cuando el nuevo se ha guardado correctamente en la ruta canónica); y <em>Eliminar</em> borra el archivo de clave del host. Junto a estas acciones hay un único control de custodia para la recuperación: las opciones Sí y No de <em>¿Subir la clave a PBS?</em>, un campo para la frase de contraseña al elegir Sí y un botón contextual para aplicar el cambio, con el texto <em>Iniciar subida</em>, <em>Detener subida</em> o <em>Actualizar frase de contraseña</em> según el estado actual. Todas las acciones utilizan los mismos endpoints de Flask que el menú de terminal, por lo que el resultado en disco y el estado en PBS son idénticos desde ambas interfaces."
},
"restoreAccess": {
"heading": "Recuperación del lado de la restauración",
@@ -112,7 +112,7 @@
{
"id": "repositorio-pbs",
"term": "Repositorio PBS",
"def": "Combinación de servidor Proxmox Backup Server + <a href=\"#datastore\">datastore</a> + usuario al que se suben las copias. Se identifica con el formato <code>usuario@realm@host:datastore</code>. Un mismo servidor PBS puede alojar varios repositorios."
"def": "Combinación de servidor Proxmox Backup Server + <a href=\"#datastore\">datastore</a> + usuario al que se suben las copias. Se identifica con el formato <code>user@realm@host:datastore</code>. Un mismo servidor PBS puede alojar varios repositorios."
},
{
"id": "datastore",
@@ -121,7 +121,7 @@
}
],
"schemaTitle": "Validación por esquema",
"schemaBody": "ProxMenux incluye una plantilla que describe qué campos debe contener el manifiesto y qué forma tiene cada uno. Cuando se genera una copia se puede comprobar automáticamente que el manifiesto respeta esa plantilla, de modo que si un colector produjera un JSON malformado o con un campo mal escrito se detectaría en el momento. Es una comprobación destinada al desarrollo del propio ProxMenux: si el sistema no la tiene instalada, la copia sigue funcionando con normalidad y el manifiesto se genera igual."
"schemaBody": "El manifiesto se valida con <code>scripts/backup_restore/schema/manifest.schema.json</code>. Ejecutar <code>build_manifest.sh --validate</code> activa una validación JSON Schema en Python (requiere <code>python3</code> y <code>jsonschema</code>). Si el módulo no está instalado, se omite la comprobación sin mostrar ningún aviso: esta validación es principalmente una ayuda para el desarrollo, no una dependencia necesaria durante la ejecución."
},
"applications": {
"heading": "El inventario de aplicaciones",
@@ -26,7 +26,7 @@
},
{
"action": "Descargar",
"detail": "Exporta el archivo como un fichero portable <code>.tar.zst</code> (tar comprimido con zstd). Se puede extraer en cualquier sistema Linux con <code>tar --zstd -xf FICHERO.tar.zst</code>, o desde macOS/Windows con herramientas que soporten zstd (7-Zip, PeaZip, Keka…). El árbol extraído contiene <code>manifest.json</code>, <code>metadata/</code> y <code>rootfs/</code>, exactamente el mismo layout que consume la restauración. Es útil para inspección offline o para restaurar en un host que no tiene acceso al destino original (PBS, Borg)."
"detail": "Exporta el archivo como un fichero portable <code>.tar.zst</code> (tar comprimido con zstd). Se puede extraer en cualquier sistema Linux con <code>tar --zstd -xf FILE.tar.zst</code>, o desde macOS/Windows con herramientas que soporten zstd (7-Zip, PeaZip, Keka…). El árbol extraído contiene <code>manifest.json</code>, <code>metadata/</code> y <code>rootfs/</code>, exactamente el mismo layout que consume la restauración. Es útil para inspección offline o para restaurar en un host que no tiene acceso al destino original (PBS, Borg)."
},
{
"action": "Restaurar",
@@ -110,7 +110,7 @@
},
"apply": {
"title": "Aplicar cambios del host + workloads",
"body": "Una vez confirmas, el script escribe los cambios del lado del host — <code>vfio.conf</code>, blacklist, módulos y (para NVIDIA) la regla udev por BDF en <code>/etc/udev/rules.d/10-proxmenux-vfio-bind.rules</code> más el estado BDF en <code>/etc/proxmenux/vfio-bind.bdfs</code>. También aplica la política de conflicto elegida a cada VM/LXC afectada. Si la config del host realmente cambió, ejecuta <code>update-initramfs -u -k all</code> — si no, salta ese paso."
"body": "Tras confirmar, el script escribe los cambios en el host: <code>vfio.conf</code>, la lista de módulos bloqueados, los módulos y, para NVIDIA, la regla udev por BDF en <code>/etc/udev/rules.d/10-proxmenux-vfio-bind.rules</code> y el estado BDF en <code>/etc/proxmenux/vfio-bind.bdfs</code>. También aplica la política de conflictos elegida a cada VM/LXC afectado. Si la configuración del host ha cambiado, ejecuta <code>update-initramfs -u -k all</code> y después <code>proxmox-boot-tool refresh</code>; si no ha cambiado, omite ambos comandos."
},
"reboot": {
"title": "Reiniciar",
@@ -257,7 +257,7 @@
"<strong>Hecho.</strong> El 2FA está ahora activo. La próxima vez que te logues, el panel pide primero la contraseña; una vez aceptada pide el código actual de 6 dígitos."
],
"setupStep4Sub": [
"<em>Camino fácil:</em> en la app, pulsa <em>Añadir cuenta</em> → <em>Escanear código QR</em>, apunta la cámara al QR en la pantalla. La app nombra la entrada automáticamente (algo como <code>ProxMenux Monitor (tu-usuario)</code>) y empieza a mostrar un código de 6 dígitos que se refresca cada 30 segundos.",
"<em>Camino fácil:</em> en la app, pulsa <em>Añadir cuenta</em> → <em>Escanear código QR</em>, apunta la cámara al QR en la pantalla. La app nombra la entrada automáticamente (algo como <code>ProxMenux Monitor (your-username)</code>) y empieza a mostrar un código de 6 dígitos que se refresca cada 30 segundos.",
"<em>Plan B manual</em> (cuando escanear no es posible — p. ej. configurando en el mismo móvil con el que abriste el panel): pulsa <em>Añadir cuenta</em> → <em>Introducir clave de setup</em>. Escribe cualquier nombre (p. ej. <em>Proxmox Monitor</em>), pega la cadena Base32 del diálogo, deja <em>Tipo</em> como <em>Basado en tiempo</em>, guarda."
],
"testTitle": "Prueba antes de hacer logout",
@@ -319,7 +319,7 @@
"heading": "Secure Gateway (Tailscale)",
"intro": "Los reverse proxies son la respuesta clásica a \"llegar al panel desde fuera\" pero requieren un dominio público, certificado y un puerto abierto en el borde. <strong>Secure Gateway</strong> es la alternativa cero-puertos que viene dentro del propio Monitor — una app desplegable preconstruida que levanta un LXC Alpine ejecutando <a>Tailscale</a> como subnet router. Una vez unido a tu tailnet, cada dispositivo en él puede llegar al Monitor en la propia IP LAN del host — desde un portátil de vacaciones, un móvil con 5G u otro nodo — sin exponer TCP 8008 a internet.",
"calloutTitle": "Por qué esto es cómodo",
"calloutBody": "La URL se mantiene igual que en la LAN — <code>http://&lt;ip-lan-proxmox&gt;:8008</code> funciona donde Tailscale funcione. Sin certificados, sin DNS, sin port forwarding. El propio Monitor ve la petición viniendo de una IP de tailnet (típicamente <code>100.x.y.z</code>), así que el log de auth y el hook de Fail2Ban siguen funcionando como en la LAN.",
"calloutBody": "La URL se mantiene igual que en la LAN — <code>http://&lt;proxmox-lan-ip&gt;:8008</code> funciona donde Tailscale funcione. Sin certificados, sin DNS, sin port forwarding. El propio Monitor ve la petición viniendo de una IP de tailnet (típicamente <code>100.x.y.z</code>), así que el log de auth y el hook de Fail2Ban siguen funcionando como en la LAN.",
"deployBody": "El flujo de despliegue es una sola pantalla — elige el storage LXC del host, pega un auth-key de Tailscale (generado en <a>login.tailscale.com/admin/settings/keys</a>), elige qué subnets anunciar, pulsa Deploy. El LXC tarda ~30 segundos en arrancar y se registra en el tailnet automáticamente.",
"outro": "El despliegue paso a paso, la configuración de subnet-routes, las ACLs de Tailscale y el modo Exit Node se documentan por separado en <link>Dashboard → Security → Secure Gateway</link> — ahí vive el wizard de despliegue en la UI del panel. Esta página solo cubre el patrón de acceso."
},
@@ -55,7 +55,7 @@
"heading": "Convenciones",
"items": [
"Todas las peticiones y respuestas son JSON salvo que se indique explícitamente (la descarga de logs es texto plano, <code>/api/prometheus</code> es text/plain en formato OpenMetrics, el log de tareas es texto plano).",
"Los endpoints que modifican estado con éxito devuelven <code>'{'\"success\": true, ...'}'</code>. Las respuestas de error usan un estado HTTP no-2xx con <code>'{'\"success\": false, \"error\": \"'<'motivo'>'\"'}'</code>.",
"Los endpoints que modifican estado con éxito devuelven <code>'{'\"success\": true, ...'}'</code>. Las respuestas de error usan un estado HTTP no-2xx con <code>'{'\"success\": false, \"error\": \"'<'reason'>'\"'}'</code>.",
"Los endpoints de listado aceptan <code>limit</code>, <code>offset</code>, <code>since</code> opcionales y filtros específicos por categoría vía query string.",
"Los campos de tiempo se devuelven como segundos epoch Unix o ISO-8601 con zona horaria explícita, nunca como cadenas de locale."
]
@@ -174,7 +174,7 @@
"syncVsAsyncBody": "Las acciones a nivel de sistema (power del host, PVE update, self-update de ProxMenux) pueden tardar minutos — corren en su propia unit systemd transitoria y exponen un endpoint <code>.../status</code> más un <code>DELETE</code> para cancelar. Las acciones VM / LXC (start, stop, shutdown, reboot, backup) son rápidas y usan el estilo fire-and-return que la UI del Monitor ya expone: el POST devuelve el resultado directo. Ambos estilos comparten el mismo modelo de autenticación (JWT o token de API de larga duración).",
"curlTitle": "Ejemplo con curl",
"curlBody": "Disparar una actualización de PVE y hacer polling hasta que termine — exactamente la misma secuencia que ejecutaría una automatización de Home Assistant o un playbook de Ansible:",
"curlCode": "TOKEN=<tu token full_admin>\n\ncurl -sSf -X POST \\\n -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/run\n\nwhile true; do\n state=$(curl -sSf -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/status | jq -r .state)\n [ \"$state\" != \"running\" ] && break\n sleep 30\ndone\necho \"estado final: $state\"",
"curlCode": "TOKEN=<your full_admin token>\n\ncurl -sSf -X POST \\\n -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/run\n\nwhile true; do\n state=$(curl -sSf -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/status | jq -r .state)\n [ \"$state\" != \"running\" ] && break\n sleep 30\ndone\necho \"final state: $state\"",
"haTitle": "Snippet de integración con Home Assistant",
"haBody": "Un sensor <code>rest</code> hace polling del estado y un <code>rest_command</code> dispara la actualización. Conecta ambos a un botón del dashboard y a las automatizaciones que quieras:",
"haCode": "# configuration.yaml\nsensor:\n - platform: rest\n resource: https://pve.local:8008/api/system/pve-update/status\n name: pve_update_state\n value_template: \"{{ value_json.state }}\"\n scan_interval: 60\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\nrest_command:\n pve_update:\n url: https://pve.local:8008/api/system/pve-update/run\n method: POST\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\n # Encender VM 100 (funciona igual para LXC — mismo endpoint)\n vm_100_start:\n url: https://pve.local:8008/api/vms/100/control\n method: POST\n content_type: 'application/json'\n payload: '{\"action\": \"start\"}'\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\n # Backup de la VM 100 al storage 'pbs-main'\n vm_100_backup:\n url: https://pve.local:8008/api/vms/100/backup\n method: POST\n content_type: 'application/json'\n payload: '{\"storage\": \"pbs-main\", \"mode\": \"snapshot\", \"compress\": \"zstd\"}'\n headers:\n Authorization: \"Bearer !secret proxmenux_token\""
@@ -101,7 +101,7 @@
],
"sourcesHeading": "Fuentes para la versión disponible",
"sources": [
"<strong>Repositorio de GitHub</strong>: último lanzamiento o etiqueta de un repositorio público <code>propietario/nombre</code>.",
"<strong>Repositorio de GitHub</strong>: último lanzamiento o etiqueta de un repositorio público <code>owner/name</code>.",
"<strong>HTTP JSON</strong>: un punto final público y una ruta como <code>data.version</code> o <code>releases[0].tag_name</code>.",
"<strong>Docker Hub</strong>: etiquetas versionadas filtradas con una expresión regular. La vista previa muestra etiquetas reales coincidentes antes de guardar.",
"Las etiquetas móviles como <code>latest</code>, <code>stable</code> o <code>lts</code> no contienen una versión. Esas imágenes se siguen por digest desde las actualizaciones de imágenes Docker."
@@ -110,8 +110,8 @@
"No incluyas <code>pct exec</code>; ProxMenux ya entra en el contenedor y ejecuta el comando como root."
],
"exampleLead": "Ejemplo de procedimiento completo dentro del contenedor:",
"example": "cd /opt/mi-app && ./update.sh",
"callout": "Un comando de versión como <code>miapp --version</code> solo lee una versión; no instala nada. Los comandos se ejecutan con privilegios administrativos y deben revisarse con el mismo cuidado que un comando de shell como root."
"example": "cd /opt/my-app && ./update.sh",
"callout": "Un comando de versión como <code>myapp --version</code> solo lee una versión; no instala nada. Los comandos se ejecutan con privilegios administrativos y deben revisarse con el mismo cuidado que un comando de shell como root."
},
"bulk": {
"heading": "Actualización en bloque",
@@ -142,7 +142,7 @@
"La espera tras una versión solo se aplica a las apps seleccionadas con seguimiento. Las apps sin seguimiento ejecutan su actualizador cuando vence la programación.",
"El estado de la última ejecución diferencia entre éxito, finalización parcial, error, retención de seguridad y ausencia de elementos pendientes. Después de la primera ejecución programada, <strong>Actualizaciones → Actualizaciones programadas → Ver log</strong> abre la salida completa capturada del actualizador y de los scripts secundarios que haya ejecutado.",
"Después de cada ejecución, ProxMenux comprueba el marcador estándar de Debian que indica si es necesario reiniciar. Cuando hace falta, la pestaña Actualizaciones y la notificación de finalización lo indican; el aviso se elimina cuando ese LXC se inicia o reinicia.",
"En el host Proxmox, los logs de las ejecuciones programadas se guardan en <code>/usr/local/share/proxmenux/logs/lxc-updates/</code> con el nombre <code>&lt;VMID&gt;-scheduled-&lt;id-de-ejecución&gt;.log</code>. Se conservan los diez últimos logs de cada LXC y los archivos más antiguos se eliminan automáticamente.",
"En el host Proxmox, los logs de las ejecuciones programadas se guardan en <code>/usr/local/share/proxmenux/logs/lxc-updates/</code> con el nombre <code>&lt;VMID&gt;-scheduled-&lt;run-id&gt;.log</code>. Se conservan los diez últimos logs de cada LXC y los archivos más antiguos se eliminan automáticamente.",
"Este historial corresponde a las actualizaciones programadas. Una actualización manual muestra su salida en tiempo real en la ventana de ejecución del Monitor y no crea un log de ejecución programada en ese directorio.",
"Las programaciones externas detectadas de Proxmox VE Helper-Scripts se muestran aparte para hacer visible cualquier automatización coincidente."
],
@@ -186,7 +186,7 @@
},
{
"problem": "Una actualización programada indica que es necesario reiniciar",
"resolution": "Abre <strong>Ver log</strong> para revisar la ejecución completada y reinicia ese LXC. ProxMenux elimina el aviso mediante el evento de ciclo de vida existente cuando el contenedor vuelve a arrancar."
"resolution": "Abre Ver registro para revisar la ejecución completada y después reinicia ese LXC. ProxMenux borra el aviso cuando el evento de ciclo de vida detecta el nuevo arranque."
}
]
},
@@ -37,7 +37,7 @@
"headingHref": "https://gethomepage.dev",
"intro": "Homepage es un panel de aplicaciones totalmente estático y personalizable. ProxMenux Monitor se enchufa vía el widget <code>customapi</code> integrado — pega una entrada de servicio en <code>services.yaml</code>, reinicia Homepage y la tarjeta aparece con números en vivo.",
"iconCalloutTitle": "El logo oficial de ProxMenux está en dashboardicons.com",
"iconCalloutBody": "Las guías de abajo usan <code>icon: proxmenux.png</code>. Homepage resuelve automáticamente los nombres de archivo simples contra <a1>dashboardicons.com</a1> — una librería de iconos curada para paneles autoalojados. La entrada de ProxMenux vive en <a2>dashboardicons.com/icons/external/proxmenux</a2> y Homepage la descarga en el primer render. La misma búsqueda funciona para miles de otras herramientas (Telegram, Discord, Grafana, Tailscale, etc.) — basta con escribir <code>icon: &lt;nombre&gt;.png</code> en cualquier entrada de servicio.",
"iconCalloutBody": "Las guías de abajo usan <code>icon: proxmenux.png</code>. Homepage resuelve automáticamente los nombres de archivo simples contra <a1>dashboardicons.com</a1> — una librería de iconos curada para paneles autoalojados. La entrada de ProxMenux vive en <a2>dashboardicons.com/icons/external/proxmenux</a2> y Homepage la descarga en el primer render. La misma búsqueda funciona para miles de otras herramientas (Telegram, Discord, Grafana, Tailscale, etc.) — basta con escribir <code>icon: &lt;name&gt;.png</code> en cualquier entrada de servicio.",
"imageAlt": "Panel Homepage mostrando tres tarjetas de ProxMenux Monitor (EDGE, VOID, DREAM) con uptime, CPU, RAM y temperatura para cada host Proxmox",
"imageCaption": "Tres instancias de ProxMenux Monitor renderizadas como tarjetas Homepage — uptime, CPU, RAM y temperatura de CPU leídas en vivo desde <code>/api/system</code> en cada host cada 10 s.",
"basicTitle": "Widget básico — sin autenticación",
@@ -94,7 +94,7 @@
"twoColTipBody": "Reemplaza cualquier par de tarjetas (p. ej. <em>Sistema</em> + <em>VMs</em>, o <em>Almacenamiento</em> + <em>Red</em>) con un único <code>horizontal-stack</code> envolviendo ambas, para que siempre se rendericen lado a lado independientemente del ancho de pantalla:",
"twoColTipOutro": "En móvil la fila se mantiene comprimida; el auto layout de HA (sin horizontal-stack) refluye mejor a anchos estrechos.",
"step6Title": "6 · Automatizaciones",
"step6Body": "Tres automatizaciones que cubren los escenarios reactivos más comunes — reemplaza <code>notify.mobile_app_&lt;tu_movil&gt;</code> por el servicio notify que uses:",
"step6Body": "Tres automatizaciones que cubren los escenarios reactivos más comunes — reemplaza <code>notify.mobile_app_&lt;your_phone&gt;</code> por el servicio notify que uses:",
"logoTitle": "Sobre el logo de ProxMenux",
"logoBody": "La tarjeta picture-entity en la parte superior del YAML Lovelace descarga el logo oficial de ProxMenux desde <a1>dashboardicons.com</a1> — una librería de iconos gratuita curada para paneles autoalojados. La entrada de ProxMenux vive en <a2>dashboardicons.com/icons/external/proxmenux</a2>. Home Assistant descarga el SVG sobre HTTPS en el primer render y lo cachea.",
"logoBrokenTitle": "Si la tarjeta del logo muestra una imagen rota",
@@ -120,7 +120,7 @@
"tokenTipTitle": "Token vía archivo o env, no inline",
"tokenTipBody": "Para despliegues en producción evita poner el token inline. Prometheus soporta <code>credentials_file: /etc/prometheus/secrets/proxmenux.token</code> como alternativa — guarda el token en un archivo 0600 y deja que Prometheus lo lea.",
"step2Title": "2 · Verifica el scrape con un par de queries",
"step2Body": "Antes de configurar Grafana, confirma que Prometheus realmente tiene los datos. Abre la propia UI de Prometheus en <code>http://&lt;host-prometheus&gt;:9090</code>, pulsa <em>Query</em> y ejecuta cualquiera de estas — deberías obtener números en vivo de tu host Proxmox:",
"step2Body": "Antes de configurar Grafana, confirma que Prometheus realmente tiene los datos. Abre la propia UI de Prometheus en <code>http://&lt;prometheus-host&gt;:9090</code>, pulsa <em>Query</em> y ejecuta cualquiera de estas — deberías obtener números en vivo de tu host Proxmox:",
"headerQuery": "Query",
"headerConfirms": "Qué confirma",
"verifyRows": [
@@ -44,7 +44,7 @@
"Arranca el hilo de fondo de despacho. El hilo hace polling de la cola de eventos y camina cada evento por la pipeline diagramada arriba."
],
"activeAlt": "Tarjeta de notificaciones activada con pestañas de canales, nombre visible y opciones avanzadas de IA",
"activeCaption": "Estado activo: pestañas Telegram, Gotify, Discord, Email, Pushover y Apprise, nombre visible, categorías por canal y opciones avanzadas de IA."
"activeCaption": "Estado activo: pestañas de canales en la parte superior (Telegram / Gotify / Discord / correo electrónico / Pushover / Apprise), campo Nombre para mostrar, lista de categorías de cada canal y sección desplegable <em>Avanzado: mejora con IA</em>."
},
"sources": {
"heading": "Fuentes de eventos",
@@ -119,7 +119,7 @@
"groupItems": [
"Añade el bot al grupo como miembro (y hazlo admin si el grupo lo requiere para publicar).",
"Envía cualquier mensaje en el grupo.",
"Abre <code>https://api.telegram.org/bot&lt;TU_TOKEN&gt;/getUpdates</code> en un navegador. Busca <code>chat.id</code> en la respuesta JSON — para grupos es un número negativo, para supergrupos empieza con <code>-100</code>.",
"Abre <code>https://api.telegram.org/bot&lt;YOUR_TOKEN&gt;/getUpdates</code> en un navegador. Busca <code>chat.id</code> en la respuesta JSON — para grupos es un número negativo, para supergrupos empieza con <code>-100</code>.",
"Para supergrupos con <em>Topics</em> activado, anota también el <code>message_thread_id</code> del tema al que quieres apuntar — eso va en el campo opcional <em>Topic ID</em>."
],
"groupAlt": "Formulario de canal Telegram con Bot Token (enmascarado), Chat ID negativo prefijado con -100 indicando un supergrupo, y Topic ID 3 configurado para entregar a un tema específico",
@@ -203,7 +203,7 @@
"stepsTitle": "Pasos",
"steps": [
"Elige el servicio destino en la <a>wiki de Apprise</a> y copia la plantilla de URL para él. Cada página de servicio muestra el esquema exacto a usar (<code>ntfy://</code>, <code>matrix://</code>, <code>pover://</code>, <code>slack://</code>…) más cualquier token, canal u hostname requerido.",
"Rellena los placeholders con tus propias credenciales. Por ejemplo, un topic de ntfy.sh tiene aspecto de <code>ntfy://ntfy.sh/mi-topic</code>; una URL de Pushover tiene aspecto de <code>pover://user@token</code>; una URL de Matrix tiene aspecto de <code>matrix://user:pass@host:port/#room</code>.",
"Sustituye los marcadores por tus credenciales. Ejemplos: ntfy.sh <code>ntfy://ntfy.sh/my-topic</code>; Pushover <code>pover://user@token</code>; Matrix <code>matrix://user:pass@host:port/#room</code>.",
"Pega la URL final en el campo <em>Apprise URL</em> en la pestaña Apprise del panel Notifications y guarda.",
"Pulsa <em>Send Test</em> para verificar que la URL es alcanzable y las credenciales se aceptan."
],
@@ -295,7 +295,7 @@
"rows": [
{
"stage": "1. Deduplicación por huella",
"what": "Cada evento genera una huella (<code>event_type + campos clave de data</code>). Las huellas idénticas dentro de una ventana corta se consideran duplicados del primero.",
"what": "Cada evento genera una huella (<code>event_type + key fields from data</code>). Las huellas idénticas dentro de una ventana corta se consideran duplicados del primero.",
"tunable": "No — lógica interna del dispatcher."
},
{
@@ -339,7 +339,7 @@
"<strong>Llamadores remotos.</strong> Cinco capas se apilan encima del rate-limiting: un shared secret en la cabecera <code>X-Webhook-Secret</code>, un timestamp de frescura en <code>X-ProxMenux-Timestamp</code> (rechazado si se desvía más allá de la ventana configurada), una búsqueda de caché de replay y una allowlist de IP opcional. El shared secret vive en la tabla de ajustes SQLite del Monitor — no en <code>/etc/pve/priv/notifications.cfg</code> — y se genera en el primer setup. Este camino existe para integraciones personalizadas que hacen POST desde fuera del host; el destino configurado por PVE nunca lo ejercita."
],
"practiceTitle": "En la práctica",
"practiceBody": "El setup de PVE escribe el destino como <code>http://127.0.0.1:8008</code>, así que las notificaciones emitidas por PVE siempre pasan por el camino loopback con seguridad solo rate-limit. El camino de llamador remoto con shared secret es opt-in para integraciones personalizadas — apunta un servicio externo a <code>https://&lt;host-monitor&gt;:&lt;port&gt;/api/notifications/webhook</code> y suministra la cabecera <code>X-Webhook-Secret</code> para usarlo.",
"practiceBody": "El setup de PVE escribe el destino como <code>http://127.0.0.1:8008</code>, así que las notificaciones emitidas por PVE siempre pasan por el camino loopback con seguridad solo rate-limit. El camino de llamador remoto con shared secret es opt-in para integraciones personalizadas — apunta un servicio externo a <code>https://&lt;monitor-host&gt;:&lt;port&gt;/api/notifications/webhook</code> y suministra la cabecera <code>X-Webhook-Secret</code> para usarlo.",
"actionsIntro": "El Monitor gestiona este destino a través de tres acciones en la pestaña Settings:",
"actionsItems": [
"<strong>Setup</strong> — corre automáticamente cuando activas Notifications. Crea la entrada en <code>/etc/pve/notifications.cfg</code>. El archivo solo se escribe cuando su contenido tiene que cambiar, y se guarda un backup del anterior en <code>/usr/local/share/proxmenux/backups/pve-notifications/</code> (los tres más recientes). No se escribe nada mientras <code>/etc/pve</code> no está montado: un Monitor que arranca durante un reinicio de <code>pve-cluster</code> registra la entrada cuando vuelve.",
@@ -1,8 +1,8 @@
{
"meta": {
"title": "Backup y reinicio de interfaces | ProxMenux Documentation",
"title": "Backup y reinicio de interfaces | Documentación de ProxMenux",
"description": "Snapshot manual, navegación y restauración de backups de /etc/network/interfaces almacenados en /var/backups/proxmenux/. Incluye un reinicio del servicio de red con confirmación y una vista rápida de la configuración en vivo.",
"ogTitle": "Backup y reinicio de interfaces | ProxMenux Documentation",
"ogTitle": "Backup y reinicio de interfaces | Documentación de ProxMenux",
"ogDescription": "Snapshot y restauración de la configuración de red de Proxmox; reinicia el servicio de red con confirmación."
},
"header": {
@@ -27,7 +27,7 @@
"heading": "Crear backup de red",
"body": "Copia el <code>/etc/network/interfaces</code> actual al directorio de backups con un timestamp nuevo. Ya está — sin análisis, sin prompts, solo un snapshot.",
"whenTitle": "Cuándo hacer un backup manual",
"whenBody": "Antes de editar <code>/etc/network/interfaces</code> a mano, antes de instalar un paquete que pueda tocar la stack de red (p. ej. NetworkManager, Open vSwitch) o antes de cualquier cambio de hardware. Las reparaciones guiadas ya hacen snapshot automáticamente — esta opción es para los momentos <em>manuales</em>."
"whenBody": "Antes de editar <code>/etc/network/interfaces</code> a mano, antes de instalar un paquete que pueda modificar la pila de red (p. ej. NetworkManager, Open vSwitch) o antes de cualquier cambio de hardware. Las reparaciones guiadas ya hacen un backup automáticamente; esta opción es para las operaciones <em>manuales</em>."
},
"restore": {
"heading": "Restaurar backup de red",
@@ -96,7 +96,7 @@
"tail": " — la razón más habitual por la que un backup acaba aquí."
},
{
"label": "Análisis de config y limpieza guiada",
"label": "Análisis de configuración y limpieza guiada",
"href": "/docs/network/config-analysis",
"tailRich": " — también escribe en <code>/var/backups/proxmenux/</code> automáticamente."
},
@@ -1,8 +1,8 @@
{
"meta": {
"title": "Análisis de bridges y reparación guiada | ProxMenux Documentation",
"title": "Análisis de bridges y reparación guiada | Documentación de ProxMenux",
"description": "Detecta bridges vmbrX con puertos físicos ausentes o inválidos (típico tras una re-enumeración PCI), los reporta con comandos de shell propuestos y ofrece una reparación guiada de 5 pasos con backup obligatorio.",
"ogTitle": "Análisis de bridges y reparación guiada | ProxMenux Documentation",
"ogTitle": "Análisis de bridges y reparación guiada | Documentación de ProxMenux",
"ogDescription": "Auditar y reparar los puertos de bridge de Proxmox tras cambios de hardware, con flujo guiado y rollback seguro."
},
"header": {
@@ -35,7 +35,7 @@
"bridgeLabel": "Analizar (solo lectura)",
"bridgeDetail": "ip link show enp3s0\n→ no existe",
"targetLabel": "Informe + sugerencia",
"targetDetail": "❌ enp3s0: NOT FOUND\nReemplazar por: eno1\n(aún sin cambios)"
"targetDetail": "❌ enp3s0: NO ENCONTRADO\nReemplazar por: eno1\n(aún sin cambios)"
}
},
"diagram2": {
@@ -50,7 +50,7 @@
},
"step1": {
"heading": "Paso 1: análisis (solo lectura)",
"intro": "Seleccionar <strong>Analizar configuración de bridges</strong> aborta inmediatamente si el host no usa la stack clásica de Debian/Proxmox. Si no, recorre cada bridge y reporta:",
"intro": "Al seleccionar <strong>Analizar configuración de bridges</strong>, la herramienta se detiene inmediatamente si el host no usa la pila clásica de Debian/Proxmox. En caso contrario, recorre todos los bridges e informa de:",
"items": [
"Nombre del bridge, estado actual (UP / DOWN), IP asignada.",
"Cada puerto declarado y si existe actualmente (<code>ip link show &lt;port&gt;</code>).",
@@ -76,7 +76,7 @@
},
{
"title": "3. Previsualizar los cambios propuestos",
"body": "Lista exactamente qué bridges se van a tocar y qué sustituciones de puerto se van a hacer. Si el análisis decide que en realidad no hay que arreglar nada (race condition: el puerto volvió), el flujo sale limpio con <em>\"No changes needed.\"</em>",
"body": "Lista exactamente qué bridges se modificarán y qué sustituciones de puertos se harán. Si el análisis determina que no hay nada que reparar porque el puerto ha reaparecido entre las comprobaciones, el proceso termina con <em>«No se necesitan cambios»</em>.",
"tone": "blue"
},
{
@@ -90,7 +90,7 @@
"tone": "emerald"
}
],
"restartTitle": "Reiniciar networking ≠ un undo gratis",
"restartTitle": "Reiniciar la red ≠ deshacer los cambios sin riesgo",
"restartBody": "La reparación se escribe en disco independientemente de si reinicias el servicio. <code>systemctl restart networking</code> aplica el cambio <em>ahora</em>, lo que puede cortar tu sesión SSH si el nuevo puerto es incorrecto. Si rechazas el reinicio, el cambio sigue surtiendo efecto en el siguiente reinicio — confirma antes la nueva config o haz rollback con el comando impreso."
},
"edits": {
@@ -99,8 +99,8 @@
},
"troubleshoot": {
"heading": "Solución de problemas",
"unsupportedTitle": "El análisis aborta con \"Unsupported Network Stack\"",
"unsupportedBody": "El host usa netplan, systemd-networkd o NetworkManager. La herramienta solo soporta <code>/etc/network/interfaces</code>. Cambia el host a la stack clásica primero, o edita la configuración con las herramientas nativas del gestor (p. ej. <code>netplan apply</code>).",
"unsupportedTitle": "El análisis se detiene con «Unsupported Network Stack»",
"unsupportedBody": "El host usa netplan, systemd-networkd o NetworkManager. La herramienta solo admite <code>/etc/network/interfaces</code>. Cambia primero el host a la pila clásica o edita la configuración con las herramientas nativas del gestor (p. ej. <code>netplan apply</code>).",
"noSuggestTitle": "No se imprime sugerencia para un puerto inválido",
"noSuggestBody": "El host no tiene ninguna interfaz física libre (todas están ya en otro bridge o no existen). El análisis cae a sugerir <code>bridge-ports none</code> para que el bridge al menos pueda levantar sin puerto. Añade una NIC o migra puertos entre bridges manualmente antes de volver a ejecutar.",
"stillDownTitle": "La reparación termina pero el bridge sigue DOWN",
@@ -118,7 +118,7 @@
"tail": " — fija los nombres a direcciones MAC para que esto deje de pasar."
},
{
"label": "Análisis de config y limpieza guiada",
"label": "Análisis de configuración y limpieza guiada",
"href": "/docs/network/config-analysis",
"tailRich": " — para bloques <code>iface</code> huérfanos (la otra mitad del mismo problema)."
},
@@ -1,12 +1,12 @@
{
"meta": {
"title": "Análisis de config y limpieza guiada | ProxMenux Documentation",
"title": "Análisis de configuración y limpieza guiada | Documentación de ProxMenux",
"description": "Detecta bloques iface en /etc/network/interfaces que referencian NICs físicas que ya no están en el host. Los reporta y ofrece una eliminación guiada de 5 pasos con backup obligatorio y previsualización por bloque.",
"ogTitle": "Análisis de config y limpieza guiada | ProxMenux Documentation",
"ogTitle": "Análisis de configuración y limpieza guiada | Documentación de ProxMenux",
"ogDescription": "Encuentra y elimina bloques de interfaz huérfanos dejados por cambios de hardware, con previsualización completa y rollback."
},
"header": {
"title": "Análisis de config y limpieza guiada",
"title": "Análisis de configuración y limpieza guiada",
"description": "Recorre cada bloque iface en /etc/network/interfaces y verifica que la NIC física subyacente sigue existiendo. Reporta los bloques huérfanos dejados por cambios de hardware y ofrece una eliminación guiada con backup, previsualización y confirmación por bloque.",
"section": "Red"
},
@@ -18,7 +18,7 @@
"heading": "En qué se diferencia del análisis de bridges",
"headerAspect": "Aspecto",
"headerBridge": "Análisis de bridges",
"headerConfig": "Análisis de config",
"headerConfig": "Análisis de configuración",
"rows": [
{
"aspect": "Mira",
@@ -45,7 +45,7 @@
},
"step1": {
"heading": "Paso 1: análisis (solo lectura)",
"intro": "Aborta inmediatamente si el host no usa la stack clásica. Si no, lista cada interfaz configurada que no sea loopback y reporta su estado:",
"intro": "Se detiene inmediatamente si el host no usa la pila clásica. En caso contrario, lista todas las interfaces configuradas salvo loopback e indica su estado:",
"virtTitle": "Las interfaces virtuales están protegidas",
"virtBody": "Los bridges (<code>vmbrX</code>) y los bonds (<code>bondX</code>) son construcciones virtuales. Pueden no existir legítimamente en el momento de la inspección (p. ej. un bridge aún sin puertos), por lo que el análisis nunca propone eliminarlos — solo NICs físicas."
},
@@ -60,7 +60,7 @@
},
{
"title": "2. Confirmar la lista a eliminar",
"body": "Lista exactamente qué bloques de interfaz física se van a eliminar. Si, entre el análisis y la limpieza, las NICs han reaparecido (p. ej. has reasentado una tarjeta), el flujo sale con <em>\"No cleanup needed.\"</em>",
"body": "Lista exactamente qué bloques de interfaz física se eliminarán. Si las NIC han reaparecido entre el análisis y la limpieza, por ejemplo al volver a insertar una tarjeta, el proceso termina con <em>«No se necesita limpieza»</em>.",
"tone": "blue"
},
{
@@ -91,7 +91,7 @@
},
"troubleshoot": {
"heading": "Solución de problemas",
"notFoundTitle": "El análisis muestra mi NIC nueva como \"NOT FOUND\"",
"notFoundTitle": "El análisis muestra mi NIC nueva como «NO ENCONTRADO»",
"notFoundBody": "El kernel ve el dispositivo con un nombre distinto al que hay en el fichero. Ejecuta <code>ip link show</code> para obtener el nombre real. Este es exactamente el caso en el que <link>Nombres persistentes de interfaz</link> evitaría el problema de aquí en adelante.",
"tooMuchTitle": "La limpieza eliminó demasiado (un bloque que quería conservar)",
"tooMuchBody": "Restaura desde el backup impreso en el paso 5:",
@@ -1,8 +1,8 @@
{
"meta": {
"title": "Diagnóstico | ProxMenux Documentation",
"description": "Tres comprobaciones de diagnóstico puntuales de solo lectura: Mostrar tabla de rutas, Test de conectividad y Diagnóstico avanzado. Pura inspección — nunca escribe en /etc/network/interfaces y nunca ejecuta un comando modificador (con una excepción explícita y opt-in para purgar NetworkManager cuando se detecta).",
"ogTitle": "Diagnóstico | ProxMenux Documentation",
"title": "Diagnóstico | Documentación de ProxMenux",
"description": "Tres comprobaciones de diagnóstico puntuales de solo lectura: Mostrar tabla de rutas, Test de conectividad y Diagnóstico avanzado. Pura inspección: nunca escribe en /etc/network/interfaces ni ejecuta comandos modificadores, con una excepción explícita que requiere tu aceptación para purgar NetworkManager si se detecta.",
"ogTitle": "Diagnóstico | Documentación de ProxMenux",
"ogDescription": "Diagnóstico de red de solo lectura para el host Proxmox: rutas, alcanzabilidad, estadísticas avanzadas."
},
"header": {
@@ -21,12 +21,12 @@
"connectivity": {
"heading": "Test de conectividad",
"intro": "Envía dos sondas ICMP a tres destinos en secuencia y reporta cada uno. Luego ejecuta un <code>nslookup google.com</code> para verificar la resolución DNS independientemente de ICMP.",
"headerTest": "Test",
"headerTest": "Prueba",
"headerTarget": "Destino",
"headerConfirms": "Qué confirma",
"rows": [
{
"test": "Google DNS",
"test": "DNS de Google",
"target": "8.8.8.8",
"confirms": "Alcanzabilidad externa por IP anycast conocida"
},
@@ -36,7 +36,7 @@
"confirms": "Segunda opinión independiente si Google bloquea ICMP"
},
{
"test": "Gateway",
"test": "Pasarela",
"target": "(ruta por defecto)",
"confirms": "Conectividad L2 / L3 con el router local"
},
@@ -53,7 +53,7 @@
"heading": "Diagnóstico avanzado",
"intro": "Agrega estadísticas de red a nivel global y ejecuta una batería de comprobaciones de problemas comunes. Reporta el número de conexiones activas, puertos en escucha, total de interfaces y señala dos antipatrones explícitamente:",
"items": [
"<strong>NetworkManager corriendo en un host Proxmox.</strong> NetworkManager y el <code>ifupdown</code> de Proxmox entran en conflicto — los dos intentan gestionar interfaces, lo que provoca bridges que flapean o se niegan a levantar. Si se detecta, la herramienta ofrece un prompt interactivo para detenerlo, deshabilitarlo y purgarlo (es el <em>único</em> diagnóstico que puede modificar el sistema, y solo tras consentimiento explícito).",
"<strong>NetworkManager ejecutándose en un host Proxmox.</strong> NetworkManager y el <code>ifupdown</code> de Proxmox entran en conflicto: ambos intentan gestionar las interfaces, lo que provoca bridges con caídas intermitentes o que no se activan. Si se detecta, la herramienta ofrece una confirmación interactiva para detenerlo, deshabilitarlo y purgarlo (es el <em>único</em> diagnóstico que puede modificar el sistema, y solo tras consentimiento explícito).",
"<strong>Direcciones IP duplicadas en distintas interfaces.</strong> Dos interfaces con la misma IPv4 causan conectividad intermitente extremadamente difícil de depurar desde dentro de la VM. Se detecta vía <code>ip -4 addr show | sort | uniq -d</code>."
],
"nmTitle": "El prompt de NetworkManager es la única acción modificadora aquí",
@@ -80,7 +80,7 @@
"tail": " — cuando un vmbrX se queda sin su puerto físico."
},
{
"label": "Análisis de config y limpieza guiada",
"label": "Análisis de configuración y limpieza guiada",
"href": "/docs/network/config-analysis",
"tail": " — cuando una NIC antigua sigue declarada pero ya no está."
},
+8 -8
View File
@@ -1,15 +1,15 @@
{
"meta": {
"title": "Gestión de red en Proxmox — bridges, bonds, diagnóstico, reparación | ProxMenux",
"description": "Diagnóstico de solo lectura, flujos de analizar-y-sugerir y reparaciones guiadas para la stack de red Debian / Proxmox (/etc/network/interfaces). Inspecciona bridges y bonds, ejecuta herramientas de monitorización en vivo, persiste nombres de interfaz, hace backup y reinicia la red de forma segura — con backups obligatorios y previsualizaciones paso a paso.",
"description": "Diagnóstico de solo lectura, análisis con propuestas y reparaciones guiadas para la pila de red Debian / Proxmox (/etc/network/interfaces). Inspecciona bridges y bonds, ejecuta herramientas de monitorización en vivo, fija nombres de interfaz, crea backups y reinicia la red de forma segura, con backups obligatorios y vistas previas paso a paso.",
"ogTitle": "Gestión de red en Proxmox — bridges, bonds, diagnóstico, reparación",
"ogDescription": "Diagnóstico, análisis y reparaciones guiadas para la stack de red de Proxmox con backups obligatorios y previsualizaciones paso a paso.",
"ogDescription": "Diagnóstico, análisis y reparaciones guiadas para la pila de red de Proxmox con backups obligatorios y vistas previas paso a paso.",
"twitterTitle": "Gestión de red en Proxmox | ProxMenux",
"twitterDescription": "Bridges, bonds, diagnóstico y reparaciones guiadas para la stack de red de Proxmox con backups obligatorios."
"twitterDescription": "Bridges, bonds, diagnóstico y reparaciones guiadas para la pila de red de Proxmox con backups obligatorios."
},
"header": {
"title": "Gestión de red",
"description": "Diagnóstico de solo lectura, informes de analizar-y-sugerir y reparaciones guiadas para la stack clásica de red Debian/Proxmox. Cada flujo destructivo hace primero un backup y previsualiza los cambios exactos antes de aplicarlos.",
"description": "Diagnóstico de solo lectura, informes de análisis con propuestas y reparaciones guiadas para la pila de red clásica de Debian/Proxmox. Cada operación destructiva hace primero un backup y muestra los cambios exactos antes de aplicarlos.",
"section": "Red"
},
"intro": {
@@ -52,8 +52,8 @@
]
}
},
"classicTitle": "Solo stack clásica",
"classicBody": "Cada función de análisis y reparación comprueba el gestor de red activo antes de tocar nada. Si el host usa <strong>netplan</strong>, <strong>systemd-networkd</strong> o <strong>NetworkManager</strong>, la herramienta aborta inmediatamente con un mensaje claro — el menú solo soporta la stack clásica de Debian/Proxmox en <code>/etc/network/interfaces</code>. Es intencional: editar un fichero de netplan con reglas escritas para <code>ifupdown</code> corrompería silenciosamente la configuración.",
"classicTitle": "Solo la pila de red clásica",
"classicBody": "Cada función de análisis y reparación comprueba el gestor de red activo antes de tocar nada. Si el host usa <strong>netplan</strong>, <strong>systemd-networkd</strong> o <strong>NetworkManager</strong>, la herramienta se detiene inmediatamente con un mensaje claro: el menú solo admite la pila clásica de Debian/Proxmox en <code>/etc/network/interfaces</code>. Es intencional: editar un fichero de netplan con reglas escritas para <code>ifupdown</code> corrompería silenciosamente la configuración.",
"backups": {
"heading": "Dónde van los backups",
"intro": "Cada reparación guiada, restauración o backup manual escribe una copia con timestamp de <code>/etc/network/interfaces</code> en <code>/var/backups/proxmenux/</code>:",
@@ -61,7 +61,7 @@
},
"readOnlySection": {
"heading": "Inspección de solo lectura",
"body": "El punto de partida cuando algo huele raro. Pura inspección — nunca escribe en <code>/etc/network/interfaces</code> y nunca ejecuta un comando modificador (con una única excepción explícita y opt-in para purgar NetworkManager cuando se detecta). Seguro de usar por SSH en cualquier momento.",
"body": "El punto de partida cuando algo parece ir mal. Pura inspección: nunca escribe en <code>/etc/network/interfaces</code> ni ejecuta comandos que modifiquen el sistema (con una única excepción explícita, que requiere tu aceptación, para purgar NetworkManager cuando se detecta). Se puede usar por SSH en cualquier momento de forma segura.",
"options": [
{
"title": "Diagnóstico",
@@ -82,7 +82,7 @@
"description": "Detecta bridges vmbrX con puertos ausentes o inválidos (típico tras una re-enumeración PCI). Muestra primero un informe; solo repara cuando aceptas el flujo guiado de 5 pasos."
},
{
"title": "Análisis de config y limpieza guiada",
"title": "Análisis de configuración y limpieza guiada",
"description": "Encuentra interfaces físicas declaradas en /etc/network/interfaces que ya no existen (configs huérfanas que dejan cambios de hardware). Las reporta y ofrece una eliminación guiada."
}
]
+9 -9
View File
@@ -1,13 +1,13 @@
{
"meta": {
"title": "Herramientas de monitorización en vivo | ProxMenux Documentation",
"title": "Herramientas de monitorización en vivo | Documentación de ProxMenux",
"description": "Tres lanzadores interactivos de monitorización de red: iftop (ancho de banda en tiempo real por par de hosts), iptraf-ng (monitor de tráfico multimodo) e iperf3 (test de ancho de banda, modo servidor / cliente). Cada uno se instala la primera vez que se usa.",
"ogTitle": "Herramientas de monitorización en vivo | ProxMenux Documentation",
"ogTitle": "Herramientas de monitorización en vivo | Documentación de ProxMenux",
"ogDescription": "Monitorización interactiva de red y test de ancho de banda para el host Proxmox: iftop, iptraf-ng, iperf3."
},
"header": {
"title": "Herramientas de monitorización en vivo",
"description": "Tres lanzadores interactivos para observación de red en tiempo real y medición de ancho de banda: iftop, iptraf-ng e iperf3. Cada herramienta se autoinstala desde apt la primera vez que se usa, corre en primer plano y se sale con la tecla documentada. De solo lectura sobre la configuración del host — solo observan el tráfico.",
"description": "Tres lanzadores interactivos para observar la red en tiempo real y medir el ancho de banda: iftop, iptraf-ng e iperf3. Cada herramienta se instala automáticamente desde apt la primera vez que se usa, se ejecuta en primer plano y se cierra con la tecla indicada. No cambian la configuración de red del host; iperf3 genera tráfico de prueba.",
"section": "Red"
},
"intro": {
@@ -69,7 +69,7 @@
}
],
"exit": "<strong>Salir:</strong> pulsa <kbd>x</kbd> desde cualquier vista (o <kbd>Q</kbd> desde el menú principal). ProxMenux muestra un diálogo recordatorio antes de lanzarlo.",
"logTitle": "El logging captura a fichero",
"logTitle": "Guardar las capturas en un fichero",
"logBody": "Cada modo ofrece registrar las estadísticas capturadas en <code>/var/log/iptraf-ng/</code>. Útil si necesitas un registro de un pico de tráfico — déjalo corriendo, vuelca al fichero, revisa el fichero después en lugar de intentar leer la pantalla en vivo."
},
"iperf3": {
@@ -81,24 +81,24 @@
"headerCli": "CLI equivalente",
"rows": [
{
"mode": "Server",
"mode": "Servidor",
"behaviour": "Escucha en TCP 5201 e imprime resultados de cada test entrante. Se detiene con Ctrl+C.",
"cli": "iperf3 -s"
},
{
"mode": "Client",
"mode": "Cliente",
"behaviour": "Pide la IP / hostname del servidor, conecta, ejecuta un test por defecto de 10 segundos e imprime el informe.",
"cli": "iperf3 -c <target>"
}
],
"workflowIntro": "Flujo típico para probar un enlace 10 GbE entre dos hosts Proxmox:",
"workflow": [
"En el host A, abre el menú Red → <em>Test de ancho de banda (iperf3)</em> → elige <strong>Server</strong>.",
"En el host B, abre la misma entrada de menú → elige <strong>Client</strong> → introduce la IP del host A.",
"En el host A, abre el menú Red → <em>Test de ancho de banda (iperf3)</em> → elige <strong>Servidor</strong>.",
"En el host B, abre la misma entrada de menú → elige <strong>Cliente</strong> → introduce la IP del host A.",
"Espera 10 segundos. Compara la tasa reportada con el máximo teórico del enlace."
],
"sample": "Salida de ejemplo del cliente:",
"flagsTitle": "Flags útiles a mano (desde una shell)",
"flagsTitle": "Opciones útiles para ejecutar a mano desde una shell",
"flagsBody": "<code>-t 60</code> test más largo (60s en lugar de los 10s por defecto), <code>-P 4</code> 4 streams en paralelo (satura más rápido), <code>-R</code> dirección inversa (servidor → cliente), <code>-u -b 100M</code> test UDP a 100 Mbit/s (para mediciones de jitter / pérdida de paquetes), <code>-p 5202</code> usa un puerto distinto (varios tests en paralelo). <code>man iperf3</code> para el set completo.",
"firewallTitle": "Abre el puerto del firewall en el servidor",
"firewallBody": "El servidor escucha en TCP <strong>5201</strong> por defecto. Si corres el servidor dentro de un host Proxmox con un firewall estricto (a nivel de datacenter o de host), permite entrada TCP 5201 desde la IP del cliente durante el test y luego ciérralo. Lo mismo aplica a <code>nftables</code> / <code>iptables</code> en hosts bare metal."
@@ -1,8 +1,8 @@
{
"meta": {
"title": "Nombres persistentes de interfaz | ProxMenux Documentation",
"title": "Nombres persistentes de interfaz | Documentación de ProxMenux",
"description": "Fija los nombres de interfaz de Proxmox (eno1, enp3s0, …) a direcciones MAC mediante ficheros .link de systemd para que los nombres sobrevivan a la re-enumeración PCI, actualizaciones de kernel y al añadir / quitar otras NICs.",
"ogTitle": "Nombres persistentes de interfaz | ProxMenux Documentation",
"ogTitle": "Nombres persistentes de interfaz | Documentación de ProxMenux",
"ogDescription": "Evita que los nombres de interfaz de Proxmox cambien al modificar el hardware. Usa ficheros .link de systemd basados en la dirección MAC."
},
"header": {
@@ -16,7 +16,7 @@
},
"problem": {
"heading": "El problema que resuelve",
"intro": "Linux deriva los nombres de interfaz por defecto a partir de la topología PCI — <code>eno1</code> = onboard, <code>enp3s0</code> = la tarjeta en el bus PCI 3, slot 0, etc. El esquema de naming es determinista <em>dado el mismo layout de hardware</em>. Cambia el layout y los nombres se mueven:",
"intro": "Linux obtiene los nombres de interfaz predeterminados a partir de la topología PCI: <code>eno1</code> = integrada en placa, <code>enp3s0</code> = la tarjeta en el bus PCI 3, slot 0, etc. El esquema de nombres es determinista <em>con la misma disposición de hardware</em>. Si cambia la disposición, cambian los nombres:",
"items": [
"Añade una GPU delante de una NIC existente → el número de bus de la NIC puede cambiar → el nombre cambia.",
"Mueve una tarjeta a otro slot PCIe → el nombre cambia.",
@@ -46,7 +46,7 @@
"headerWhy": "Por qué",
"rows": [
{
"type": "NIC onboard / PCIe",
"type": "NIC integrada / PCIe",
"behaviour": "Se escribe fichero <code>.link</code>",
"why": "Respaldada por un dispositivo PCI real — el caso para el que está la herramienta"
},
@@ -56,7 +56,7 @@
"why": "Tiene una MAC real y se beneficia de la estabilidad de nombre"
},
{
"type": "Bridges (vmbrX)",
"type": "Puentes (vmbrX)",
"behaviour": "Se omite",
"why": "Virtual; el nombre viene de <code>/etc/network/interfaces</code>"
},
@@ -87,7 +87,7 @@
"intro": "Si <code>/etc/systemd/network/</code> ya contiene ficheros <code>.link</code> (de una ejecución anterior u otra herramienta), se copian a un directorio de backup con timestamp antes de generar los nuevos:",
"outro": "Para hacer rollback: copia los ficheros desde el directorio de backup y reinicia.",
"rebootTitle": "Tiene efecto en el siguiente reinicio, no inmediatamente",
"rebootBody": "Los cambios en ficheros <code>.link</code> solo se aplican en el arranque, cuando udev re-enumera los dispositivos. La herramienta reporta <em>\"Changes will apply after reboot\"</em> por este motivo. Renombrar una interfaz en vivo es arriesgado y no se intenta: un <code>vmbr0</code> activo con miembros tendría que reconfigurarse atómicamente, por eso la operación se difiere al siguiente arranque limpio."
"rebootBody": "Los cambios en ficheros <code>.link</code> solo se aplican en el arranque, cuando udev vuelve a enumerar los dispositivos. Por eso la herramienta indica <em>«Los cambios se aplicarán después del reinicio»</em>. No intenta renombrar una interfaz en vivo por el riesgo que supone: un <code>vmbr0</code> activo con interfaces miembro tendría que reconfigurarse de forma atómica, así que la operación se aplaza al siguiente arranque limpio."
},
"afterReboot": {
"heading": "Tras el reinicio",
@@ -100,11 +100,11 @@
},
"troubleshoot": {
"heading": "Solución de problemas",
"emptyTitle": "\"No physical interfaces found\" tras ejecutar la herramienta",
"emptyTitle": "«No se encontraron interfaces físicas» tras ejecutar la herramienta",
"emptyBody": "El host no tiene interfaces respaldadas por PCI / phy80211 visibles para el kernel. Confirma con <code>ls -l /sys/class/net/</code> — cada entrada debería tener un symlink <code>device</code> (PCI) o una entrada <code>phy80211</code> (Wi-Fi). Si faltan ambos para lo que debería ser una NIC real, el driver no está cargado.",
"noChangeTitle": "Tras el reinicio, los nombres no han cambiado como esperaba",
"noChangeBody": "Comprueba que el fichero está presente y bien formado: <code>cat /etc/systemd/network/10-&lt;iface&gt;.link</code>. Después mira los logs de udev: <code>journalctl -u systemd-udevd -b | grep -i link</code>. Una causa habitual es un parámetro de kernel <code>net.ifnames=0</code> residual que deshabilita el naming predictivo por completo — quítalo de <code>/etc/default/grub</code>, ejecuta <code>update-grub</code> y reinicia.",
"undoTitle": "Quiero deshacer el naming persistente",
"undoTitle": "Quiero deshacer los nombres persistentes",
"undoBody": "O bien borra los ficheros <code>.link</code> (<code>rm /etc/systemd/network/10-*.link</code>) o restaura desde el directorio de backup generado en la ejecución anterior. Reinicia para aplicar."
},
"related": {
@@ -116,7 +116,7 @@
"tailRich": " — el camino de recuperación cuando los nombres <em>ya</em> se han movido."
},
{
"label": "Análisis de config y limpieza guiada",
"label": "Análisis de configuración y limpieza guiada",
"href": "/docs/network/config-analysis",
"tail": " — para eliminar bloques huérfanos dejados por los cambios de nombre."
},
@@ -1,17 +1,17 @@
{
"meta": {
"title": "Cómo se traduce una imagen OCI | ProxMenux",
"description": "Del repositorio de la imagen y su archivo Compose a una plantilla revisable, un plan de despliegue y un LXC nativo de Proxmox VE, sin Docker dentro."
"title": "Cómo se adapta una imagen OCI | ProxMenux",
"description": "Del repositorio de la imagen y su archivo Compose a una plantilla que puedes revisar, un plan de despliegue y un LXC nativo de Proxmox VE, sin Docker dentro."
},
"header": {
"title": "Cómo se traduce una imagen OCI",
"description": "Del repositorio de la imagen y su archivo Compose a una plantilla revisable, un plan de despliegue y un LXC nativo, sin instalar Docker dentro.",
"title": "Cómo se adapta una imagen OCI",
"description": "Del repositorio de la imagen y su archivo Compose a una plantilla que puedes revisar, un plan de despliegue y un LXC nativo, sin instalar Docker dentro.",
"section": "OCI manager Apps"
},
"sections": [
{
"id": "pipeline",
"title": "La cadena de traducción",
"title": "El proceso de adaptación",
"blocks": [
{
"mermaid": {
@@ -20,7 +20,7 @@
"repo": "Repositorio de la imagen",
"converter": "Conversor",
"template": "Plantilla JSON",
"blockers": "¿Sin bloqueos?",
"blockers": "¿Sin impedimentos?",
"no": "No",
"yes": "Sí",
"review": "Revisión / overlay",
@@ -30,7 +30,7 @@
}
},
{
"p": "El conversor lee la imagen y el archivo Compose que publica su proyecto y escribe una plantilla JSON. Una plantilla con bloqueos sin traducir pasa por revisión, donde un overlay curado los resuelve, antes de publicarse en el catálogo. Solo las plantillas sin bloqueos se ofrecen para instalar."
"p": "El conversor lee la imagen y el archivo Compose publicados por el proyecto y genera una plantilla JSON. Si quedan requisitos que no se han podido adaptar y que impiden la instalación, la plantilla pasa por una revisión: un archivo de ajustes revisados, llamado overlay, los resuelve antes de publicarla en el catálogo. Solo se ofrecen para instalar las plantillas que no tienen impedimentos pendientes."
}
]
},
@@ -41,10 +41,26 @@
{
"cards": {
"items": [
{ "icon": "archive", "title": "Identidad de la imagen", "body": "Repositorio, etiqueta rolling, arquitectura, digest resuelto y revisión del origen." },
{ "icon": "braces", "title": "Contrato del contenedor", "body": "Entrypoint, Cmd, entorno, usuario, directorio de trabajo, señal de parada, puertos y volúmenes." },
{ "icon": "layers", "title": "Traducción a Proxmox VE", "body": "Recursos, seguridad, puntos de montaje, dispositivos, sysctls, healthchecks y las adaptaciones que necesita cada uno, con su motivo." },
{ "icon": "shield", "title": "Compatibilidad", "body": "Claves admitidas, bloqueos sin traducir y el estado de cada validación." }
{
"icon": "archive",
"title": "Identidad de la imagen",
"body": "Repositorio, etiqueta de actualización continua, arquitectura, digest resuelto y revisión de origen."
},
{
"icon": "braces",
"title": "Contrato del contenedor",
"body": "Entrypoint, Cmd, entorno, usuario, directorio de trabajo, señal de parada, puertos y volúmenes."
},
{
"icon": "layers",
"title": "Adaptación a Proxmox VE",
"body": "Recursos, seguridad, puntos de montaje, dispositivos, sysctls, comprobaciones de estado y las adaptaciones necesarias en cada caso, con su justificación."
},
{
"icon": "shield",
"title": "Compatibilidad",
"body": "Claves compatibles, requisitos pendientes de adaptar que impiden la instalación y estado de cada validación."
}
]
}
}
@@ -56,12 +72,32 @@
"blocks": [
{
"table": {
"headers": ["Origen", "Ejemplo", "Resultado nativo"],
"headers": [
"Origen",
"Ejemplo",
"Resultado nativo"
],
"rows": [
["Metadatos OCI", "<code>Entrypoint</code>, <code>Cmd</code>, <code>User</code>", "Proxmox VE los importa al crear el CT"],
["Docker Compose", "<code>environment</code>, <code>volumes</code>, <code>devices</code>", "entradas de entorno del LXC, <code>mpN</code> y <code>devN</code>"],
["Perfil de ProxMenux", "GPU, healthcheck, credenciales", "preguntas y adaptaciones revisadas"],
["Usuario", "VMID, almacenamiento, red", "el contrato de la instancia"]
[
"Metadatos OCI",
"<code>Entrypoint</code>, <code>Cmd</code>, <code>User</code>",
"Proxmox VE los importa al crear el CT"
],
[
"Docker Compose",
"<code>environment</code>, <code>volumes</code>, <code>devices</code>",
"Entradas de entorno de LXC, <code>mpN</code> y <code>devN</code>"
],
[
"Perfil de ProxMenux",
"GPU, comprobación de estado, credenciales",
"Preguntas y adaptaciones revisadas"
],
[
"Usuario",
"VMID, almacenamiento, red",
"El contrato de la instancia"
]
]
}
}
@@ -69,18 +105,39 @@
},
{
"id": "install",
"title": "Qué ocurre durante una instalación",
"title": "Qué ocurre durante la instalación",
"blocks": [
{
"steps": {
"items": [
{ "title": "Resolver", "body": "Se consulta el registro, se selecciona la arquitectura del host y se fija el digest efectivo de la etiqueta rolling." },
{ "title": "Descargar y verificar", "body": "Skopeo descarga la imagen como archivo OCI, y cada capa se comprueba contra su digest y se descomprime antes de crear nada. Una descarga dañada se repite una vez antes de detener la instalación." },
{ "title": "Construir", "body": "<code>pct create</code> construye el rootfs a partir del archivo y conserva los metadatos oficiales de proceso de la imagen." },
{ "title": "Conectar", "body": "Se añaden los volúmenes, la red, el entorno, los dispositivos y los perfiles de seguridad declarados." },
{ "title": "Consola", "body": "La salida de consola del contenedor se guarda en el host, y la consola de Proxmox VE abre un shell cuando la imagen incluye uno." },
{ "title": "Comprobar", "body": "El primer arranque espera una dirección y la respuesta del servicio; un fallo no se presenta como instalación correcta." },
{ "title": "Registrar", "body": "La configuración efectiva se escribe en el contrato de la instancia que usan las actualizaciones y las recreaciones." }
{
"title": "Resolver la referencia",
"body": "Se consulta el registro, se selecciona la arquitectura del host y se fija el digest concreto al que apunta la etiqueta de actualización continua."
},
{
"title": "Descargar y verificar",
"body": "Skopeo descarga la imagen como un archivo OCI. Antes de crear nada, se verifica el digest de cada capa y se descomprimen todas las capas. Si la descarga está dañada, se vuelve a descargar una vez antes de detener la instalación."
},
{
"title": "Crear el sistema de archivos",
"body": "<code>pct create</code> crea el rootfs a partir del archivo y conserva los metadatos oficiales del proceso de la imagen."
},
{
"title": "Conectar los recursos",
"body": "Se aplican los volúmenes, la red, el entorno, los dispositivos y los perfiles de seguridad declarados."
},
{
"title": "Consola",
"body": "La salida de consola del contenedor se guarda en el host. La consola de Proxmox VE abre una shell si la imagen incluye una."
},
{
"title": "Comprobar",
"body": "En el primer arranque se espera a que el contenedor tenga una dirección y el servicio responda. Si falla, la instalación no se da por completada correctamente."
},
{
"title": "Registrar la configuración",
"body": "La configuración efectiva se guarda en el contrato de la instancia que utilizan las actualizaciones y las recreaciones."
}
]
}
}
@@ -89,7 +146,7 @@
{
"id": "example",
"title": "Ejemplo: una imagen con /config y /downloads",
"intro": "Una definición habitual de Compose y la configuración de Proxmox VE en la que se convierte. Las rutas que espera la aplicación no cambian.",
"intro": "Una definición Compose habitual y la configuración de Proxmox VE que se genera a partir de ella. Las rutas que espera la aplicación no cambian.",
"blocks": [
{
"codeGrid": {
@@ -99,14 +156,14 @@
"code": "image: lscr.io/linuxserver/example:latest\nenvironment:\n - PUID=1000\n - PGID=1000\nvolumes:\n - config:/config\n - /srv/downloads:/downloads\nports:\n - 8080:8080"
},
{
"title": "/etc/pve/lxc/VMID.conf (extracto)",
"title": "/etc/pve/lxc/VMID.conf (fragmento)",
"code": "entrypoint: /init\nmp0: local-lvm:vm-VMID-disk-1,mp=/config,backup=1,size=8G\nmp1: /srv/downloads,mp=/downloads\nnet0: name=eth0,bridge=vmbr0,ip=dhcp,type=veth\nlxc.environment.runtime: PUID=1000\nlxc.environment.runtime: PGID=1000"
}
]
}
},
{
"p": "<code>mp0</code> es un segundo disco que pertenece al contenedor, con el nombre <code>vm-VMID-disk-N</code> en el almacenamiento elegido. Se monta en <code>/config</code> y, con <code>backup=1</code>, forma parte del backup del contenedor. <code>mp1</code> no crea ningún disco: enlaza el directorio del host <code>/srv/downloads</code> con <code>/downloads</code> dentro del LXC. El puerto 8080 no se mapea: el LXC tiene una dirección propia y el servicio responde en ella."
"p": "<code>mp0</code> es un segundo disco que pertenece al contenedor, con el nombre <code>vm-VMID-disk-N</code> en el almacenamiento seleccionado. Se monta en <code>/config</code> y, con <code>backup=1</code>, forma parte del backup del contenedor. <code>mp1</code> no crea ningún disco: monta el directorio del host <code>/srv/downloads</code> en <code>/downloads</code> dentro del LXC. El puerto 8080 no se mapea: el LXC tiene su propia dirección y el servicio responde en ella."
}
]
}
@@ -1,11 +1,11 @@
{
"meta": {
"title": "Instalar una imagen que no está en el catálogo | ProxMenux",
"description": "Traducción de una imagen OCI desde un archivo Compose, una URL, un comando docker run o una referencia de imagen, con revisión de lo que ProxMenux puede reproducir antes de instalarla."
"title": "Instalar una imagen fuera del catálogo | ProxMenux",
"description": "Adapta una imagen OCI a partir de un archivo Compose, una URL, un comando docker run o una referencia de imagen, y revisa qué puede reproducir ProxMenux antes de instalarla."
},
"header": {
"title": "Instalar una imagen que no está en el catálogo",
"description": "Una imagen propia se traduce desde su archivo Compose, un comando docker run o solo su referencia, y el resultado se presenta para revisión antes de crear ningún LXC.",
"title": "Instalar una imagen que no esté en el catálogo",
"description": "Tu imagen se adapta a partir de su archivo Compose, de un comando docker run o de su referencia. El resultado se muestra para que lo revises antes de crear ningún LXC.",
"section": "OCI manager Apps"
},
"sections": [
@@ -14,8 +14,8 @@
"blocks": [
{
"calloutInfo": {
"title": "El mismo conversor, el mismo instalador",
"body": "La opción <strong>Instalar una imagen que no está en el catálogo</strong> utiliza el conversor y el instalador de las plantillas del catálogo. La diferencia es que el contrato se genera en ese momento a partir de la definición aportada y se valida antes de crear ningún LXC."
"title": "El mismo conversor y el mismo instalador",
"body": "La opción <strong>Instalar una imagen que no esté en el catálogo</strong> utiliza el mismo conversor y el mismo instalador que las plantillas del catálogo. La diferencia es que el contrato se genera en ese momento a partir de la definición proporcionada y se valida antes de crear ningún LXC."
}
}
]
@@ -23,45 +23,92 @@
{
"id": "sources",
"title": "Cómo se describe la imagen",
"intro": "La primera pantalla pregunta cómo se describe la imagen. Cuatro formas aportan una definición que se traduce, una quinta usa solo el nombre de la imagen y tres reciben un oci-compose ya escrito.",
"intro": "La primera pantalla pregunta cómo vas a describir la imagen. Cuatro opciones reciben una definición que se adapta, una quinta usa solo el nombre de la imagen y otras tres leen un oci-compose ya escrito.",
"blocks": [
{
"table": {
"headers": ["Opción", "Qué lee"],
"headers": [
"Opción",
"Qué lee"
],
"rows": [
["Pegar su archivo Compose en la terminal", "El YAML se pega en la terminal y termina con Ctrl+D."],
["Leer su archivo Compose desde un archivo de este host", "Una ruta del nodo, <code>/root/docker-compose.yml</code> por defecto. El archivo debe existir y ocupar como máximo 256 KiB."],
["Descargar su archivo Compose desde una dirección", "Una dirección <code>http://</code> o <code>https://</code> que sirva el YAML sin procesar. Se descargan como máximo 256 KiB."],
["Pegar su comando docker run en la terminal", "El comando que publica el proyecto. Se traducen puertos, entorno, volúmenes, dispositivos, capacidades, usuario, memoria compartida y el resto de opciones admitidas."],
["Solo la referencia de la imagen, sin archivo Compose", "Una referencia como <code>ghcr.io/user/application:latest</code>. Se consulta el registro y se conservan los metadatos OCI de la imagen."],
["Pegar un oci-compose en la terminal", "El JSON se pega en la terminal y termina con Ctrl+D. No se traduce: se comprueba y se instala tal como está escrito."],
["Leer un oci-compose desde un archivo de este host", "Un archivo JSON del nodo, <code>/root/oci-compose.json</code> por defecto, de 2 MiB como máximo."],
["Descargar un oci-compose desde una dirección", "Una dirección <code>http://</code> o <code>https://</code> que sirva el archivo JSON. Se descargan como máximo 2 MiB."]
[
"Pegar su archivo Compose en la terminal",
"Pega el YAML en la terminal y termina con Ctrl+D."
],
[
"Leer su archivo Compose desde este host",
"Una ruta del nodo; la predeterminada es <code>/root/docker-compose.yml</code>. El archivo debe existir y no superar los 256 KiB."
],
[
"Descargar su archivo Compose desde una dirección",
"Una dirección <code>http://</code> o <code>https://</code> que sirva el YAML sin procesar. Se descargan como máximo 256 KiB."
],
[
"Pegar su comando docker run en la terminal",
"El comando publicado por el proyecto. Se adaptan los puertos, el entorno, los volúmenes, los dispositivos, las capabilities, el usuario, la memoria compartida y las demás opciones compatibles."
],
[
"Solo la referencia de imagen, sin archivo Compose",
"Una referencia como <code>ghcr.io/user/application:latest</code>. Se consulta el registro y se conservan los metadatos OCI de la imagen."
],
[
"Pegar un oci-compose en la terminal",
"Pega el JSON en la terminal y termina con Ctrl+D. No se convierte: se valida y se instala tal como está escrito."
],
[
"Leer un oci-compose desde este host",
"Un archivo JSON del nodo, <code>/root/oci-compose.json</code> por defecto, de un máximo de 2 MiB."
],
[
"Descargar un oci-compose desde una dirección",
"Una dirección <code>http://</code> o <code>https://</code> que sirva el archivo JSON. Se descargan como máximo 2 MiB."
]
]
}
},
{
"figure": {
"src": "/oci-manager/custom-source-menu.png",
"alt": "Menú que pregunta cómo se describe una imagen que no está en el catálogo",
"caption": "Las formas de describir una imagen que no está en el catálogo."
"alt": "Menú para elegir cómo describir una imagen que no está en el catálogo",
"caption": "Formas de describir una imagen fuera del catálogo."
}
}
]
},
{
"id": "reference-only",
"title": "Qué aporta solo la referencia de la imagen",
"intro": "Una imagen lleva sus metadatos de proceso, pero no todo lo que un archivo Compose suele añadir a su alrededor.",
"title": "Qué aporta una referencia de imagen por sí sola",
"intro": "La imagen contiene los metadatos de su proceso, pero no todo el entorno que suele añadir un archivo Compose.",
"blocks": [
{
"table": {
"headers": ["Se lee de la imagen", "No está en la imagen", "Consecuencia"],
"headers": [
"Se lee de la imagen",
"No está en la imagen",
"Consecuencia"
],
"rows": [
["<code>Entrypoint</code>, <code>Cmd</code>, <code>User</code>, <code>WorkingDir</code> y entorno integrado", "Variables que solo aparecen en la documentación", "Se añaden durante la instalación o con Modificar"],
["Volúmenes declarados por la imagen", "Directorios del host que solo nombra un archivo Compose", "Las rutas adicionales se añaden antes de instalar"],
["Puertos <code>EXPOSE</code>", "La URL, el protocolo o un healthcheck funcional", "Se confirman el puerto y la forma de comprobar el servicio"],
["Arquitecturas y digest del registro", "Dispositivos, privilegios o dependencias externas", "Ninguno se activa sin una definición que lo pida"]
[
"<code>Entrypoint</code>, <code>Cmd</code>, <code>User</code>, <code>WorkingDir</code> y el entorno incorporado",
"Variables que solo figuran en la documentación",
"Se añaden durante la instalación o desde Modificar"
],
[
"Volúmenes declarados por la imagen",
"Directorios del host que solo se indican en Compose",
"Las rutas adicionales se añaden antes de instalar"
],
[
"Puertos <code>EXPOSE</code>",
"La URL, el protocolo o la comprobación funcional del servicio",
"Se confirman el puerto y la forma de comprobar el servicio"
],
[
"Arquitecturas y digest del registro",
"Dispositivos, privilegios o dependencias externas",
"No se habilitan sin una definición que los solicite"
]
]
}
}
@@ -69,29 +116,44 @@
},
{
"id": "review",
"title": "Revisión antes de instalar",
"intro": "Tras traducir la definición, ProxMenux muestra lo que ha entendido antes de pedir VMID, recursos o almacenamiento.",
"title": "Revisar antes de instalar",
"intro": "Tras adaptar la definición, ProxMenux muestra cómo la ha interpretado antes de preguntar el VMID, los recursos o el almacenamiento.",
"blocks": [
{
"steps": {
"items": [
{ "title": "Analizar", "body": "Se leen servicios, imagen, puertos, rutas, entorno, dispositivos, seguridad y healthcheck." },
{ "title": "Consultar el registro", "body": "La imagen debe existir en su registro, y se enumeran las arquitecturas que publica. Un registro privado se lee con la cuenta guardada para él." },
{ "title": "Enumerar lo que no se aplica", "body": "Se enumeran las etiquetas, las redes Docker, los ajustes de Swarm y el resto de claves que no tienen efecto en un LXC." },
{ "title": "Bloquear lo que no puede traducirse", "body": "Una clave sin equivalencia segura aparece en <strong>Lo que no puede traducirse</strong> y la instalación no continúa. Nada se descarta en silencio." },
{ "title": "Pedir los secretos", "body": "Las variables cuyo nombre corresponde a una contraseña, un token o una clave se convierten en preguntas sensibles de la instalación." }
{
"title": "Analizar",
"body": "Se leen servicios, imagen, puertos, rutas, entorno, dispositivos, seguridad y comprobaciones de estado."
},
{
"title": "Consultar el registro",
"body": "La imagen debe existir en el registro y se muestran las arquitecturas publicadas. Si el registro es privado, se utiliza la cuenta guardada para él."
},
{
"title": "Enumerar lo que no se aplica",
"body": "Se enumeran las etiquetas, redes de Docker, ajustes de Swarm y otras claves que no tienen efecto en un LXC."
},
{
"title": "Bloquear opciones sin equivalente seguro",
"body": "Las claves sin equivalente seguro aparecen en <strong>Opciones sin equivalente</strong> e impiden continuar con la instalación. No se descartan silenciosamente."
},
{
"title": "Solicitar secretos",
"body": "Las variables cuyo nombre indica una contraseña, token o clave se solicitan como datos sensibles durante la instalación."
}
]
}
},
{
"figure": {
"src": "/oci-manager/custom-review.png",
"alt": "Resumen de lo que ProxMenux ha entendido de un archivo Compose",
"caption": "El resumen que se muestra antes de que la instalación pida VMID y recursos."
"alt": "Resumen de cómo ProxMenux ha interpretado el archivo Compose",
"caption": "Resumen mostrado antes de que el instalador pregunte el VMID y los recursos."
}
},
{
"p": "Tras aceptar el resumen, el recorrido es el del catálogo: nombre, modo predeterminado o avanzado, VMID, CPU, memoria, red, arranque con el nodo, rutas persistentes, rutas adicionales, dispositivos compatibles y resumen final."
"p": "Tras aceptar el resumen se sigue el mismo asistente que en el catálogo: nombre, modo predeterminado o avanzado, VMID, CPU, memoria, red, arranque con el nodo, rutas persistentes, rutas adicionales, dispositivos compatibles y resumen final."
}
]
},
@@ -118,68 +180,79 @@
{
"id": "oci-compose",
"title": "Un oci-compose escrito a mano",
"intro": "Un oci-compose es el archivo JSON desde el que se instala una aplicación. El catálogo guarda uno por cada aplicación, y el mismo formato puede escribirse a mano e instalarse con esta opción.",
"intro": "Un oci-compose es el archivo JSON a partir del cual se instala una aplicación. El catálogo conserva uno por aplicación. Puedes escribir el mismo formato a mano e instalarlo con esta opción.",
"blocks": [
{
"p": "El que se escribe a mano indica lo que decide su autor: la imagen, sus puertos, variables y volúmenes, y lo que pregunta la instalación. ProxMenux completa el resto al leer el archivo. Puede decir lo que un archivo Compose no puede: el texto de una pregunta, una contraseña generada durante la instalación, un perfil de GPU, el propietario de cada volumen, la comprobación del primer arranque o las credenciales que se muestran al terminar."
"p": "Al escribirlo a mano, el autor decide la imagen, los puertos, las variables, los volúmenes y las preguntas de la instalación. ProxMenux completa el resto al leer el archivo. Permite expresar lo que Compose no incluye: el texto de una pregunta, una contraseña generada durante la instalación, un perfil de GPU, el propietario de cada volumen, la comprobación del primer arranque o las credenciales mostradas al final."
},
{
"steps": {
"items": [
{
"title": "Comprobar",
"body": "Un archivo con errores no se instala. Cada error indica el campo en el que está, y un archivo que no es JSON válido indica la línea y la columna."
"body": "Los archivos con errores no se instalan. Cada error indica el campo afectado; si el JSON no es válido, se muestran la línea y la columna."
},
{
"title": "Revisar",
"body": "Un archivo válido muestra lo que instala: imagen, dirección web, puertos, rutas persistentes, las variables que pide la instalación y los archivos que escribe."
"body": "Si el archivo es válido, se muestra lo que instalará: imagen, dirección web, puertos, rutas persistentes, variables que solicitará el instalador y archivos que escribirá."
},
{
"title": "Instalar",
"body": "La instalación es la de cualquier aplicación del catálogo, con ajustes por defecto o avanzados."
"body": "Se utiliza el mismo instalador que para cualquier aplicación del catálogo, con ajustes predeterminados o avanzados."
}
]
}
},
{
"calloutWarning": {
"title": "Un archivo que decide privilegios",
"body": "Un oci-compose decide qué se monta en el contenedor y con qué privilegios. El resumen lo indica antes de instalar: instala solo archivos que vengan de una fuente de confianza."
"title": "Un archivo que decide los privilegios",
"body": "El oci-compose determina qué se monta dentro del contenedor y con qué privilegios. La revisión lo muestra antes de instalar: utiliza únicamente archivos de fuentes de confianza."
}
},
{
"p": "El formato se describe bloque a bloque, con dos ejemplos completos, en el <readmeLink>README del motor OCI</readmeLink>. El registro de una instalación se lee de la misma forma: solo se usa la plantilla con la que se instaló, y ninguna de las respuestas de esa instalación."
"p": "El <readmeLink>README del motor OCI</readmeLink> explica el formato bloque a bloque e incluye dos ejemplos completos. También se puede leer el registro de una instalación: solo se utiliza la plantilla original, sin incorporar ninguna de las respuestas de aquella instalación."
}
]
},
{
"id": "private-registries",
"title": "Imágenes en registros privados",
"intro": "Una imagen en un registro privado, como un paquete privado de GitHub o un repositorio privado de Docker Hub, se lee con una cuenta guardada en ProxMenux.",
"title": "Imágenes de registros privados",
"intro": "Las imágenes de registros privados, como un paquete privado de GitHub o un repositorio privado de Docker Hub, se consultan con una cuenta guardada en ProxMenux.",
"blocks": [
{
"steps": {
"items": [
{ "title": "El registro rechaza la imagen", "body": "Cuando el registro responde que la imagen necesita una cuenta, la revisión ofrece iniciar sesión en ese registro y vuelve a leer la imagen." },
{ "title": "Iniciar sesión", "body": "Un usuario y una contraseña o un token de acceso que puedan descargar la imagen. El registro los comprueba y solo se guardan si los acepta." },
{ "title": "Instalar y mantener al día", "body": "La instalación descarga la imagen con esa cuenta, y también las actualizaciones, Modificar, Recrear, la vigilancia y la comprobación de actualizaciones del Monitor, en cualquier nodo del clúster." }
{
"title": "El registro deniega el acceso a la imagen",
"body": "Si el registro indica que la imagen requiere una cuenta, la revisión ofrece iniciar sesión en ese registro y vuelve a consultar la imagen."
},
{
"title": "Iniciar sesión",
"body": "Un usuario y una contraseña o token con permiso para descargar la imagen. El registro los comprueba y solo se guardan si los acepta."
},
{
"title": "Instalar y mantener al día",
"body": "Esa cuenta se utiliza para descargar la imagen durante la instalación y también en las actualizaciones, Modificar, Recrear, la vigilancia y la comprobación de actualizaciones del Monitor, en cualquier nodo del clúster."
}
]
}
},
{ "p": "<strong>Cuentas de registro</strong>, en el menú principal de OCI manager Apps, lista las cuentas guardadas por registro y usuario, nunca su secreto. Desde cada cuenta se puede comprobar, descargar o instalar una imagen, y actualizar o eliminar la cuenta." },
{
"p": "<strong>Cuentas de registros</strong>, en el menú principal de OCI manager Apps, muestra las cuentas guardadas por registro y usuario, nunca sus secretos. Desde cada cuenta puedes comprobar, descargar o instalar una imagen, actualizar las credenciales o eliminarlas."
},
{
"list": {
"items": [
"GitHub (<code>ghcr.io</code>): el usuario es la cuenta de GitHub, y la contraseña un token de acceso personal con el permiso <code>read:packages</code>.",
"Docker Hub (<code>docker.io</code>): el usuario es la cuenta de Docker Hub, y la contraseña un token de acceso con permiso de lectura.",
"Otros registros, también uno con su propio puerto como <code>registry.example.com:5000</code>: el usuario y la contraseña o token que da ese registro."
"GitHub (<code>ghcr.io</code>): el usuario es la cuenta de GitHub y la contraseña es un token de acceso personal con permiso <code>read:packages</code>.",
"Docker Hub (<code>docker.io</code>): el usuario es la cuenta de Docker Hub y la contraseña es un token con permiso de lectura.",
"Otros registros, incluidos los que usan un puerto propio como <code>registry.example.com:5000</code>: el usuario y la contraseña o token que proporcione ese registro."
]
}
},
{
"calloutInfo": {
"title": "Dónde se guardan",
"body": "En <code>/etc/pve/priv/proxmenux/registry-auth.json</code>, legible solo por root, en la misma carpeta donde Proxmox guarda las contraseñas de sus almacenamientos. <code>/etc/pve</code> lo comparten todos los nodos del clúster, así que una cuenta añadida en un nodo se usa en todos. El backup del host lo incluye, y al desinstalar ProxMenux se elimina de todos los nodos."
"title": "Dónde se guardan las cuentas",
"body": "En <code>/etc/pve/priv/proxmenux/registry-auth.json</code>, accesible solo por root, en la misma carpeta donde Proxmox guarda las contraseñas de almacenamiento. <code>/etc/pve</code> se comparte entre los nodos del clúster, de modo que una cuenta añadida en un nodo se utiliza en todos. El backup del host incluye ese archivo y desinstalar ProxMenux lo elimina de todos los nodos."
}
}
]
@@ -191,11 +264,11 @@
{
"list": {
"items": [
"Un Dockerfile sin imagen publicada: la imagen debe construirse y publicarse antes en un registro OCI.",
"Un archivo Compose con varios servicios: queda bloqueado porque describe más de una imagen. Esta opción instala un único contenedor.",
"<code>configs</code>, secretos externos o formatos de dispositivo que no pueden traducirse sin ambigüedad.",
"Sustituciones del shell como <code>$(command)</code>: debe escribirse el valor resultante.",
"Opciones de <code>docker run</code> no reconocidas y <code>--env-file</code>: se lee en su lugar un archivo Compose explícito."
"Un Dockerfile sin imagen publicada: primero hay que construir la imagen y publicarla en un registro OCI.",
"Un archivo Compose con varios servicios: se bloquea porque esta opción instala un único servicio por contenedor, aunque varios servicios utilicen la misma imagen.",
"<code>configs</code>, secretos externos o formatos de dispositivo que no puedan adaptarse de forma inequívoca.",
"Sustituciones de shell como <code>$(command)</code>: hay que escribir directamente el valor resultante.",
"Opciones de <code>docker run</code> no reconocidas y <code>--env-file</code>: utiliza un archivo Compose con los valores explícitos."
]
}
}
+203 -44
View File
@@ -19,9 +19,18 @@
{
"flow": {
"nodes": [
{ "label": "Inventario del host", "detail": "/dev/dri/renderD128\nGID 993 · Intel" },
{ "label": "ProxMenux", "detail": "fabricante y\npermisos comprobados" },
{ "label": "LXC", "detail": "mismo dispositivo\nGID efectivo" }
{
"label": "Inventario del host",
"detail": "/dev/dri/renderD128\nGID 993 · Intel"
},
{
"label": "ProxMenux",
"detail": "fabricante y\npermisos comprobados"
},
{
"label": "LXC",
"detail": "mismo dispositivo\nGID efectivo"
}
]
}
}
@@ -33,12 +42,32 @@
"blocks": [
{
"table": {
"headers": ["Origen", "Qué se lee", "Qué hace el instalador"],
"headers": [
"Origen",
"Qué se lee",
"Qué hace el instalador"
],
"rows": [
["Docker Compose", "<code>devices</code>, <code>group_add</code>, <code>deploy.resources</code> y peticiones NVIDIA", "Cada requisito se convierte en una petición de dispositivo que se muestra para revisión"],
["Perfil del catálogo", "El soporte de GPU, Coral, OpenCL, USB o FUSE que tiene realmente la aplicación", "Solo se ofrecen las opciones validadas para esa imagen"],
["Metadatos y documentación de la imagen", "VA-API, Selkies, mods de LinuxServer o el runtime NVIDIA", "Se añaden las variables y la preparación documentadas"],
["Selección del usuario", "Solo CPU, Intel/AMD, OpenCL, NVIDIA o un dispositivo opcional", "La selección se guarda en el contrato de la instancia"]
[
"Docker Compose",
"<code>devices</code>, <code>group_add</code>, <code>deploy.resources</code> y peticiones NVIDIA",
"Cada requisito se convierte en una petición de dispositivo que se muestra para revisión"
],
[
"Perfil del catálogo",
"El soporte de GPU, Coral, OpenCL, USB o FUSE que tiene realmente la aplicación",
"Solo se ofrecen las opciones validadas para esa imagen"
],
[
"Metadatos y documentación de la imagen",
"VA-API, Selkies, mods de LinuxServer o el runtime NVIDIA",
"Se añaden las variables y la preparación documentadas"
],
[
"Selección del usuario",
"Solo CPU, Intel/AMD, OpenCL, NVIDIA o un dispositivo opcional",
"La selección se guarda en el contrato de la instancia"
]
]
}
},
@@ -57,16 +86,52 @@
"blocks": [
{
"table": {
"headers": ["Tipo", "Identificación", "Validación"],
"headers": [
"Tipo",
"Identificación",
"Validación"
],
"rows": [
["Intel/AMD DRM", "<code>/dev/dri/renderD*</code> y <code>/sys/class/drm/NODO/device/vendor</code>", "Un dispositivo de caracteres con fabricante <code>0x8086</code> (Intel) o <code>0x1002</code> (AMD)"],
["OpenCL AMD", "El render node, más <code>/dev/kfd</code> cuando el perfil lo necesita", "Existencia, tipo, fabricante, permisos y compatibilidad declarada"],
["AMD ROCm", "El nodo de render, <code>/dev/kfd</code> y la generación que declara el driver de cómputo en <code>/sys/class/kfd/kfd/topology/nodes/*/properties</code>", "Una generación para la que la imagen ROCm de la aplicación trae kernels, las GPU RDNA2 que incluye y las posteriores, se ofrece tal cual. Las demás GPU de esas familias, como las Radeon 680M y 780M, se ofrecen como experimentales y nunca son la opción propuesta: ROCm no las soporta oficialmente, la aplicación las presenta como la generación de su familia (<code>HSA_OVERRIDE_GFX_VERSION</code>) y el instalador pide confirmación antes de descargar la imagen, que es más grande. Una GPU anterior, como los gráficos integrados de un Ryzen 5000U, no se ofrece e Immich deja el reconocimiento en la CPU"],
["NVIDIA", "<code>nvidia-smi</code> y <code>nvidia-container-cli</code>", "GPU, UUID, bus PCI, versión del driver, Toolkit, nodos <code>/dev/nvidia*</code>, binarios y librerías"],
["Coral PCIe/M.2", "<code>/dev/apex_N</code> y su enlace en <code>/sys/dev/char/MAJOR:MINOR</code>", "Nodo de caracteres, major/minor, propietario, GID y permisos"],
["USB y serie", "<code>/dev/ttyUSB*</code>, <code>/dev/ttyACM*</code> o <code>/dev/bus/usb/BBB/DDD</code>", "Nodo de caracteres; en USB también fabricante, producto y número de serie cuando sysfs los publica"],
["KVM, TUN, FUSE, vídeo y SCSI genérico", "<code>/dev/kvm</code>, <code>/dev/net/tun</code>, <code>/dev/fuse</code>, <code>/dev/videoN</code> o <code>/dev/sgN</code>", "Ruta admitida, tipo de nodo y permisos efectivos"],
["Unidad óptica", "<code>/dev/srN</code>", "Un dispositivo de bloques"]
[
"Intel/AMD DRM",
"<code>/dev/dri/renderD*</code> y <code>/sys/class/drm/NODE/device/vendor</code>",
"Un dispositivo de caracteres con fabricante <code>0x8086</code> (Intel) o <code>0x1002</code> (AMD)"
],
[
"OpenCL AMD",
"El render node, más <code>/dev/kfd</code> cuando el perfil lo necesita",
"Existencia, tipo, fabricante, permisos y compatibilidad declarada"
],
[
"AMD ROCm",
"El nodo de render, <code>/dev/kfd</code> y la generación que declara el driver de cómputo en <code>/sys/class/kfd/kfd/topology/nodes/*/properties</code>",
"Una generación para la que la imagen ROCm de la aplicación trae kernels, las GPU RDNA2 que incluye y las posteriores, se ofrece tal cual. Las demás GPU de esas familias, como las Radeon 680M y 780M, se ofrecen como experimentales y nunca son la opción propuesta: ROCm no las soporta oficialmente, la aplicación las presenta como la generación de su familia (<code>HSA_OVERRIDE_GFX_VERSION</code>) y el instalador pide confirmación antes de descargar la imagen, que es más grande. Una GPU anterior, como los gráficos integrados de un Ryzen 5000U, no se ofrece e Immich deja el reconocimiento en la CPU"
],
[
"NVIDIA",
"<code>nvidia-smi</code> y <code>nvidia-container-cli</code>",
"GPU, UUID, bus PCI, versión del driver, Toolkit, nodos <code>/dev/nvidia*</code>, binarios y librerías"
],
[
"Coral PCIe/M.2",
"<code>/dev/apex_N</code> y su enlace en <code>/sys/dev/char/MAJOR:MINOR</code>",
"Nodo de caracteres, major/minor, propietario, GID y permisos"
],
[
"USB y serie",
"<code>/dev/ttyUSB*</code>, <code>/dev/ttyACM*</code> o <code>/dev/bus/usb/BBB/DDD</code>",
"Nodo de caracteres; en USB también fabricante, producto y número de serie cuando sysfs los publica"
],
[
"KVM, TUN, FUSE, vídeo y SCSI genérico",
"<code>/dev/kvm</code>, <code>/dev/net/tun</code>, <code>/dev/fuse</code>, <code>/dev/videoN</code> o <code>/dev/sgN</code>",
"Ruta admitida, tipo de nodo y permisos efectivos"
],
[
"Unidad óptica",
"<code>/dev/srN</code>",
"Un dispositivo de bloques"
]
]
}
}
@@ -79,12 +144,30 @@
{
"steps": {
"items": [
{ "title": "La plantilla ofrece sus perfiles", "body": "Por ejemplo solo CPU, Intel/AMD VA-API, OpenCL AMD, OpenCL Intel o NVIDIA. Las opciones pertenecen a la imagen, no a un menú común." },
{ "title": "Se elige un perfil", "body": "Define los nodos de dispositivo, el entorno, los mods o el runtime que necesita la aplicación." },
{ "title": "Se propone una ruta", "body": "Para DRM, <code>/dev/dri/renderD128</code>, que puede cambiarse en un host con varios render nodes. Para USB o serie se selecciona el nodo concreto." },
{ "title": "Validación", "body": "Se comprueban existencia, tipo, fabricante admitido, permisos y GID. Una discrepancia detiene la operación." },
{ "title": "Se escribe el contrato", "body": "Ruta, modo, GID, acceso de escritura y perfil quedan registrados para las actualizaciones y las recreaciones." },
{ "title": "Conexión y prueba", "body": "<code>pct set</code> añade la entrada <code>devN</code> y después se comprueba el acceso dentro del LXC. Las imágenes de LinuxServer se comprueban también como usuario <code>abc</code>." }
{
"title": "La plantilla ofrece sus perfiles",
"body": "Por ejemplo solo CPU, Intel/AMD VA-API, OpenCL AMD, OpenCL Intel o NVIDIA. Las opciones pertenecen a la imagen, no a un menú común."
},
{
"title": "Se elige un perfil",
"body": "Define los nodos de dispositivo, el entorno, los mods o el runtime que necesita la aplicación."
},
{
"title": "Se propone una ruta",
"body": "Para DRM, <code>/dev/dri/renderD128</code>, que puede cambiarse en un host con varios render nodes. Para USB o serie se selecciona el nodo concreto."
},
{
"title": "Validación",
"body": "Se comprueban existencia, tipo, fabricante admitido, permisos y GID. Una discrepancia detiene la operación."
},
{
"title": "Se escribe el contrato",
"body": "Ruta, modo, GID, acceso de escritura y perfil quedan registrados para las actualizaciones y las recreaciones."
},
{
"title": "Conexión y prueba",
"body": "<code>pct set</code> añade la entrada <code>devN</code> y después se comprueba el acceso dentro del LXC. Las imágenes de LinuxServer se comprueban también como usuario <code>abc</code>."
}
]
}
}
@@ -98,10 +181,22 @@
{
"codeGrid": {
"items": [
{ "title": "Intel/AMD VA-API", "code": "dev0: path=/dev/dri/renderD128,mode=0660,gid=993,deny-write=0" },
{ "title": "Coral PCIe/M.2", "code": "dev0: path=/dev/apex_0,mode=0660,gid=GID,deny-write=0" },
{ "title": "Un dispositivo USB concreto", "code": "dev0: path=/dev/bus/usb/003/004,mode=0660,gid=GID,deny-write=0" },
{ "title": "OpenCL AMD", "code": "dev0: path=/dev/dri/renderD128,mode=0660,gid=GID,deny-write=0\ndev1: path=/dev/kfd,mode=0660,gid=GID,deny-write=0" }
{
"title": "Intel/AMD VA-API",
"code": "dev0: path=/dev/dri/renderD128,mode=0660,gid=993,deny-write=0"
},
{
"title": "Coral PCIe/M.2",
"code": "dev0: path=/dev/apex_0,mode=0660,gid=GID,deny-write=0"
},
{
"title": "Un dispositivo USB concreto",
"code": "dev0: path=/dev/bus/usb/003/004,mode=0660,gid=GID,deny-write=0"
},
{
"title": "OpenCL AMD",
"code": "dev0: path=/dev/dri/renderD128,mode=0660,gid=GID,deny-write=0\ndev1: path=/dev/kfd,mode=0660,gid=GID,deny-write=0"
}
]
}
},
@@ -116,13 +211,37 @@
"blocks": [
{
"table": {
"headers": ["Perfil", "Traducción", "Se ofrece cuando"],
"headers": [
"Perfil",
"Configuración resultante",
"Se ofrece cuando"
],
"rows": [
["Intel/AMD VA-API", "Render node de <code>/dev/dri</code>", "La aplicación admite aceleración de vídeo"],
["OpenCL", "Render node, <code>/dev/kfd</code> si hace falta y el mod oficial", "La imagen o el perfil lo documentan"],
["NVIDIA", "Dispositivos y librerías del driver del host", "El host tiene un driver operativo y NVIDIA Container Toolkit"],
["Coral", "<code>/dev/apex_0</code> o el bus USB", "El perfil declara soporte de Coral (Frigate)"],
["USB, serie, FUSE", "Un dispositivo concreto, un árbol validado o una función LXC", "El contrato lo pide"]
[
"Intel/AMD VA-API",
"Render node de <code>/dev/dri</code>",
"La aplicación admite aceleración de vídeo"
],
[
"OpenCL",
"Render node, <code>/dev/kfd</code> si hace falta y el mod oficial",
"La imagen o el perfil lo documentan"
],
[
"NVIDIA",
"Dispositivos y librerías del driver del host",
"El host tiene un driver operativo y NVIDIA Container Toolkit"
],
[
"Coral",
"<code>/dev/apex_0</code> o el bus USB",
"El perfil declara soporte de Coral (Frigate)"
],
[
"USB, serie, FUSE",
"Un dispositivo concreto, un árbol validado o una función LXC",
"El contrato lo pide"
]
]
}
}
@@ -145,7 +264,9 @@
"p": "Estos dos comandos, en el host, muestran si el driver y el Toolkit están disponibles:"
},
{
"shell": { "code": "nvidia-smi -L\nnvidia-container-cli --version" }
"shell": {
"code": "nvidia-smi -L\nnvidia-container-cli --version"
}
},
{
"p": "En un host cuyo driver se instaló por otros medios, el Toolkit se instala desde el repositorio estable oficial:"
@@ -159,7 +280,9 @@
"p": "El inventario que usa OCI manager Apps es la salida de:"
},
{
"shell": { "code": "nvidia-container-cli list --device all --libraries --binaries --firmwares --ipcs" }
"shell": {
"code": "nvidia-container-cli list --device all --libraries --binaries --firmwares --ipcs"
}
},
{
"calloutInfo": {
@@ -170,10 +293,26 @@
{
"cards": {
"items": [
{ "icon": "cpu", "title": "Inventario desde el driver", "body": "<code>nvidia-container-cli</code> enumera los nodos de dispositivo, los binarios, el firmware y las librerías del driver instalado." },
{ "icon": "refresh", "title": "Sin versión fija", "body": "La plantilla no nombra archivos de librería. El perfil se genera a partir del host actual." },
{ "icon": "shield", "title": "Montajes de solo lectura", "body": "Las librerías del host se montan en solo lectura en lugar de copiarse dentro del contenedor." },
{ "icon": "hardDrive", "title": "Cambios de driver", "body": "Tras un cambio de driver, el inventario se genera de nuevo antes de que arranquen los LXC afectados." }
{
"icon": "cpu",
"title": "Inventario desde el driver",
"body": "<code>nvidia-container-cli</code> enumera los nodos de dispositivo, los binarios, el firmware y las librerías del driver instalado."
},
{
"icon": "refresh",
"title": "Sin versión fija",
"body": "La plantilla no nombra archivos de librería. El perfil se genera a partir del host actual."
},
{
"icon": "shield",
"title": "Montajes de solo lectura",
"body": "Las librerías del host se montan en solo lectura en lugar de copiarse dentro del contenedor."
},
{
"icon": "hardDrive",
"title": "Cambios de driver",
"body": "Tras un cambio de driver, el inventario se genera de nuevo antes de que arranquen los LXC afectados."
}
]
}
},
@@ -209,12 +348,32 @@
"blocks": [
{
"table": {
"headers": ["Petición", "Traducción", "Alcance"],
"headers": [
"Petición",
"Configuración resultante",
"Alcance"
],
"rows": [
["<code>/dev/dvb</code>, <code>/dev/snd</code> o <code>/dev/bus/usb</code>", "Cada nodo de caracteres del árbol recibe su propia entrada <code>devN</code> con el modo y el GID del host", "Solo el árbol pedido, no el resto de <code>/dev</code>"],
["<code>/dev/fuse</code>", "El nodo y, cuando el perfil lo necesita, la función <code>fuse=1</code>", "FUSE por sí solo no publica montajes a otros LXC"],
["<code>/dev/net/tun</code>", "Una entrada <code>devN</code> en la misma ruta dentro del LXC", "La configuración de la VPN o de la red queda en la aplicación"],
["<code>/dev/kvm</code>", "Una entrada <code>devN</code> validada", "Solo se ofrece cuando el contrato lo pide"]
[
"<code>/dev/dvb</code>, <code>/dev/snd</code> o <code>/dev/bus/usb</code>",
"Cada nodo de caracteres del árbol recibe su propia entrada <code>devN</code> con el modo y el GID del host",
"Solo el árbol pedido, no el resto de <code>/dev</code>"
],
[
"<code>/dev/fuse</code>",
"El nodo y, cuando el perfil lo necesita, la función <code>fuse=1</code>",
"FUSE por sí solo no publica montajes a otros LXC"
],
[
"<code>/dev/net/tun</code>",
"Una entrada <code>devN</code> en la misma ruta dentro del LXC",
"La configuración de la VPN o de la red queda en la aplicación"
],
[
"<code>/dev/kvm</code>",
"Una entrada <code>devN</code> validada",
"Solo se ofrece cuando el contrato lo pide"
]
]
}
}
+125 -40
View File
@@ -1,11 +1,11 @@
{
"meta": {
"title": "OCI manager Apps | ProxMenux",
"description": "Imágenes OCI oficiales ejecutadas como contenedores LXC nativos de Proxmox VE, con datos persistentes, dispositivos, aplicaciones multicontenedor y actualizaciones transaccionales."
"description": "Ejecuta imágenes OCI oficiales como contenedores LXC nativos de Proxmox VE, con datos persistentes, acceso a dispositivos, aplicaciones con varios contenedores y actualizaciones transaccionales."
},
"header": {
"title": "OCI manager Apps",
"description": "Las imágenes OCI oficiales se ejecutan como contenedores LXC nativos de Proxmox VE. La imagen sigue siendo la que publica su responsable; ProxMenux reproduce el entorno que Docker Compose habría creado a su alrededor.",
"description": "Las imágenes OCI oficiales se ejecutan como contenedores LXC nativos de Proxmox VE. Se utiliza la misma imagen que publica su desarrollador; ProxMenux reproduce el entorno que Docker Compose habría creado a su alrededor.",
"section": "OCI manager Apps"
},
"sections": [
@@ -15,34 +15,43 @@
{
"calloutInfo": {
"title": "Una imagen OCI, un LXC nativo",
"body": "Dentro de los contenedores no se ejecuta ningún motor Docker. Proxmox VE importa el sistema de archivos de la imagen y sus metadatos OCI, y la aplicación pasa a ser el proceso principal de un LXC nativo, gestionado con las mismas herramientas que cualquier otro contenedor del nodo."
"body": "No se ejecuta Docker Engine dentro de los contenedores. Proxmox VE importa el sistema de archivos de la imagen y sus metadatos OCI; la aplicación pasa a ser el proceso principal de un LXC nativo, administrado con las mismas herramientas que cualquier otro contenedor del nodo."
}
},
{
"flow": {
"nodes": [
{ "label": "Origen", "detail": "Imagen OCI\nCompose y documentación" },
{ "label": "ProxMenux", "detail": "Contrato JSON\nvalidación y plan" },
{ "label": "Proxmox VE", "detail": "LXC nativo\nvolúmenes y dispositivos" }
{
"label": "Origen",
"detail": "Imagen OCI\nCompose y documentación"
},
{
"label": "ProxMenux",
"detail": "Contrato JSON\nvalidación y planificación"
},
{
"label": "Proxmox VE",
"detail": "LXC nativo\nvolúmenes y dispositivos"
}
],
"caption": "La aplicación no se reconstruye: su entorno se reproduce de forma declarativa."
"caption": "Se utiliza la aplicación original; su entorno se define de forma declarativa y se reproduce."
}
}
]
},
{
"id": "where",
"title": "Dónde se encuentra",
"intro": "OCI manager Apps se abre desde la opción <strong>OCI manager Apps (Technology Preview)</strong> del menú principal de ProxMenux, en el nodo Proxmox y como root. Su primera pantalla ofrece:",
"title": "Dónde encontrarlo",
"intro": "OCI manager Apps se abre desde la opción <strong>OCI manager Apps (Technology Preview)</strong> del menú principal de ProxMenux, en el nodo Proxmox y como root. La primera pantalla ofrece:",
"blocks": [
{
"list": {
"items": [
"<strong>Buscar aplicaciones</strong>: búsqueda por nombre en todo el catálogo.",
"<strong>Todas las aplicaciones</strong>: el catálogo completo, con el número de aplicaciones.",
"<strong>Gestionar aplicaciones OCI instaladas</strong>: actualizar, modificar, eliminar o recuperar lo instalado.",
"<strong>Cuentas de registro</strong>: las cuentas con las que se instalan y actualizan imágenes de registros privados.",
"<strong>Instalar una imagen que no está en el catálogo</strong>: traducción de un archivo Compose, un comando <code>docker run</code> o una referencia de imagen.",
"<strong>Buscar aplicaciones</strong>: busca por nombre en todo el catálogo.",
"<strong>Todas las aplicaciones</strong>: muestra el catálogo completo y su número de aplicaciones.",
"<strong>Gestionar aplicaciones OCI instaladas</strong>: actualiza, modifica, elimina o recupera las aplicaciones que ya has instalado.",
"<strong>Cuentas de registros</strong>: administra las cuentas utilizadas para instalar y actualizar imágenes de registros privados.",
"<strong>Instalar una imagen que no esté en el catálogo</strong>: adapta un archivo Compose, un comando <code>docker run</code> o una referencia de imagen.",
"Las categorías del catálogo, cada una con su número de aplicaciones."
]
}
@@ -50,40 +59,72 @@
{
"figure": {
"src": "/oci-manager/main-menu.png",
"alt": "Pantalla principal de OCI manager Apps con la búsqueda, todas las aplicaciones, la gestión, la imagen propia y las categorías del catálogo",
"alt": "Pantalla principal de OCI manager Apps con búsqueda, listado completo, gestión de aplicaciones, imágenes fuera del catálogo y categorías.",
"caption": "Pantalla principal de OCI manager Apps."
}
},
{
"p": "Al seleccionar una aplicación se muestra su descripción, la imagen que ejecuta y dos modos de instalación: <strong>Instalar con la configuración predeterminada</strong>, que pregunta solo lo que decide toda instalación (almacenamiento, dónde van los datos, dirección e inicio), e <strong>Instalar con la configuración avanzada</strong>, que abre cada decisión en orden: VMID y recursos, el almacenamiento de cada ruta, el bridge y los dispositivos."
"p": "Al seleccionar una aplicación se muestran su descripción, la imagen que utiliza y dos modos de instalación. <strong>Instalar con ajustes predeterminados</strong> solo pregunta lo esencial de cada instalación: almacenamiento, ubicación de los datos, dirección y arranque. <strong>Instalar con ajustes avanzados</strong> recorre todas las decisiones en orden: VMID y recursos, almacenamiento de cada ruta, puente de red y dispositivos."
},
{
"p": "Una aplicación probada en real muestra <strong>Verificado</strong> en esa vista y aparece marcada con ✓ en las listas, tanto si se probó en el laboratorio de ProxMenux como si la probó la comunidad."
"p": "Las aplicaciones que se han probado realmente muestran <strong>Verificado</strong> en esa vista y una marca ✓ en las listas, tanto si la prueba se hizo en el laboratorio de ProxMenux como si la realizó la comunidad."
}
]
},
{
"id": "beta",
"title": "Por qué es una Technology Preview",
"title": "Por qué lleva la etiqueta Technology Preview",
"blocks": [
{ "p": "OCI manager Apps lleva la etiqueta <strong>Technology Preview</strong> que Proxmox VE da a los contenedores de aplicación creados a partir de imágenes OCI, introducidos en Proxmox VE 9.1. Se refiere a aquello sobre lo que funciona OCI manager Apps, no al motor de ProxMenux: el comportamiento de esos contenedores todavía puede cambiar entre versiones de Proxmox VE. La etiqueta se mantiene hasta que Proxmox VE dé ese soporte por estable." },
{ "p": "El motor de OCI manager Apps (instalación, actualización, modificación, recreación, backups, restauración, migración y vigilancia) está probado en el laboratorio de ProxMenux. Cada aplicación se prueba por separado: las que se han probado de verdad muestran <strong>Verified</strong> y llevan una ✓ en las listas." }
{
"p": "OCI manager Apps mantiene la etiqueta <strong>Technology Preview</strong> que Proxmox VE asigna a los contenedores de aplicaciones creados a partir de imágenes OCI, cuyo soporte se introdujo en Proxmox VE 9.1. La etiqueta se refiere a la tecnología sobre la que funciona OCI manager Apps, no al motor de ProxMenux: el comportamiento de estos contenedores puede cambiar entre versiones de Proxmox VE. Se mantendrá hasta que Proxmox VE considere estable ese soporte."
},
{
"p": "El motor de OCI manager Apps se prueba en el laboratorio de ProxMenux: instalación, actualización, modificación, recreación, backups, restauración, migración y vigilancia. Cada aplicación se verifica por separado. Las que se han probado realmente muestran <strong>Verificado</strong> y llevan un ✓ en las listas."
}
]
},
{
"id": "translation",
"title": "Lo que Docker expresa y en qué lo convierte OCI manager Apps",
"title": "Cómo describe Docker los requisitos y cómo los aplica OCI manager Apps",
"blocks": [
{
"table": {
"headers": ["Necesidad", "Docker la expresa como", "OCI manager Apps la convierte en"],
"headers": [
"Requisito",
"Cómo lo expresa Docker",
"Cómo lo aplica OCI manager Apps"
],
"rows": [
["Ejecutar la aplicación", "<code>image</code>, <code>entrypoint</code>, <code>command</code>", "rootfs OCI y proceso principal del LXC"],
["Conservar la configuración", "<code>volumes: /config</code>", "un disco <code>mpN</code> persistente incluido en el backup, o un directorio del host"],
["Publicar el servicio", "<code>ports</code>", "una dirección propia del LXC y la URL de acceso al servicio"],
["Usar hardware", "<code>devices</code>, <code>group_add</code>", "entradas <code>devN</code> con el GID efectivo del host y un perfil validado"],
["Conectar dependencias", "<code>networks</code>, <code>depends_on</code>", "un bridge privado, direcciones fijas, orden de arranque y healthchecks"],
["Actualizar", "<code>pull</code> y recrear", "un rootfs nuevo con el mismo contrato persistente"]
[
"Ejecutar la aplicación",
"<code>image</code>, <code>entrypoint</code>, <code>command</code>",
"El rootfs de la imagen OCI y el proceso principal del LXC"
],
[
"Conservar la configuración",
"<code>volumes: /config</code>",
"Un volumen persistente <code>mpN</code> incluido en el backup, o bien un directorio del host."
],
[
"Publicar el servicio",
"<code>ports</code>",
"Una dirección propia para el LXC y la URL de acceso al servicio."
],
[
"Usar hardware",
"<code>devices</code>, <code>group_add</code>",
"Entradas <code>devN</code> con el GID efectivo del host y un perfil validado."
],
[
"Conectar las dependencias",
"<code>networks</code>, <code>depends_on</code>",
"Un puente de red privado, direcciones fijas, orden de arranque y comprobaciones de estado."
],
[
"Actualizar",
"Descargar con <code>pull</code> y recrear",
"Un rootfs nuevo que mantiene el mismo contrato de persistencia."
]
]
}
}
@@ -91,15 +132,31 @@
},
{
"id": "kept",
"title": "Qué se mantiene y qué cambia",
"title": "Qué se conserva y qué cambia",
"blocks": [
{
"cards": {
"items": [
{ "icon": "archive", "title": "Se mantiene", "body": "La imagen oficial, sus rutas internas, su entorno, su proceso de arranque y su documentación funcional." },
{ "icon": "boxes", "title": "Se adapta", "body": "El entorno de ejecución: red, persistencia, dispositivos, permisos y dependencias usan primitivas LXC nativas de Proxmox VE." },
{ "icon": "shield", "title": "No se traduce", "body": "Una clave de Compose sin equivalencia segura figura como bloqueo. Las plantillas con bloqueos no se ofrecen, y las opciones sensibles se confirman durante la instalación." },
{ "icon": "refresh", "title": "Se registra", "body": "Digest de la imagen, recursos, rutas, red, dispositivos y pertenencia a una pila quedan en el contrato de la instancia, que las actualizaciones y las recreaciones reproducen." }
{
"icon": "archive",
"title": "Se conserva",
"body": "La imagen oficial, sus rutas internas, su entorno, su proceso de arranque y su documentación de uso."
},
{
"icon": "boxes",
"title": "Se adapta",
"body": "El entorno de ejecución: la red, la persistencia, los dispositivos, los permisos y las dependencias utilizan los mecanismos nativos de LXC de Proxmox VE."
},
{
"icon": "shield",
"title": "Sin equivalente",
"body": "Una opción de Compose sin una equivalencia segura se registra como un impedimento para la instalación. Las plantillas con impedimentos no se ofrecen para instalar, y las opciones sensibles requieren confirmación durante el asistente."
},
{
"icon": "refresh",
"title": "Se registra",
"body": "El digest de la imagen, los recursos, las rutas, la red, los dispositivos y la pertenencia a una pila se guardan en el contrato de la instancia. Las actualizaciones y recreaciones reproducen ese contrato."
}
]
}
}
@@ -112,13 +169,41 @@
{
"next": {
"items": [
{ "label": "Cómo se traduce una imagen OCI", "href": "/docs/oci-manager/architecture", "tail": "de la imagen y su archivo Compose a un LXC nativo." },
{ "label": "Instalar una imagen que no está en el catálogo", "href": "/docs/oci-manager/custom-image", "tail": "Compose, docker run o una referencia de imagen." },
{ "label": "Datos, rutas y red", "href": "/docs/oci-manager/storage-network", "tail": "discos del contenedor, directorios del host, montajes Rclone y direcciones." },
{ "label": "Dispositivos y aceleración", "href": "/docs/oci-manager/hardware", "tail": "GPU, NVIDIA, Coral, USB y otros dispositivos." },
{ "label": "Aplicaciones multicontenedor", "href": "/docs/oci-manager/stacks", "tail": "aplicación, base de datos y caché como LXC coordinados." },
{ "label": "Instalar, actualizar y modificar", "href": "/docs/oci-manager/lifecycle", "tail": "el contrato de la instancia y sus operaciones." },
{ "label": "En ProxMenux Monitor", "href": "/docs/oci-manager/monitor", "tail": "versiones, actualizaciones, salida de consola y terminal." }
{
"label": "Cómo se adapta una imagen OCI",
"href": "/docs/oci-manager/architecture",
"tail": "De la imagen y su archivo Compose a un LXC nativo."
},
{
"label": "Instalar una imagen que no esté en el catálogo",
"href": "/docs/oci-manager/custom-image",
"tail": "Un archivo Compose, un comando docker run o una referencia de imagen."
},
{
"label": "Datos, rutas y red",
"href": "/docs/oci-manager/storage-network",
"tail": "Volúmenes del contenedor, directorios del host, montajes con rclone y direcciones."
},
{
"label": "Dispositivos y aceleración",
"href": "/docs/oci-manager/hardware",
"tail": "GPU, NVIDIA, Coral, USB y otros dispositivos."
},
{
"label": "Aplicaciones con varios contenedores",
"href": "/docs/oci-manager/stacks",
"tail": "Aplicación, base de datos y caché en varios LXC coordinados."
},
{
"label": "Instalar, actualizar y modificar",
"href": "/docs/oci-manager/lifecycle",
"tail": "El contrato de la instancia y sus operaciones."
},
{
"label": "En ProxMenux Monitor",
"href": "/docs/oci-manager/monitor",
"tail": "Versiones, actualizaciones, salida de consola y terminal."
}
]
}
}
@@ -18,7 +18,7 @@
},
{
"code": {
"code": "instances/\n└── 105/\n └── oci-compose.json\n ├── imagen y digest resuelto\n ├── recursos y red\n ├── entorno (secretos protegidos)\n ├── discos del contenedor y directorios del host\n ├── perfil de hardware y dispositivos\n ├── log de consola y modo de terminal\n └── pertenencia a una pila y ciclo de vida"
"code": "instances/\n└── 105/\n └── oci-compose.json\n ├── image and resolved digest\n ├── resources and network\n ├── environment (secrets protected)\n ├── container disks and host directories\n ├── hardware profile and devices\n ├── console log and terminal mode\n └── stack membership and lifecycle"
}
},
{
@@ -86,7 +86,7 @@
"registry": "Registro OCI",
"update": "Actualizar la instancia",
"resolve": "Resolver la etiqueta",
"verify": "Verificar el archivo y preflight",
"verify": "Verificar el archivo y realizar las comprobaciones previas",
"backup": "Detener y respaldar el CT",
"import": "Importar el rootfs nuevo",
"reapply": "Aplicar de nuevo el contrato",
@@ -215,7 +215,7 @@
{
"id": "restore",
"title": "Backup, restauración y otro host",
"intro": "Un backup hecho con vzdump o Proxmox Backup Server incluye el contenedor, sus discos y la copia de su contrato. Lo que la instalación guarda en el host no forma parte de él. <strong>Gestionar aplicaciones OCI instaladas</strong> detecta los contenedores restaurados en un host que no tiene su contrato, un Proxmox recién instalado u otro host, y ofrece registrarlos de nuevo.",
"intro": "Un backup hecho con vzdump o Proxmox Backup Server incluye el contenedor, los discos del contenedor seleccionados para el backup y la copia de su contrato. Lo que la instalación guarda en el host no forma parte de él. <strong>Gestionar aplicaciones OCI instaladas</strong> detecta los contenedores restaurados en un host que no tiene su contrato, un Proxmox recién instalado u otro host, y ofrece registrarlos de nuevo.",
"blocks": [
{
"steps": {
@@ -462,7 +462,7 @@
],
[
"Discos del contenedor",
"Proxmox los mueve con el contenedor. HA necesita que estén en un almacenamiento compartido."
"Proxmox los mueve con el contenedor. HA necesita sus datos disponibles en el nodo de destino, mediante almacenamiento compartido o una configuración de replicación compatible."
],
[
"Directorios del host y dispositivos",
@@ -52,7 +52,7 @@
},
{
"id": "app",
"title": "App",
"title": "Aplicación",
"intro": "La pestaña <appLink>App</appLink> ofrece la aplicación instalada como una detección, con el nombre, el logo, el puerto y el esquema del registro. Al registrarla se abre el editor con el método <strong>Imagen OCI (instalada por ProxMenux)</strong>, que no necesita configuración.",
"blocks": [
{
+200 -46
View File
@@ -4,7 +4,7 @@
"description": "Cómo convierte OCI manager Apps una aplicación con su base de datos y su caché en LXC nativos coordinados: plan, red privada, hook de dependencias, validación y actualizaciones transaccionales."
},
"header": {
"title": "Aplicaciones multicontenedor",
"title": "Aplicaciones con varios contenedores",
"description": "Una aplicación con su base de datos, su caché y otros servicios se convierte en varios LXC nativos coordinados, que se instalan y actualizan como uno solo.",
"section": "OCI manager Apps"
},
@@ -21,7 +21,14 @@
{
"mermaid": {
"chartCode": "flowchart LR\n C[\"Docker Compose\"] --> O[\"{{plan}}\"]\n O --> A[\"{{app}}<br/>{{appNet}}\"]\n O --> D[\"{{db}}<br/>{{private}}\"]\n O --> R[\"{{cache}}<br/>{{private}}\"]\n V1[(\"config\")] --> A\n V2[(\"database\")] --> D\n V3[(\"cache\")] --> R\n D --> A\n R --> A",
"labels": { "plan": "Plan de la pila", "app": "LXC de la aplicación", "appNet": "LAN + privada", "db": "LXC PostgreSQL", "cache": "LXC Valkey", "private": "privada" }
"labels": {
"plan": "Plan de la pila",
"app": "LXC de la aplicación",
"appNet": "LAN + privada",
"db": "LXC PostgreSQL",
"cache": "LXC Valkey",
"private": "privada"
}
}
}
]
@@ -35,14 +42,42 @@
},
{
"table": {
"headers": ["Elemento del plan", "Contenido", "Comprobado antes de crear nada"],
"headers": [
"Elemento del plan",
"Contenido",
"Comprobado antes de crear nada"
],
"rows": [
["Miembros", "Aplicación principal, base de datos, caché, aprendizaje automático y demás dependencias", "VMID únicos, roles conocidos y exactamente un miembro principal"],
["Imágenes", "Referencia rolling, arquitectura y digest resuelto de cada servicio", "Todas existen, admiten la arquitectura y superan la verificación de integridad OCI"],
["Red", "Bridge privado, subred, una dirección fija por servicio y acceso LAN para el miembro principal", "Sin colisión con bridges o subredes existentes y sin direcciones repetidas"],
["Persistencia", "Discos del contenedor, directorios del host, propietarios y backup", "Rutas sin solapamientos, almacenamiento disponible y permisos declarados"],
["Secretos", "Contraseña de la base de datos, claves de la aplicación y credenciales iniciales", "Se generan una vez y solo se entregan a los miembros que los usan"],
["Ciclo de vida", "Orden de arranque, orden de parada y una comprobación de salud por miembro", "La aplicación principal arranca la última y se detiene la primera"]
[
"Miembros",
"Aplicación principal, base de datos, caché, aprendizaje automático y demás dependencias",
"VMID únicos, roles conocidos y exactamente un miembro principal"
],
[
"Imágenes",
"Referencia rolling, arquitectura y digest resuelto de cada servicio",
"Todas existen, admiten la arquitectura y superan la verificación de integridad OCI"
],
[
"Red",
"Bridge privado, subred, una dirección fija por servicio y acceso LAN para el miembro principal",
"Sin colisión con bridges o subredes existentes y sin direcciones repetidas"
],
[
"Persistencia",
"Discos del contenedor, directorios del host, propietarios y backup",
"Rutas sin solapamientos, almacenamiento disponible y permisos declarados"
],
[
"Secretos",
"Contraseña de la base de datos, claves de la aplicación y credenciales iniciales",
"Se generan una vez y solo se entregan a los miembros que los usan"
],
[
"Ciclo de vida",
"Orden de arranque, orden de parada y una comprobación de salud por miembro",
"La aplicación principal arranca la última y se detiene la primera"
]
]
}
}
@@ -55,13 +90,34 @@
{
"steps": {
"items": [
{ "title": "Reservar todos los VMID", "body": "Se comprueban el inventario de Proxmox VE y el registro de instancias. No se adopta un CT existente ni se reutiliza un contrato que todavía pertenece a otra instancia." },
{ "title": "Preparar todas las imágenes", "body": "Todas las imágenes se resuelven, descargan y verifican antes de crear el primer contenedor." },
{ "title": "Crear cada rootfs", "body": "Se importan los metadatos OCI oficiales y se añaden la identidad de instancia de ProxMenux y el rol del miembro." },
{ "title": "Red privada", "body": "Se crean un bridge y una subred y cada miembro recibe su dirección fija; solo el miembro principal recibe además la interfaz de la LAN." },
{ "title": "Persistencia", "body": "Cada base de datos y configuración recibe su propio disco del contenedor; solo los datos destinados a compartirse usan directorios del host." },
{ "title": "Entorno", "body": "Se escriben los endpoints internos, los secretos compartidos y las variables de servicio. La aplicación llega a sus dependencias en sus direcciones privadas reservadas." },
{ "title": "Registro", "body": "Cada miembro registra su configuración nativa, los cambios del rootfs que las actualizaciones deben reproducir y su relación con la pila." }
{
"title": "Reservar todos los VMID",
"body": "Se comprueban el inventario de Proxmox VE y el registro de instancias. No se adopta un CT existente ni se reutiliza un contrato que todavía pertenece a otra instancia."
},
{
"title": "Preparar todas las imágenes",
"body": "Todas las imágenes se resuelven, descargan y verifican antes de crear el primer contenedor."
},
{
"title": "Crear cada rootfs",
"body": "Se importan los metadatos OCI oficiales y se añaden la identidad de instancia de ProxMenux y el rol del miembro."
},
{
"title": "Red privada",
"body": "Se crean un bridge y una subred y cada miembro recibe su dirección fija; solo el miembro principal recibe además la interfaz de la LAN."
},
{
"title": "Persistencia",
"body": "Cada base de datos y configuración recibe su propio disco del contenedor; solo los datos destinados a compartirse usan directorios del host."
},
{
"title": "Entorno",
"body": "Se escriben los endpoints internos, los secretos compartidos y las variables de servicio. La aplicación llega a sus dependencias en sus direcciones privadas reservadas."
},
{
"title": "Registro",
"body": "Cada miembro registra su configuración nativa, los cambios del rootfs que las actualizaciones deben reproducir y su relación con la pila."
}
]
}
}
@@ -74,20 +130,48 @@
"blocks": [
{
"table": {
"headers": ["Servicio", "Comprobación", "Qué demuestra"],
"headers": [
"Servicio",
"Comprobación",
"Qué demuestra"
],
"rows": [
["PostgreSQL", "<code>pg_isready</code> en el CT con el host, el usuario y la base de datos esperados", "El servidor acepta conexiones para la base de datos configurada"],
["Redis / Valkey", "<code>redis-cli</code> o <code>valkey-cli</code> <code>PING</code> contra su dirección privada", "El broker escucha y responde"],
["Aprendizaje automático de Immich", "HTTP <code>GET /ping</code>, más una comprobación del runtime GPU seleccionado", "El servicio responde y la aceleración pedida no ha pasado a CPU"],
["Nextcloud", "<code>GET /status.php</code> con <code>installed=true</code>, <code>maintenance=false</code> y <code>needsDbUpgrade=false</code>", "La inicialización terminó sin migraciones pendientes"],
["Paperless-ngx / Tandoor", "HTTP en la dirección de la LAN y el puerto real del servicio", "El frontend y sus dependencias sirven la aplicación"],
["Aplicación principal", "El endpoint de su plantilla, por ejemplo <code>/api/server/ping</code> en Immich", "La pila completa funciona a través de la aplicación que usa las dependencias"]
[
"PostgreSQL",
"<code>pg_isready</code> en el CT con el host, el usuario y la base de datos esperados",
"El servidor acepta conexiones para la base de datos configurada"
],
[
"Redis / Valkey",
"<code>redis-cli</code> o <code>valkey-cli</code> <code>PING</code> contra su dirección privada",
"El broker escucha y responde"
],
[
"Aprendizaje automático de Immich",
"HTTP <code>GET /ping</code>, más una comprobación del runtime GPU seleccionado",
"El servicio responde y la aceleración pedida no ha pasado a CPU"
],
[
"Nextcloud",
"<code>GET /status.php</code> con <code>installed=true</code>, <code>maintenance=false</code> y <code>needsDbUpgrade=false</code>",
"La inicialización terminó sin migraciones pendientes"
],
[
"Paperless-ngx / Tandoor",
"HTTP en la dirección de la LAN y el puerto real del servicio",
"El frontend y sus dependencias sirven la aplicación"
],
[
"Aplicación principal",
"El endpoint de su plantilla, por ejemplo <code>/api/server/ping</code> en Immich",
"La pila completa funciona a través de la aplicación que usa las dependencias"
]
]
}
},
{
"calloutWarning": {
"title": "running no significa healthy",
"title": "En ejecución no significa que funcione correctamente",
"body": "El estado running solo indica que existe el proceso del LXC. Cuando el servicio ofrece una comprobación mejor, se usa una comprobación exec o HTTP con un tiempo límite. Si un miembro se detiene o no supera su comprobación, la pila no se declara instalada."
}
}
@@ -103,8 +187,14 @@
{
"codeGrid": {
"items": [
{ "title": "Configuración del CT principal", "code": "hookscript: local:snippets/proxmenux-stack-dependencies.sh" },
{ "title": "Contrato privado (ejemplo)", "code": "/etc/pve/priv/proxmenux-stack-VMID.json\n{\n \"schema\": 1,\n \"stack\": \"immich\",\n \"dependencies\": [\n {\"vmid\": 107, \"label\": \"PostgreSQL\", \"healthcheck\": {...}},\n {\"vmid\": 108, \"label\": \"Valkey\", \"healthcheck\": {...}},\n {\"vmid\": 106, \"label\": \"Machine Learning\", \"healthcheck\": {...}}\n ]\n}" }
{
"title": "Configuración del CT principal",
"code": "hookscript: local:snippets/proxmenux-stack-dependencies.sh"
},
{
"title": "Contrato privado (ejemplo)",
"code": "/etc/pve/priv/proxmenux-stack-VMID.json\n{\n \"schema\": 1,\n \"stack\": \"immich\",\n \"dependencies\": [\n {\"vmid\": 107, \"label\": \"PostgreSQL\", \"healthcheck\": {...}},\n {\"vmid\": 108, \"label\": \"Valkey\", \"healthcheck\": {...}},\n {\"vmid\": 106, \"label\": \"Machine Learning\", \"healthcheck\": {...}}\n ]\n}"
}
]
}
},
@@ -121,12 +211,30 @@
{
"steps": {
"items": [
{ "title": "Proxmox VE llama a pre-start", "body": "Antes de arrancar el CT principal, el hook se ejecuta con su VMID y la fase del ciclo de vida." },
{ "title": "Un bloqueo por pila", "body": "<code>flock</code> sobre <code>/run/lock/proxmenux-stack-VMID.lock</code> impide dos secuencias de arranque a la vez." },
{ "title": "Se lee y valida el contrato", "body": "Se exigen un esquema conocido, dependencias numéricas, etiquetas, una comprobación exec, http o running y un tiempo límite positivo." },
{ "title": "Dependencias en orden", "body": "Cada CT debe existir; uno detenido se arranca y uno que ya está en marcha no se reinicia." },
{ "title": "Espera de salud", "body": "La comprobación se ejecuta cada dos segundos y se confirma además que el CT sigue en marcha." },
{ "title": "Arranca el CT principal", "body": "Cuando todas las dependencias están listas, pre-start termina y Proxmox VE arranca la aplicación." }
{
"title": "Proxmox VE llama a pre-start",
"body": "Antes de arrancar el CT principal, el hook se ejecuta con su VMID y la fase del ciclo de vida."
},
{
"title": "Un bloqueo por pila",
"body": "<code>flock</code> sobre <code>/run/lock/proxmenux-stack-VMID.lock</code> impide dos secuencias de arranque a la vez."
},
{
"title": "Se lee y valida el contrato",
"body": "Se exigen un esquema conocido, dependencias numéricas, etiquetas, una comprobación exec, http o running y un tiempo límite positivo."
},
{
"title": "Dependencias en orden",
"body": "Cada CT debe existir; uno detenido se arranca y uno que ya está en marcha no se reinicia."
},
{
"title": "Esperar a que el servicio esté listo",
"body": "La comprobación se ejecuta cada dos segundos y se confirma además que el CT sigue en marcha."
},
{
"title": "Arranca el CT principal",
"body": "Cuando todas las dependencias están listas, pre-start termina y Proxmox VE arranca la aplicación."
}
]
}
},
@@ -138,11 +246,27 @@
},
{
"table": {
"headers": ["Tipo", "Ejemplo", "Arranques posteriores"],
"headers": [
"Tipo",
"Ejemplo",
"Arranques posteriores"
],
"rows": [
["Pila dependiente", "Immich, Nextcloud, aplicación con PostgreSQL", "El hook del CT principal arranca las dependencias y las espera"],
["Suite de aplicaciones", "Suite Arr", "Sin miembro principal: cada LXC sigue su propio <code>onboot</code>"],
["Aplicación simple", "Jellyfin", "Proxmox VE arranca directamente ese LXC"]
[
"Pila dependiente",
"Immich, Nextcloud, aplicación con PostgreSQL",
"El hook del CT principal arranca las dependencias y las espera"
],
[
"Suite de aplicaciones",
"Suite Arr",
"Sin miembro principal: cada LXC sigue su propio <code>onboot</code>"
],
[
"Aplicación simple",
"Jellyfin",
"Proxmox VE arranca directamente ese LXC"
]
]
}
}
@@ -176,21 +300,51 @@
{
"steps": {
"items": [
{ "title": "Cualquier miembro", "body": "El contrato del miembro indica el VMID principal y la lista completa de miembros." },
{ "title": "La pila es reproducible", "body": "Se validan identidades, contratos, hook, adaptaciones y la existencia de una reproducción coordinada para esa receta." },
{ "title": "Primero las imágenes", "body": "La aplicación no se detiene hasta que todos los digests están resueltos, descargados y verificados." },
{ "title": "Detener y respaldar el conjunto", "body": "Los backups nativos verificados se toman con la pila detenida, de modo que aplicación y bases de datos corresponden al mismo momento." },
{ "title": "Actualizar y comprobar cada miembro", "body": "Adaptación, red, montajes, secretos y dispositivos se aplican de nuevo antes de la comprobación de salud de cada miembro." },
{ "title": "Publicar o recuperar todo", "body": "Los contratos nuevos solo se publican cuando todos los miembros pasan. Si uno falla, se restauran todos." }
{
"title": "Cualquier miembro",
"body": "El contrato del miembro indica el VMID principal y la lista completa de miembros."
},
{
"title": "La pila es reproducible",
"body": "Se validan identidades, contratos, hook, adaptaciones y la existencia de una reproducción coordinada para esa receta."
},
{
"title": "Primero las imágenes",
"body": "La aplicación no se detiene hasta que todos los digests están resueltos, descargados y verificados."
},
{
"title": "Detener y respaldar el conjunto",
"body": "Los backups nativos verificados se toman con la pila detenida, de modo que aplicación y bases de datos corresponden al mismo momento."
},
{
"title": "Actualizar y comprobar cada miembro",
"body": "Adaptación, red, montajes, secretos y dispositivos se aplican de nuevo antes de la comprobación de salud de cada miembro."
},
{
"title": "Publicar o recuperar todo",
"body": "Los contratos nuevos solo se publican cuando todos los miembros pasan. Si uno falla, se restauran todos."
}
]
}
},
{
"table": {
"headers": ["Modificar", "Qué cambia", "Qué se conserva"],
"headers": [
"Modificar",
"Qué cambia",
"Qué se conserva"
],
"rows": [
["Rutas y dispositivos extra", "Se añaden al contenedor de la aplicación o se eliminan de él, y el contenedor se reinicia. No se reconstruye nada", "Los datos de la aplicación, su base de datos y los demás contenedores"],
["Qué ejecuta el reconocimiento (Immich)", "El contenedor Machine learning toma la imagen y los dispositivos de la CPU o de una GPU del host. Toda la aplicación se detiene y se actualiza, como en una actualización", "La caché de modelos, la biblioteca y la base de datos. Si algo falla, se restauran los contenedores y la opción anteriores"]
[
"Rutas y dispositivos extra",
"Se añaden al contenedor de la aplicación o se eliminan de él, y el contenedor se reinicia. No se reconstruye nada",
"Los datos de la aplicación, su base de datos y los demás contenedores"
],
[
"Qué ejecuta el reconocimiento (Immich)",
"El contenedor Machine learning toma la imagen y los dispositivos de la CPU o de una GPU del host. Toda la aplicación se detiene y se actualiza, como en una actualización",
"La caché de modelos, la biblioteca y la base de datos. Si algo falla, se restauran los contenedores y la opción anteriores"
]
]
}
},
@@ -220,7 +374,7 @@
"stop": "Detener, primero el principal",
"backup": "Backup verificado de cada CT",
"replace": "Sustituir el rootfs",
"healthy": "¿Todos sanos?",
"healthy": "¿Todos funcionan correctamente?",
"yes": "Sí",
"no": "No",
"commit": "Publicar los contratos",
@@ -1,11 +1,11 @@
{
"meta": {
"title": "Datos, rutas y red | ProxMenux",
"description": "Cómo conserva OCI manager Apps los datos de un contenedor OCI: discos del contenedor, directorios del host, montajes Rclone, direcciones y redes privadas."
"description": "Cómo conserva OCI manager Apps los datos de un contenedor OCI: discos del contenedor, directorios del host, montajes con rclone, direcciones y redes privadas."
},
"header": {
"title": "Datos, rutas y red",
"description": "Qué vive en el rootfs, qué sobrevive a su sustitución, cómo se comparten datos entre contenedores y cómo obtiene cada contenedor su dirección.",
"description": "Qué se guarda en el rootfs, qué sobrevive a su sustitución, cómo se comparten datos entre contenedores y cómo obtiene cada uno su dirección.",
"section": "OCI manager Apps"
},
"sections": [
@@ -14,8 +14,8 @@
"blocks": [
{
"calloutInfo": {
"title": "La persistencia se decide antes de que exista el LXC",
"body": "Los volúmenes que publican la imagen y su archivo Compose se leen antes de crear el contenedor. Cada ruta que debe sobrevivir a una actualización se convierte en un punto de montaje independiente del rootfs, de modo que el rootfs solo contiene lo que pertenece a la imagen y puede sustituirse."
"title": "La persistencia se decide antes de crear el LXC",
"body": "Antes de crear el contenedor se leen los volúmenes declarados por la imagen y por su archivo Compose. Cada ruta que deba conservarse tras una actualización se convierte en un punto de montaje independiente del rootfs. Así, el rootfs solo contiene lo que pertenece a la imagen y puede sustituirse."
}
}
]
@@ -23,17 +23,35 @@
{
"id": "questions",
"title": "Qué pregunta el instalador",
"intro": "La plantilla aporta las rutas que necesita la aplicación. Cada una se sitúa en un disco del contenedor o en un directorio del host, y pueden añadirse más rutas antes del resumen.",
"intro": "La plantilla proporciona las rutas que necesita la aplicación. Cada una se ubica en un disco del contenedor o en un directorio del host, y se pueden añadir más rutas antes del resumen.",
"blocks": [
{
"steps": {
"items": [
{ "title": "Rutas requeridas", "body": "Se enumeran <code>/config</code>, <code>/data</code>, bibliotecas, descargas y cualquier volumen que declare la aplicación." },
{ "title": "Ubicación", "body": "Cada ruta se sitúa en un disco del contenedor o en un directorio existente del host." },
{ "title": "Almacenamiento y tamaño", "body": "Un disco del contenedor se crea en un almacenamiento de Proxmox VE con el tamaño indicado. La instalación por defecto usa <code>local-lvm</code>; la instalación avanzada pregunta el almacenamiento de cada ruta justo antes de su tamaño y propone el del rootfs. Aparece como <code>vm-VMID-disk-N</code> y se conecta como <code>mpN</code>." },
{ "title": "Directorio del host", "body": "Un directorio del host se indica por su ruta. Si no existe, se crea con el propietario que mapea el contenedor." },
{ "title": "Rutas adicionales", "body": "Antes de instalar pueden añadirse más pares de ruta del host o volumen y ruta del contenedor." },
{ "title": "Resumen", "body": "La relación completa se muestra antes de crear el CT y se guarda en su contrato de instancia." }
{
"title": "Rutas necesarias",
"body": "Se enumeran <code>/config</code>, <code>/data</code>, bibliotecas, descargas y todos los volúmenes declarados por la aplicación."
},
{
"title": "Ubicación",
"body": "Cada ruta se ubica en un disco del contenedor o en un directorio del host ya existente."
},
{
"title": "Almacenamiento y tamaño",
"body": "Se crea un disco del contenedor en un almacenamiento de Proxmox VE con el tamaño indicado. La instalación predeterminada usa <code>local-lvm</code>; la avanzada pregunta el almacenamiento de cada ruta justo antes de su tamaño y propone el del rootfs. El disco aparece como <code>vm-VMID-disk-N</code> y se conecta como <code>mpN</code>."
},
{
"title": "Directorio del host",
"body": "El directorio del host se indica mediante su ruta. Si no existe, se crea con el usuario al que se mapea el del contenedor como propietario."
},
{
"title": "Rutas adicionales",
"body": "Antes de instalar se pueden añadir más pares de ruta o volumen del host y ruta dentro del contenedor."
},
{
"title": "Resumen",
"body": "Antes de crear el CT se muestra la correspondencia completa de rutas y se guarda en el contrato de la instancia."
}
]
}
}
@@ -45,44 +63,85 @@
"blocks": [
{
"table": {
"headers": ["Propiedad", "Disco del contenedor", "Directorio del host"],
"headers": [
"Propiedad",
"Disco del contenedor",
"Directorio del host"
],
"rows": [
["En la configuración", "<code>mpN: STORAGE:vm-VMID-disk-N,mp=/config,backup=1,size=16G</code>", "<code>mpN: /mnt/oci-shared/media,mp=/data/media</code>"],
["Backup del contenedor (vzdump)", "Incluido, con <code>backup=1</code>", "No incluido"],
["Tamaño", "Fijo; crece con un redimensionado del punto de montaje", "El espacio libre del sistema de archivos o dataset del host"],
["Otros contenedores", "Solo lo monta su propio contenedor", "El mismo directorio puede montarse en varios contenedores"],
["Snapshots y restauración", "Los gestiona Proxmox VE junto con el CT", "Se gestionan en el almacenamiento del host"],
["Al eliminar la aplicación", "Se elimina con el contenedor", "Se conserva, con su contenido"],
["Al mover el CT a otro nodo", "Se mueve con el CT", "La misma ruta debe existir en el otro nodo"]
[
"En la configuración",
"<code>mpN: STORAGE:vm-VMID-disk-N,mp=/config,backup=1,size=16G</code>",
"<code>mpN: /mnt/oci-shared/media,mp=/data/media</code>"
],
[
"Backup del contenedor (vzdump)",
"Incluido, con <code>backup=1</code>",
"No incluido"
],
[
"Tamaño",
"Fijo; se amplía redimensionando el punto de montaje",
"El espacio libre del sistema de archivos o dataset del host"
],
[
"Otros contenedores",
"Solo lo monta el contenedor al que pertenece",
"El mismo directorio se puede montar en varios contenedores"
],
[
"Snapshots y restauración",
"Los gestiona Proxmox VE junto con el CT",
"Se gestionan en el almacenamiento del host"
],
[
"Al eliminar la aplicación",
"Se elimina con el contenedor",
"Se conserva con su contenido"
],
[
"Al mover el CT a otro nodo",
"Se mueve con el CT",
"La misma ruta debe existir en el otro nodo"
]
]
}
},
{
"p": "El rootfs queda reservado para los binarios y el contenido de la imagen. Una actualización o una recreación lo sustituye sin tocar ninguno de los dos tipos de punto de montaje."
"p": "El rootfs se reserva para los binarios y el contenido de la imagen. Una actualización o recreación lo sustituye sin tocar ninguno de los dos tipos de punto de montaje."
}
]
},
{
"id": "example",
"title": "Ejemplo: un contenedor con las dos ubicaciones",
"title": "Ejemplo: un contenedor con ambas ubicaciones",
"blocks": [
{
"code": {
"title": "Jellyfin instalado como CT 151 en local-lvm (extracto)",
"code": "rootfs: local-lvm:vm-151-disk-0,size=8G\n# Disco del contenedor, incluido en el backup del CT\nmp0: local-lvm:vm-151-disk-1,mp=/config,backup=1,size=16G\n\n# Directorio del host, fuera del backup del CT\nmp1: /mnt/oci-shared/media,mp=/data/media"
"title": "Jellyfin instalado como CT 151 en local-lvm (fragmento)",
"code": "rootfs: local-lvm:vm-151-disk-0,size=8G\n# Container disk, part of the CT backup\nmp0: local-lvm:vm-151-disk-1,mp=/config,backup=1,size=16G\n\n# Host directory, outside the CT backup\nmp1: /mnt/oci-shared/media,mp=/data/media"
}
},
{
"p": "Una actualización o una recreación sustituye solo el rootfs: <code>mp0</code> conserva usuarios, bibliotecas y ajustes, y <code>mp1</code> sigue mostrando los mismos archivos multimedia. Restaurar el backup del CT devuelve <code>/config</code>; el directorio multimedia se restaura, si hace falta, desde el backup del almacenamiento del host."
"p": "Una actualización o recreación solo sustituye el rootfs: <code>mp0</code> conserva usuarios, bibliotecas y ajustes, y <code>mp1</code> sigue mostrando los mismos archivos multimedia. Al restaurar el backup del CT se recupera <code>/config</code>; si hace falta restaurar el directorio multimedia, se utiliza el backup del almacenamiento del host."
},
{
"flow": {
"nodes": [
{ "label": "Contrato", "detail": "/config" },
{ "label": "Ubicación", "detail": "disco del contenedor\no directorio del host" },
{ "label": "LXC", "detail": "siempre /config\npara la aplicación" }
{
"label": "Contrato",
"detail": "/config"
},
{
"label": "Ubicación",
"detail": "Disco del contenedor\no directorio del host"
},
{
"label": "LXC",
"detail": "Siempre /config\npara la aplicación"
}
],
"caption": "La aplicación ve la ruta que publica la imagen; solo cambia dónde se guarda."
"caption": "La aplicación ve la ruta declarada por la imagen; solo cambia dónde se almacena."
}
}
]
@@ -94,33 +153,48 @@
{
"mermaid": {
"chartCode": "flowchart TB\n H[\"{{host}}<br/>/mnt/oci-shared/media\"]\n H --> Q[\"qBittorrent<br/>/data\"]\n H --> J[\"Jellyfin<br/>/data\"]\n H --> R[\"Radarr / Sonarr<br/>/data\"]\n Q -. \"{{config}}\" .-> QV[(\"/config mpN\")]\n J -. \"{{config}}\" .-> JV[(\"/config mpN\")]\n R -. \"{{config}}\" .-> RV[(\"/config mpN\")]",
"labels": { "host": "Directorio del host", "config": "configuración propia" }
"labels": {
"host": "Directorio del host",
"config": "Configuración propia"
}
}
},
{
"p": "Cada contenedor guarda su configuración en su propio disco. La biblioteca o las descargas son un único directorio del host montado en la misma ruta interna de todos los contenedores, de modo que la ruta en la que escribe una aplicación es la misma en la que lee otra."
"p": "Cada contenedor guarda su configuración en su propio disco. La biblioteca o las descargas se guardan en un único directorio del host, montado en la misma ruta interna en todos los contenedores. Así, una ruta en la que escribe una aplicación es la misma desde la que lee otra."
}
]
},
{
"id": "rclone",
"title": "Almacenamiento en la nube con la aplicación Rclone",
"intro": "La aplicación Rclone del catálogo ofrece, además de su instalación, <strong>Activar un montaje en un contenedor Rclone OCI existente</strong>. Monta un remoto ya creado y autorizado en la interfaz web de Rclone y lo publica en el host, donde otros contenedores pueden usarlo como directorio del host.",
"title": "Almacenamiento en la nube mediante la aplicación rclone",
"intro": "Además de instalarla, la ficha de rclone en el catálogo permite <strong>Activar un montaje en un contenedor OCI de rclone existente</strong>. Se monta un remoto ya creado y autorizado en la interfaz web de rclone y se publica en el host. Otros contenedores pueden usarlo como un directorio del host.",
"blocks": [
{
"steps": {
"items": [
{ "title": "Contenedor y remoto", "body": "El VMID del contenedor Rclone, el nombre exacto del remoto y, opcionalmente, una ruta dentro de él." },
{ "title": "Nombre y caché", "body": "El nombre del montaje y el modo de caché VFS: <code>off</code>, <code>minimal</code>, <code>writes</code> o <code>full</code> (por defecto)." },
{ "title": "Vistas publicadas", "body": "Una raíz común, <code>/mnt/oci-shared</code> por defecto, contiene una vista de lectura y escritura en <code>/mnt/oci-shared/remotes/NOMBRE</code> y una de solo lectura en <code>/mnt/oci-shared/remotes-ro/NOMBRE</code>." },
{ "title": "Activación", "body": "Tras una confirmación, el CT se detiene, se configuran su orden de arranque y un hookscript de Proxmox VE, y se vuelve a iniciar. La operación espera hasta que las dos vistas están montadas en el host." }
{
"title": "Contenedor y remoto",
"body": "El VMID del contenedor de rclone, el nombre exacto del remoto y, opcionalmente, una ruta dentro de él."
},
{
"title": "Nombre del montaje y caché",
"body": "El nombre del montaje y el modo de caché VFS: <code>off</code>, <code>minimal</code>, <code>writes</code> o <code>full</code> (predeterminado)."
},
{
"title": "Vistas publicadas",
"body": "Una raíz común, <code>/mnt/oci-shared</code> de forma predeterminada, contiene una vista de lectura y escritura en <code>/mnt/oci-shared/remotes/NAME</code> y otra de solo lectura en <code>/mnt/oci-shared/remotes-ro/NAME</code>."
},
{
"title": "Activación",
"body": "Tras confirmar, se detiene el CT, se configuran su comando de arranque y un hookscript de Proxmox VE y se vuelve a iniciar. La operación espera a que ambas vistas estén montadas en el host."
}
]
}
},
{
"calloutInfo": {
"title": "Si el montaje no llega a activarse",
"body": "Se restaura la configuración anterior del contenedor y se vuelve a iniciar, de modo que una activación fallida deja Rclone como estaba."
"title": "Si el montaje no se activa",
"body": "Se restaura la configuración anterior del contenedor y se vuelve a iniciar. Así, si la activación falla, rclone queda como estaba."
}
}
]
@@ -128,41 +202,58 @@
{
"id": "network",
"title": "Direcciones y redes",
"intro": "Una aplicación simple necesita una dirección. Una aplicación multicontenedor necesita además una red estable entre sus miembros.",
"intro": "Una aplicación de un solo contenedor necesita una dirección. Una aplicación con varios contenedores también necesita una red estable entre sus miembros.",
"blocks": [
{
"cards": {
"items": [
{ "icon": "network", "title": "Aplicación simple", "body": "Se eligen el bridge y DHCP o una dirección CIDR fija. El LXC tiene una dirección propia y el resumen muestra las URL completas de los servicios." },
{ "icon": "waypoints", "title": "Aplicación multicontenedor", "body": "Se busca una subred libre, se crea un bridge privado persistente y cada miembro (aplicación, base de datos, caché) recibe en él una dirección fija." }
{
"icon": "network",
"title": "Aplicación de un contenedor",
"body": "Se elige el puente de red y DHCP o una dirección fija en formato CIDR. El LXC tiene su propia dirección y el resumen muestra las URL completas de los servicios."
},
{
"icon": "waypoints",
"title": "Aplicación con varios contenedores",
"body": "Se busca una subred libre, se crea un puente privado persistente y cada miembro —aplicación, base de datos y caché— recibe una dirección fija en él."
}
]
}
},
{
"flow": {
"nodes": [
{ "label": "LAN", "detail": "dirección accesible\nsolo el servicio principal" },
{ "label": "LXC principal", "detail": "web / API\nLAN + red privada" },
{ "label": "Red privada", "detail": "PostgreSQL · Valkey · ML\ndirecciones fijas" }
{
"label": "LAN",
"detail": "Dirección accesible\nsolo para el servicio principal"
},
{
"label": "LXC principal",
"detail": "Web / API\nLAN + red privada"
},
{
"label": "Red privada",
"detail": "PostgreSQL · Valkey · ML\ndirecciones fijas"
}
],
"caption": "Las dependencias se comunican por la red privada y no tienen dirección en la LAN."
"caption": "Las dependencias se comunican por la red privada y no tienen una dirección en la LAN."
}
},
{
"p": "El contrato de la pila guarda el bridge, la subred, las direcciones y las relaciones entre servicios. La actualización de la aplicación reutiliza la misma topología en todos sus miembros. ProxMenux Monitor abre el contenedor principal en su dirección de la LAN, no en la de la red privada."
"p": "El contrato de la pila guarda el puente, la subred, las direcciones y las relaciones entre servicios. Al actualizar la aplicación se reutiliza la misma topología para todos sus miembros. ProxMenux Monitor abre el contenedor principal en su dirección de la LAN, no en la de la red privada."
}
]
},
{
"id": "ownership",
"title": "Propietarios",
"title": "Propietarios de archivos y directorios",
"blocks": [
{
"list": {
"items": [
"Los directorios nuevos se crean con el UID y el GID que mapea el LXC no privilegiado.",
"Los directorios existentes no cambian de propietario de forma recursiva.",
"Los sockets, los archivos del sistema y las rutas sensibles no se ofrecen como directorios del host genéricos."
"Los directorios nuevos se crean con el UID y el GID a los que se mapea el LXC sin privilegios.",
"No se cambia recursivamente el propietario de los directorios existentes.",
"Los sockets, archivos del sistema y rutas sensibles no se ofrecen como directorios genéricos del host."
]
}
}
@@ -174,13 +265,37 @@
"blocks": [
{
"table": {
"headers": ["Elemento", "En el vzdump del CT", "Dónde se conserva"],
"headers": [
"Elemento",
"En el backup vzdump del CT",
"Dónde se conserva"
],
"rows": [
["rootfs OCI", "Sí", "El backup del CT; también puede reconstruirse desde la imagen y el contrato"],
["Disco del contenedor con <code>backup=1</code>", "Sí", "El backup del CT"],
["Directorio del host", "No", "El backup del almacenamiento del host"],
["Contrato de la instancia", "No", "<code>/usr/local/share/proxmenux/oci/instances/VMID/</code> en el host"],
["Aplicación multicontenedor", "Cada miembro en su propio backup", "Los backups de cada miembro, más el contrato de la pila y su bridge en el host"]
[
"Rootfs OCI",
"Sí",
"En el backup del CT; también se puede reconstruir a partir de la imagen y el contrato"
],
[
"Disco del contenedor con <code>backup=1</code>",
"Sí",
"El backup del CT"
],
[
"Directorio del host",
"No",
"El backup del almacenamiento del host"
],
[
"Contrato de la instancia",
"Sí, la copia que guarda el CT",
"<code>/.proxmenux/oci-record.json</code> dentro del CT; las copias adicionales del host y del clúster se guardan por separado"
],
[
"Aplicación con varios contenedores",
"Cada miembro en su propio backup",
"Los backups de todos los miembros, más el contrato de la pila y su puente de red en el host"
]
]
}
}
@@ -78,6 +78,17 @@
"heading": "Scripts de la comunidad",
"body": "El menú también ofrece dos scripts de terceros del proyecto <a>community-scripts</a>: <em>Proxmox VE Post Install</em> y <em>Proxmox VE Microcode</em>. Son envoltorios que descargan y ejecutan los scripts originales mediante <code>wget | bash</code>. ProxMenux no los mantiene. Consulta <link>Repositorios externos</link> para conocer los detalles y valorar la confianza antes de ejecutarlos."
},
"pbs": {
"heading": "En Proxmox Backup Server",
"body": "En un host Proxmox Backup Server, el mismo menú se abre desde <strong>Settings post-install Proxmox</strong> en el menú de PBS. Automatizado, Personalizable, Apply Available Updates y Uninstall Optimizations funcionan igual que en Proxmox VE, con estas diferencias:",
"items": [
"<strong>Repositorios y actualización:</strong> cuando el servidor no tiene suscripción y solo está activo el repositorio Enterprise de PBS, ProxMenux pregunta antes de cambiar al repositorio sin suscripción de PBS. El cambio se hace con la API de repositorios del propio servidor, la misma que usa <em>Administration > Repositories</em>. Con una suscripción activa, o con un repositorio sin suscripción o de pruebas ya configurado, las fuentes se mantienen como están.",
"<strong>Lista personalizable:</strong> no aparecen las opciones que solo se aplican a Proxmox VE: agente de invitado, VFIO IOMMU, Open vSwitch, velocidad de backups vzdump, pigz, Appliance Manager, Ceph, alta disponibilidad y OVH Real Time Monitoring.",
"<strong>Banner de suscripción:</strong> el parche se aplica a la interfaz web de Proxmox Backup Server, y Uninstall Optimizations lo restaura.",
"<strong>Figurine:</strong> se instala sin los alias de Proxmox VE.",
"<strong>Scripts de la comunidad:</strong> la sección ofrece <em>Proxmox Backup Server Post Install</em> y <em>Proxmox Backup Server Microcode</em> en lugar de los scripts de Proxmox VE."
]
},
"related": {
"heading": "Relacionado",
"items": [
+17 -17
View File
@@ -1,30 +1,30 @@
{
"meta": {
"title": "Fail2Ban | ProxMenux Documentation",
"title": "Fail2Ban | Documentación de ProxMenux",
"description": "Instala Fail2Ban con tres jails afinados para Proxmox (SSH agresivo, Proxmox UI 8006, ProxMenux Monitor 8008). Incluye el arreglo de journald MaxLevelStore, servicios de log propios para fiabilidad, backend nftables/iptables autodetectado y hardening de SSH MaxAuthTries.",
"ogTitle": "Fail2Ban | ProxMenux Documentation",
"ogDescription": "Protección contra fuerza bruta para SSH y las UIs web de Proxmox, con arreglos específicos de journald y backend para Proxmox."
"ogTitle": "Fail2Ban | Documentación de ProxMenux",
"ogDescription": "Protección contra fuerza bruta para SSH y las interfaces web de Proxmox, con correcciones de journald y del backend específicas para Proxmox."
},
"header": {
"title": "Fail2Ban",
"description": "Instala Fail2Ban con una configuración específica para Proxmox: tres jails (SSH agresivo, Proxmox UI en puerto 8006, ProxMenux Monitor en puerto 8008 + proxy inverso), un arreglo del nivel de log de journald para que los eventos de autenticación SSH se almacenen de verdad, dos servicios logger journal-a-archivo que rodean un problema conocido del backend systemd de Fail2Ban, backend de firewall autodetectado y hardening de SSH MaxAuthTries.",
"description": "Instala Fail2Ban con configuración para Proxmox: tres jails (SSH agresivo, Proxmox en 8006 y ProxMenux Monitor en 8008 y proxy inverso), corrección del nivel de journald para guardar fallos SSH, dos servicios que copian el journal a archivos para evitar un problema del backend systemd de Fail2Ban, detección del backend de firewall y refuerzo SSH mediante MaxAuthTries.",
"section": "Seguridad"
},
"intro": {
"title": "Qué hace",
"body": "Instala Fail2Ban desde los repos de Debian y escribe una configuración completa afinada para Proxmox que protege tres superficies de ataque (SSH, Proxmox UI, ProxMenux Monitor) por defecto. Detecta una instalación existente y ofrece un menú de gestión (reinstalar / eliminar) en lugar de volver a ejecutar el instalador."
"body": "Instala Fail2Ban desde los repositorios Debian y escribe una configuración para Proxmox que protege SSH, Proxmox UI y ProxMenux Monitor desde el primer momento. Si detecta una instalación existente, ofrece un menú para reinstalar o eliminar."
},
"firstLaunch": {
"heading": "Diálogo de primer lanzamiento",
"body": "En un host sin Fail2Ban, el script muestra un diálogo de confirmación que resume todo lo que va a instalar y configurar. Cancelar sale sin cambios; confirmar arranca el flujo de instalación.",
"imageAlt": "Diálogo de confirmación de instalación de Fail2Ban listando los tres jails, el arreglo de journald y el hardening de SSH"
"body": "Sin Fail2Ban instalado, el script muestra un diálogo con lo que instalará y configurará. Cancelar termina sin cambios; confirmar inicia la instalación.",
"imageAlt": "Confirmación de instalación de Fail2Ban con las tres jails, corrección de journald y refuerzo SSH"
},
"jails": {
"heading": "Los tres jails",
"headerJail": "Jail",
"headerProtects": "Protege",
"headerRetries": "Reintentos / Ventana",
"headerBan": "Tiempo de ban",
"headerBan": "Tiempo de bloqueo",
"rows": [
{
"jail": "[sshd]",
@@ -49,12 +49,12 @@
},
"journald": {
"heading": "Por qué importa el arreglo de journald",
"intro": "Proxmox entrega <code>/etc/systemd/journald.conf</code> con <codeNw>MaxLevelStore=warning</codeNw>. journald descarta cada mensaje de log <em>por debajo</em> de warning antes de almacenarlo. SSH y PAM emiten fallos de autenticación a niveles <em>info</em> / <em>notice</em>, así que:",
"intro": "Proxmox incluye <code>/etc/systemd/journald.conf</code> con <codeNw>MaxLevelStore=warning</codeNw>. journald descarta los mensajes de nivel <em>inferior</em> a warning antes de guardarlos. SSH y PAM emiten fallos de autenticación en los niveles <em>info</em> / <em>notice</em>, por lo que:",
"diagram": {
"sshLabel": "SSH / PAM",
"sshDetail": "fallo de autenticación\n(nivel info / notice)",
"journaldLabel": "journald",
"journaldDetail": "MaxLevelStore=warning\n→ evento descartado en silencio",
"journaldDetail": "MaxLevelStore=warning\n→ evento descartado sin aviso",
"fail2banLabel": "Fail2Ban",
"fail2banDetail": "no ve nada\n→ nunca banea nada",
"arrowLabel": "Proxmox por defecto"
@@ -65,8 +65,8 @@
},
"loggers": {
"heading": "Por qué dos servicios logger propios",
"intro1": "Fail2Ban puede leer directamente del journal de systemd (<code>backend = systemd</code>), pero en Proxmox este backend tiene problemas conocidos de fiabilidad con los procesos worker de <code>pvedaemon</code> (los eventos de autenticación aparecen en el journal pero Fail2Ban no siempre los recoge) e intermitentemente con <code>sshd</code>.",
"intro2": "La solución alternativa: ProxMenux crea dos pequeños servicios systemd que hacen <code>journalctl -f</code> de las unidades relevantes y añaden cada línea a un archivo. Fail2Ban entonces lee esos archivos con el sólido como una roca <code>backend = auto</code> (modo archivo):",
"intro1": "Fail2Ban puede leer directamente el journal de systemd (<code>backend = systemd</code>), pero en Proxmox este backend presenta problemas de fiabilidad con procesos worker de <code>pvedaemon</code> (los eventos aparecen en el journal pero Fail2Ban no siempre los recoge) y ocasionalmente con <code>sshd</code>.",
"intro2": "ProxMenux crea dos pequeños servicios systemd que siguen las unidades correspondientes con <code>journalctl -f</code> y añaden cada línea a un archivo. Fail2Ban lee esos archivos con el fiable <code>backend = auto</code> (modo archivo):",
"headerService": "Servicio",
"headerSource": "Unidad origen",
"headerOutput": "Archivo de salida",
@@ -91,12 +91,12 @@
},
"hardening": {
"heading": "Hardening de SSH: MaxAuthTries",
"intro": "El control de Lynis <strong>SSH-7408</strong> recomienda <code>MaxAuthTries 3</code> en <code>sshd_config</code>. Con el <code>maxretry = 2</code> de Fail2Ban en el jail SSH, un cliente malicioso nunca llega a tres intentos de todas formas — pero el ajuste explícito satisface la auditoría y añade defensa en profundidad (p. ej. si Fail2Ban está parado por mantenimiento).",
"intro": "El control Lynis <strong>SSH-7408</strong> recomienda <code>MaxAuthTries 3</code> en <code>sshd_config</code>. La jail SSH usa <code>maxretry = 2</code> para bloquear tras fallos repetidos; MaxAuthTries limita los intentos dentro de una conexión. Este ajuste SSH añade defensa en profundidad, también cuando Fail2Ban está detenido por mantenimiento.",
"installerIntro": "El instalador:",
"items": [
"Lee el valor actual de <code>MaxAuthTries</code> (o por defecto 6 si está ausente).",
"Lo guarda en <code>/usr/local/share/proxmenux/sshd_maxauthtries_backup</code>.",
"Edita <code>sshd_config</code> en sitio — reemplaza la línea existente, descomenta la línea comentada o la añade.",
"Edita <code>sshd_config</code> directamente: sustituye la línea existente, descomenta la comentada o añade una nueva.",
"Recarga <code>sshd</code> (reload, no restart, para mantener vivas las sesiones existentes)."
],
"outro": "Al desinstalar, el valor original guardado se restaura y se recarga <code>sshd</code> otra vez."
@@ -109,7 +109,7 @@
"rows": [
{
"action": "Reinstalar",
"what": "Vuelve a ejecutar el instalador completo — reescribe todos los jails con los valores por defecto actuales de ProxMenux. Úsalo cuando una actualización de ProxMenux suba los valores recomendados."
"what": "Repite la instalación completa y reescribe todas las jails con los valores actuales de ProxMenux. Úsalo cuando una actualización cambie las recomendaciones."
},
{
"action": "Eliminar",
@@ -125,7 +125,7 @@
"troubleshoot": {
"heading": "Solución de problemas",
"neverBansTitle": "Fail2Ban corre pero nunca banea nada",
"neverBansBody": "Comprueba que los archivos de log de autenticación reciben entradas de verdad: <code>tail -f /var/log/ssh-auth.log</code> y prueba un intento SSH con contraseña incorrecta desde otra máquina. Si el log se queda vacío, el servicio logger no está corriendo: <code>systemctl status ssh-auth-logger.service</code>. Si está activo pero el log está vacío, comprueba que el drop-in de journald surtió efecto: <code>journalctl --dump-catalog | head</code> — eventos a nivel <em>info</em> deberían ser visibles.",
"neverBansBody": "Comprueba que <code>tail -f /var/log/ssh-auth.log</code> recibe una entrada tras intentar acceder por SSH con contraseña incorrecta desde otra máquina. Si sigue vacío, consulta <code>systemctl status ssh-auth-logger.service</code>. Si el logger está activo, mira los eventos SSH recientes con <code>journalctl -u ssh.service -n 50 --no-pager -p info</code> y comprueba que el drop-in de journald admite el nivel <em>info</em>.",
"monitorEmptyTitle": "El jail del Monitor de ProxMenux no tiene entradas ni siquiera tras logins fallidos",
"monitorEmptyBody": "El jail <code>[proxmenux]</code> lee <code>/var/log/proxmenux-auth.log</code>, que lo escribe la app Flask del Monitor de ProxMenux — no un logger de journald. Si no usas el Monitor, el archivo se queda vacío y el jail nunca dispara. Eso es lo esperado; la configuración del jail es inocua. Si sí usas el Monitor y el log está vacío, comprueba la configuración de logging de Flask.",
"selfBanTitle": "Me he baneado a mí mismo",
@@ -143,7 +143,7 @@
"related": {
"heading": "Relacionado",
"monitorLabel": "ProxMenux Monitor → pestaña de Seguridad",
"monitorTail": " — misma instalación accesible desde el panel, más estado en vivo de los jails, IPs baneadas y ajuste por jail de reintentos / tiempo de ban desde el navegador.",
"monitorTail": " — instalación desde el panel, estado de las jails en directo, IP bloqueadas y ajuste de reintentos y duración de bloqueo por jail desde el navegador.",
"lynisLabel": "Lynis",
"lynisTail": " — ejecuta una auditoría de seguridad antes/después para confirmar que el control SSH-7408 se satisface.",
"securityLabel": "Resumen de Seguridad",
+18 -18
View File
@@ -1,24 +1,24 @@
{
"meta": {
"title": "Seguridad de Proxmox — Fail2Ban, auditoría de hardening con Lynis | ProxMenux",
"description": "Dos herramientas de seguridad instalables para Proxmox VE: Fail2Ban (prevención de intrusiones para SSH, la UI web de Proxmox y el Monitor de ProxMenux) y Lynis (escáner de auditoría y hardening de seguridad instalado desde GitHub upstream).",
"ogTitle": "Seguridad de Proxmox — Fail2Ban, auditoría de hardening con Lynis",
"ogDescription": "Fail2Ban y Lynis para Proxmox VE — prevención de intrusiones más una auditoría de hardening instaladas y gestionadas por ProxMenux.",
"title": "Seguridad de Proxmox — Fail2Ban y auditoría de refuerzo con Lynis | ProxMenux",
"description": "Dos herramientas de seguridad para Proxmox VE: Fail2Ban (prevención de intrusiones para SSH, la interfaz web de Proxmox y ProxMenux Monitor) y Lynis (auditor de seguridad y refuerzo del sistema instalado desde el repositorio original en GitHub).",
"ogTitle": "Seguridad de Proxmox — Fail2Ban y auditoría de refuerzo con Lynis",
"ogDescription": "Fail2Ban y Lynis para Proxmox VE: prevención de intrusiones y auditoría de refuerzo, instaladas y gestionadas por ProxMenux.",
"twitterTitle": "Seguridad de Proxmox | ProxMenux",
"twitterDescription": "Fail2Ban y Lynis para Proxmox VE — prevención de intrusiones y auditoría de hardening."
"twitterDescription": "Fail2Ban y Lynis para Proxmox VE: prevención de intrusiones y auditoría de refuerzo."
},
"header": {
"title": "Seguridad",
"description": "Dos herramientas de seguridad complementarias para Proxmox VE: una defensa activa (Fail2Ban — banea IPs que atacan SSH o las UIs web) y una auditoría offline (Lynis — escanea el sistema en busca de huecos de hardening y da una puntuación 0–100). Ambas se instalan y gestionan mediante su propio menú dedicado, con detección de una instalación existente antes de cualquier acción.",
"description": "Dos herramientas complementarias para Proxmox VE: defensa activa (Fail2Ban bloquea IP que atacan SSH o las interfaces web) y auditoría local (Lynis busca carencias de seguridad y da una puntuación de 0 a 100). Cada una tiene su propio menú de instalación y gestión, que detecta instalaciones existentes antes de actuar.",
"section": "Seguridad"
},
"intro": {
"title": "Defensa activa vs. auditoría offline",
"body": "Estas dos herramientas responden a preguntas distintas. <strong>Fail2Ban</strong> responde a <em>\"¿hay algo atacándonos ahora mismo?\"</em> vigilando los logs de autenticación y baneando las IPs ofensoras. <strong>Lynis</strong> responde a <em>\"¿cómo de hardened está este host?\"</em> ejecutando una auditoría de un tirón e imprimiendo recomendaciones concretas. Úsalas juntas: Lynis te dice qué arreglar, Fail2Ban gestiona el abuso en vivo."
"title": "Defensa activa y auditoría local",
"body": "Responden a preguntas distintas. <strong>Fail2Ban</strong> contesta <em>«¿nos están atacando ahora?»</em> vigilando registros de autenticación y bloqueando las IP responsables. <strong>Lynis</strong> contesta <em>«¿qué nivel de refuerzo tiene este host?»</em> mediante una auditoría puntual con recomendaciones concretas. Usa ambas: Lynis indica qué mejorar y Fail2Ban responde a los ataques en curso."
},
"opening": {
"heading": "Abrir el menú",
"body": "Desde el menú principal de ProxMenux, selecciona <strong>Seguridad</strong>. Verás esto:",
"body": "Desde el menú principal de ProxMenux, selecciona <strong>Seguridad</strong>. Verás lo siguiente:",
"imageAlt": "Menú de Seguridad con opciones de Fail2Ban y Lynis"
},
"pick": {
@@ -28,7 +28,7 @@
"cards": {
"fail2ban": {
"title": "Fail2Ban",
"body": "Prevención de intrusiones activa. Vigila los logs de autenticación de SSH y las UIs web y banea IPs tras fallos repetidos.",
"body": "Prevención activa de intrusiones. Vigila los registros de autenticación de SSH y las interfaces web y bloquea IP tras fallos repetidos.",
"bullets": [
"Tres jails: SSH, Proxmox UI (8006), ProxMenux Monitor (8008)",
"Arregla los valores por defecto de journald de Proxmox que bloquean los logs de autenticación",
@@ -38,28 +38,28 @@
},
"lynis": {
"title": "Lynis",
"body": "Auditor de seguridad offline. Escanea el host e imprime una puntuación de hardening más pistas concretas de remediación.",
"body": "Auditor local de seguridad. Analiza el host y muestra una puntuación de refuerzo y recomendaciones concretas para corregir problemas.",
"bullets": [
"Instalado desde el GitHub upstream de CISOfy (siempre el último)",
"Puntuación de hardening 0–100 + lista de warnings y sugerencias",
"Acciones de ejecutar auditoría y actualizar dentro del menú",
"De solo lectura por diseño — nunca cambia el sistema"
"Instalado desde el repositorio original de CISOfy en GitHub (última versión)",
"Puntuación de refuerzo 0–100 y lista de advertencias y sugerencias",
"Acciones de auditoría y actualización desde el menú",
"De solo lectura: nunca modifica el sistema"
]
}
},
"workflowTip": {
"title": "Flujo de trabajo que usa ambos",
"body": "Ejecuta primero una auditoría de Lynis para ver tu puntuación de partida y las recomendaciones principales. Aplica los arreglos que quieras. Después instala Fail2Ban — implementa una de las recomendaciones más comunes de Lynis (protección contra fuerza bruta SSH) automáticamente y ajusta <code>MaxAuthTries</code> en <code>sshd_config</code> para satisfacer el control SSH-7408. Vuelve a ejecutar Lynis después para confirmar que la puntuación mejoró."
"body": "Ejecuta primero una auditoría Lynis para ver la puntuación inicial y las recomendaciones principales. Aplica las correcciones que elijas. Instala Fail2Ban: implementa automáticamente la protección contra fuerza bruta SSH y ajusta <code>MaxAuthTries</code> en <code>sshd_config</code> para cumplir el control SSH-7408. Vuelve a ejecutar Lynis para comprobar la mejora."
},
"fail2banSection": {
"heading": "Fail2Ban",
"body": "ProxMenux instala Fail2Ban con una configuración afinada específicamente para Proxmox. Más allá del jail estándar de SSH, añade protección para la UI web de Proxmox y el Monitor de ProxMenux, y rodea dos rarezas específicas de Proxmox: un valor por defecto de journald que descarta eventos de autenticación, y el problema del backend systemd que impide a Fail2Ban leer de forma fiable ciertas fuentes del journal. La página de detalle cubre el flujo de instalación completo, los tres jails, el arreglo de journald, el cambio de hardening SSH y la chuleta de solución de problemas.",
"optionTitle": "Fail2Ban — instalar y gestionar",
"optionDescription": "Tres jails preconfigurados (sshd agresivo, Proxmox UI puerto 8006, ProxMenux Monitor puerto 8008 + proxy inverso), backend nftables/iptables autodetectado, arreglo de journald y hardening de SSH MaxAuthTries."
"optionDescription": "Tres jails preconfiguradas (sshd agresivo, Proxmox en 8006, ProxMenux Monitor en 8008 y proxy inverso), detección de nftables/iptables, corrección de journald y refuerzo SSH mediante MaxAuthTries."
},
"lynisSection": {
"heading": "Lynis",
"body": "ProxMenux clona Lynis desde <code>github.com/CISOfy/lynis</code> en <code>/opt/lynis</code> y lo expone como <code>/usr/local/bin/lynis</code>. El paquete de Debian se evita intencionadamente porque va varias versiones mayores por detrás de upstream. La página de detalle cubre el flujo de instalar / auditar / actualizar / desinstalar, cómo leer el informe y cómo actuar sobre los hallazgos.",
"body": "ProxMenux clona Lynis de <code>github.com/CISOfy/lynis</code> en <code>/opt/lynis</code> y lo expone como <code>/usr/local/bin/lynis</code>. Evita el paquete Debian porque va varias versiones principales por detrás del proyecto original. La página detallada explica instalación, auditoría, actualización, desinstalación, lectura del informe y aplicación de sus recomendaciones.",
"optionTitle": "Lynis — instalar, auditar y gestionar",
"optionDescription": "Instala el último Lynis desde el repo oficial de CISOfy en GitHub (no el paquete más antiguo de Debian), ejecuta auditorías del sistema con puntuación de hardening y actualiza vía git pull."
},
+19 -19
View File
@@ -1,37 +1,37 @@
{
"meta": {
"title": "Lynis | ProxMenux Documentation",
"description": "Instala Lynis desde el repositorio oficial de CISOfy en GitHub (siempre el último), ejecuta una auditoría del sistema con puntuación de hardening 0–100, actualiza vía git pull. De solo lectura por diseño — nunca modifica el sistema.",
"ogTitle": "Lynis | ProxMenux Documentation",
"ogDescription": "Instala y ejecuta el auditor de seguridad Lynis en Proxmox VE. Instalación desde GitHub upstream, auditoría, actualización."
"title": "Lynis | Documentación de ProxMenux",
"description": "Instala Lynis desde el repositorio oficial CISOfy de GitHub, ejecuta una auditoría con puntuación de refuerzo de 0 a 100 y actualiza mediante git pull. Auditor de solo lectura: no modifica el sistema.",
"ogTitle": "Lynis | Documentación de ProxMenux",
"ogDescription": "Instala y ejecuta el auditor de seguridad Lynis en Proxmox VE. Instalación desde el repositorio original GitHub, auditoría y actualización."
},
"header": {
"title": "Lynis",
"description": "Clona el último Lynis desde el repositorio oficial de CISOfy en GitHub, lo expone como /usr/local/bin/lynis y ofrece acciones de ejecutar auditoría / actualizar / reinstalar / desinstalar desde el menú. Auditor de solo lectura por diseño — nunca modifica el sistema, solo reporta.",
"description": "Clona el último Lynis del repositorio oficial CISOfy en GitHub, lo expone como /usr/local/bin/lynis y ofrece auditoría, actualización, reinstalación y desinstalación desde el menú. El auditor es de solo lectura: informa sin modificar el sistema.",
"section": "Seguridad"
},
"intro": {
"title": "Qué hace",
"body": "Instala Lynis (el auditor de seguridad de código abierto de CISOfy) desde GitHub upstream en <code>/opt/lynis</code> y crea un wrapper en <code>/usr/local/bin/lynis</code> para que esté en tu <code>PATH</code>. Detecta una instalación existente al arrancar y muestra un menú de gestión (auditoría / actualizar / reinstalar / eliminar) en su lugar."
"body": "Instala Lynis, el auditor de código abierto de CISOfy, desde su repositorio GitHub en <code>/opt/lynis</code> y crea un script lanzador en <code>/usr/local/bin/lynis</code> para incluirlo en <code>PATH</code>. Si detecta una instalación existente al abrirlo, muestra un menú de auditoría, actualización, reinstalación o eliminación."
},
"manageMenu": {
"heading": "Menú de gestión (tras la instalación)",
"heading": "Menú de gestión (tras instalar)",
"intro": "Una vez instalado Lynis, cada invocación posterior abre el menú de gestión en lugar de volver a ejecutar el instalador. Desde aquí lanzas una auditoría, actualizas vía git pull, reinstalas o desinstalas:",
"imageAlt": "Menú de gestión de Lynis con opciones de auditoría, actualizar, reinstalar y eliminar"
},
"whyUpstream": {
"heading": "Por qué GitHub upstream, no apt",
"intro": "Debian entrega Lynis vía apt, pero el paquete suele ir varias versiones mayores por detrás de upstream. Los controles más nuevos, los arreglos para nuevos vectores de ataque y las recomendaciones refinadas solo aterrizan en el repo de GitHub. El propio Lynis es un script de shell autocontenido — sin compilación, sin dependencias más allá de <code>git</code> para la instalación — así que clonar el repo es el método de instalación canónico recomendado por la propia CISOfy.",
"heading": "Por qué el repositorio oficial de GitHub y no apt",
"intro": "Debian distribuye Lynis mediante apt, pero el paquete suele ir varias versiones principales por detrás del proyecto original. GitHub recibe antes los controles, correcciones de nuevos vectores de ataque y mejoras de las recomendaciones. Lynis es un script de shell autocontenido, sin compilación ni dependencias de instalación aparte de <code>git</code>; por eso clonar el repositorio es el método recomendado por CISOfy.",
"headerSource": "Origen",
"headerPath": "Ruta de instalación",
"headerPath": "Install path",
"headerUpdate": "Método de actualización",
"headerFresh": "Frescura de versión",
"headerFresh": "Actualidad de la versión",
"rows": [
{
"sourceRich": "<strong>ProxMenux (este script)</strong>",
"path": "/opt/lynis/",
"update": "git pull (desde el menú)",
"fresh": "Última versión upstream"
"fresh": "Última versión del proyecto original"
},
{
"sourceRich": "<strong>Debian apt</strong>",
@@ -59,13 +59,13 @@
"<code>/opt/lynis/lynis</code> — ruta directa (por si el wrapper se eliminó)",
"<code>/usr/bin/lynis</code> — versión instalada por apt, si el usuario la instaló así anteriormente"
],
"outro": "Si se encuentra cualquiera de estas, se abre el menú de gestión. El script <strong>no</strong> desinstala un Lynis instalado por apt — solo el que él mismo gestiona (<code>/opt/lynis</code> + el wrapper)."
"outro": "Si encuentra cualquiera de estas rutas, abre el menú de gestión. El script <strong>no</strong> desinstala Lynis instalado por apt; solo el que gestiona en <code>/opt/lynis</code> y su lanzador."
},
"audit": {
"heading": "Ejecutar una auditoría",
"intro": "Desde el menú de gestión, elige <strong>Ejecutar auditoría de seguridad ahora</strong>. Esto equivale a ejecutar:",
"intro": "En el menú de gestión, elige <strong>Ejecutar auditoría de seguridad ahora</strong>. Equivale a ejecutar:",
"code": "lynis audit system --no-colors",
"outro": "La auditoría tarda de 30 segundos a unos minutos según el tamaño del host. La salida fluye directamente al terminal — no hay spinner. Lynis imprime secciones por cada categoría de control, marcando cada test como <ok>[ OK ]</ok>, <warn>[ WARNING ]</warn> o <sugg>[ SUGGESTION ]</sugg>. El resumen al final tiene los números titulares:",
"outro": "La auditoría tarda de 30 segundos a varios minutos según el tamaño del host. La salida se muestra directamente en el terminal, sin indicador giratorio. Lynis organiza los controles por categoría y marca cada prueba como <ok>[ OK ]</ok>, <warn>[ WARNING ]</warn> o <sugg>[ SUGGESTION ]</sugg>. El resumen final muestra las cifras principales:",
"summary": "================================================================================\n\n Lynis security scan details:\n\n Hardening index : 76 [############ ]\n Tests performed : 247\n Plugins enabled : 0\n\n Components:\n - Firewall [V]\n - Malware scanner [X]\n\n Lynis modules:\n - Compliance status [?]\n - Security audit [V]\n - Vulnerability scan [V]\n\n================================================================================"
},
"report": {
@@ -99,7 +99,7 @@
},
"update": {
"heading": "Actualizar Lynis",
"body": "Desde el menú de gestión, <strong>Actualizar Lynis a la última versión</strong> ejecuta <code>git pull --quiet</code> dentro de <code>/opt/lynis</code>. Si el directorio existe pero no es un checkout de Git (p. ej. alguien copió los archivos a mano), el script recae en una reinstalación completa."
"body": "En el menú, <strong>Actualizar Lynis a la última versión</strong> ejecuta <code>git pull --quiet</code> en <code>/opt/lynis</code>. Si el directorio existe pero no es una copia Git (por ejemplo, se copiaron archivos manualmente), el script reinstala por completo."
},
"reinstall": {
"heading": "Reinstalar / desinstalar",
@@ -108,7 +108,7 @@
"rows": [
{
"actionRich": "<strong>Reinstalar</strong>",
"whatRich": "Elimina <code>/opt/lynis</code>, vuelve a clonar desde GitHub, recrea el wrapper. Úsalo si el checkout local está corrupto."
"whatRich": "Elimina <code>/opt/lynis</code>, clona de nuevo desde GitHub y recrea el lanzador. Úsalo si la copia local está dañada."
},
{
"actionRich": "<strong>Eliminar</strong>",
@@ -128,7 +128,7 @@
"notFoundTitle": "lynis: command not found tras la instalación",
"notFoundIntro": "El wrapper en <code>/usr/local/bin/lynis</code> no se creó o se eliminó. Arreglo más rápido: reinstalar desde el menú. Arreglo manual:",
"notFoundCode": "cat > /usr/local/bin/lynis <<'EOF'\n#!/bin/bash\ncd /opt/lynis && ./lynis \"$@\"\nEOF\nchmod +x /usr/local/bin/lynis",
"sshTitle": "La auditoría imprime \"Warning: Test SSH-7408 — MaxAuthTries set incorrectly\"",
"sshTitle": "La auditoría muestra \"Warning: Test SSH-7408 — MaxAuthTries set incorrectly\"",
"sshIntro": "El demonio SSH permite demasiados intentos de autenticación por conexión. O bien instala <link>Fail2Ban</link> desde ProxMenux (que establece <code>MaxAuthTries=3</code> automáticamente) o edita <code>/etc/ssh/sshd_config</code> a mano:",
"sshCode": "sed -i 's/^#?MaxAuthTries.*/MaxAuthTries 3/' /etc/ssh/sshd_config\nsystemctl reload sshd",
"scoreTitle": "La puntuación bajó tras una actualización de Proxmox",
@@ -140,7 +140,7 @@
},
"sample": {
"heading": "Informe de ejemplo",
"intro": "ProxMenux Monitor empaqueta cada ejecución de Lynis en un PDF de varias páginas disponible desde la <link>pestaña de Seguridad</link> en el panel. La primera página es el resumen ejecutivo — puntuación de hardening, info del sistema, vista general de la postura de seguridad. Las páginas siguientes listan cada warning con explicación y cada sugerencia rankeada por impacto, más el inventario de paquetes usado durante la auditoría.",
"intro": "ProxMenux Monitor genera un PDF de varias páginas para cada ejecución de Lynis desde la <link>pestaña Seguridad</link>. La primera página resume puntuación de refuerzo, información del sistema y estado de seguridad. Las siguientes detallan cada advertencia, las sugerencias ordenadas por impacto y el inventario de paquetes utilizado en la auditoría.",
"imageAlt": "Primera página del PDF del Lynis Security Audit Report — resumen ejecutivo con Hardening Index 71/100, bloque de información del sistema y vista general de la postura de seguridad con firewall, escáner de malware y recuento de paquetes instalados",
"captionPrefix": "Primera página de un informe de ejemplo. El PDF completo (",
"captionLink": "ejemplo",
@@ -1,13 +1,13 @@
{
"meta": {
"title": "HTTPS para ProxMenux Monitor — certificado del host Proxmox o rutas personalizadas | ProxMenux",
"description": "Sirve ProxMenux Monitor sobre HTTPS usando o bien el certificado del host Proxmox (autodetectado, incluyendo el certificado Let's Encrypt subido vía la pestaña ACME de Proxmox) o un certificado personalizado en cualquier ruta del disco.",
"description": "Sirve ProxMenux Monitor por HTTPS con el certificado del host Proxmox (detectado automáticamente, incluido el de Let’s Encrypt instalado mediante ACME de Proxmox) o un certificado personalizado en cualquier ruta del disco.",
"ogTitle": "HTTPS para ProxMenux Monitor — certificado del host Proxmox o personalizado",
"ogDescription": "Habilita HTTPS en el puerto 8008 con el certificado del host Proxmox o cualquier par .pem / .key personalizado."
},
"header": {
"title": "HTTPS para ProxMenux Monitor",
"description": "Activa HTTPS para el Monitor (puerto 8008) usando o bien el certificado del host Proxmox que el Monitor autodetecta, o un certificado personalizado ubicado en cualquier sitio del disco. La opción de Proxmox elige de forma transparente el certificado subido por ACME cuando está presente, así que un certificado Let's Encrypt gestionado por la UI de Proxmox se reutiliza sin un trabajo de renovación extra.",
"description": "Activa HTTPS para Monitor en 8008 con el certificado del host Proxmox detectado automáticamente o uno personalizado en disco. La opción Proxmox prefiere el certificado instalado mediante ACME, si existe, y reutiliza el Let’s Encrypt gestionado por Proxmox sin otra tarea de renovación.",
"section": "Seguridad"
},
"intro": {
@@ -15,20 +15,20 @@
"body": "Cómo cambiar el Monitor de HTTP a HTTPS en el panel Settings → Security, a qué apunta realmente cada fuente de certificado en disco, cómo se comporta la opción de Proxmox cuando el host tiene un certificado Let's Encrypt y cómo establecer rutas personalizadas si gestionas certificados fuera de Proxmox."
},
"wheresetting": {
"heading": "Dónde vive el ajuste",
"body": "Abre el Monitor y ve a <strong>Settings → Security → HTTPS / SSL</strong>. El panel muestra el estado actual (HTTP o HTTPS), y en un host sin HTTPS aún lista las fuentes de certificado que el Monitor ha podido detectar.",
"heading": "Ubicación del ajuste",
"body": "Abre Monitor y ve a <strong>Ajustes → Seguridad → HTTPS / SSL</strong>. El panel muestra HTTP o HTTPS y, si HTTPS no está activo, las fuentes de certificados detectadas.",
"imageAlt": "Panel Settings → Security → HTTPS / SSL en el Monitor mostrando el estado HTTPS desactivado, el certificado de Proxmox autodetectado (subject, issuer, expiry) y la opción Use Custom Certificate",
"caption": "Panel Settings → Security → HTTPS / SSL antes de la activación. El Monitor saca a la luz el certificado que el propio Proxmox está usando y lo ofrece como una fuente de un solo clic."
"caption": "Panel Ajustes → Seguridad → HTTPS / SSL antes de activar HTTPS. Monitor muestra el certificado que usa Proxmox y permite elegirlo con un clic."
},
"twoways": {
"heading": "Dos formas de habilitar HTTPS",
"proxmox": {
"title": "Usar el certificado de Proxmox",
"summary": "Un clic. El Monitor reutiliza el certificado que el propio Proxmox VE sirve en el puerto 8006.",
"summary": "Un clic: Monitor reutiliza el certificado que Proxmox VE presenta en el puerto 8006.",
"items": [
"Autodetectado — no hay ruta que teclear",
"Elige el certificado subido por ACME si está presente, recae en el self-signed por defecto",
"La renovación pasa por Proxmox; el Monitor sigue automáticamente en el siguiente arranque"
"Detectado automáticamente, sin introducir rutas",
"Prefiere el certificado ACME si existe; si no, usa el autofirmado predeterminado",
"Proxmox renueva; Monitor valida y carga el certificado en la siguiente conexión TLS nueva"
]
},
"custom": {
@@ -37,7 +37,7 @@
"items": [
"Solo rutas absolutas (el proceso del Monitor debe poder leer ambos)",
"Útil cuando los certificados vienen de <code>certbot</code>, <code>acme.sh</code> o un wildcard",
"La renovación es tuya — reinicia el servicio del Monitor tras que el archivo cambie"
"La renovación queda a tu cargo: reinicia Monitor cuando cambien los archivos"
]
}
},
@@ -54,7 +54,7 @@
{
"fileRich": "<code>pveproxy-ssl.pem</code><br /><code>pveproxy-ssl.key</code>",
"originRich": "Certificado personalizado subido vía la UI de Proxmox — incluyendo el certificado Let's Encrypt emitido en <em>Datacenter → Node → Certificates → ACME</em>.",
"when": "Preferido siempre que existan ambos archivos. El Monitor seguirá el certificado que el propio Proxmox está sirviendo."
"when": "Se prefiere cuando existen ambos archivos; Monitor usa el certificado presentado por Proxmox."
},
{
"fileRich": "<code>pve-ssl.pem</code><br /><code>pve-ssl.key</code>",
@@ -65,17 +65,17 @@
},
"callout": {
"title": "Misma prioridad que el propio Proxmox",
"bodyRich": "<code>pveproxy</code> usa la misma regla de selección, así que elegir la opción de Proxmox en el Monitor siempre sirve el certificado que la UI web de Proxmox ya está sirviendo en el puerto 8006. Sin copias, sin pipeline de renovación aparte."
"bodyRich": "<code>pveproxy</code> aplica la misma selección: al elegir Proxmox, Monitor usa el certificado que la interfaz de Proxmox presenta en 8006, sin copiarlo ni mantener otro proceso de renovación."
}
},
"letsencrypt": {
"heading": "Obtener un certificado Let's Encrypt vía Proxmox ACME",
"intro": "Proxmox VE entrega su propio cliente ACME. Pulsar <em>\"Order Certificate Now\"</em> escribe el resultado en <code>/etc/pve/local/pveproxy-ssl.pem</code>, que es exactamente lo que el Monitor lee. La receta de cinco pasos de abajo es el mismo procedimiento que la <extlink1>guía oficial de Proxmox</extlink1> — destilada a los comandos que realmente necesitas ejecutar.",
"intro": "Proxmox VE incluye su propio cliente ACME. <em>«Order Certificate Now»</em> guarda el resultado en <code>/etc/pve/local/pveproxy-ssl.pem</code>, que Monitor lee. Los cinco pasos siguientes condensan el procedimiento de la <extlink1>guía oficial de Proxmox</extlink1> en los comandos necesarios.",
"prereqs": {
"title": "Prerrequisitos",
"items": [
"El nodo tiene un nombre DNS real (no solo una IP) apuntándole.",
"<strong>O bien</strong> puerto 80 alcanzable desde la internet pública (challenge HTTP-01, el más simple), <strong>o bien</strong> un proveedor de DNS con credenciales API (challenge DNS-01 — funciona detrás de NAT, soporta wildcards).",
"<strong>O bien</strong> puerto 80 accesible desde Internet (verificación HTTP-01, la más sencilla), <strong>o bien</strong> proveedor DNS con credenciales API (DNS-01, funciona tras NAT y admite comodines).",
"Una dirección de email para la cuenta ACME."
]
},
@@ -90,7 +90,7 @@
"http01Rich": "<strong>HTTP-01</strong> es el más fácil: está integrado, sin plugin extra. Let's Encrypt se conecta a <code>http://&lt;your-host&gt;/.well-known/acme-challenge/...</code> en el puerto 80, así que el puerto 80 debe estar abierto desde la internet pública a tu nodo — típicamente un port forward en tu router.",
"dns01Rich": "<strong>DNS-01</strong> funciona sin exponer el puerto 80 (bueno para homelabs detrás de CG-NAT) y es la única opción para certificados wildcard. Añades un plugin DNS una vez con el token API de tu proveedor. Ejemplo con Cloudflare:",
"code": "pvenode acme plugin add dns cf \\\n --api cloudflare \\\n --data CF_Token=YOUR_CLOUDFLARE_API_TOKEN",
"outroRich": "Para otros proveedores (Gandi, OVH, AWS Route 53, etc.) consulta <code>pvenode acme plugin add dns --help</code> — Proxmox entrega <extlink2>todos los plugins DNS de acme.sh</extlink2>."
"outroRich": "Para otros proveedores (Gandi, OVH, AWS Route 53, etc.), consulta <code>pvenode acme plugin add dns --help</code>. Proxmox incluye <extlink2>todos los plugins DNS de acme.sh</extlink2>."
},
"step3": {
"heading": "Paso 3 — Asocia el dominio a tu nodo",
@@ -112,19 +112,19 @@
},
"gui": {
"title": "¿Prefieres la GUI? Los mismos cinco pasos",
"bodyRich": "<em>Datacenter → ACME</em> registra la cuenta, <em>Datacenter → ACME → Plugins</em> añade el plugin DNS, <em>Node → Certificates → ACME</em> asocia el dominio y <em>Order Certificates Now</em> ejecuta el paso 4. Los comandos CLI de arriba son útiles para scriptar y para setups headless / solo CLI."
"bodyRich": "<em>Datacenter → ACME</em> registra la cuenta; <em>Datacenter → ACME → Plugins</em> añade DNS; <em>Node → Certificates → ACME</em> vincula el dominio; <em>Order Certificates Now</em> ejecuta el paso 4. Los comandos anteriores sirven para automatizar y trabajar sin interfaz gráfica."
}
},
"switchToHttps": {
"heading": "Cambiar el Monitor a HTTPS",
"bodyRich": "Una vez que <code>/etc/pve/local/pveproxy-ssl.pem</code> está firmado por Let's Encrypt, en el Monitor solo hace falta un clic: abre <strong>Ajustes → Seguridad → HTTPS / SSL</strong>, confirma que el emisor mostrado en el panel del certificado detectado sea <em>Let's Encrypt</em> (y no la CA local de Proxmox) y pulsa <strong>Usar certificado de Proxmox</strong>. El servicio del Monitor se reinicia y la siguiente carga del navegador usa HTTPS en el puerto 8008, sin advertencias porque la cadena es de confianza pública. Las renovaciones posteriores de Proxmox ACME se validan y seleccionan durante la siguiente conexión TLS nueva; no existe un comprobador periódico del certificado ni se reinicia el servicio durante la renovación. <strong>Actualizar certificado</strong> permanece disponible en Seguridad como acción explícita de diagnóstico y recuperación."
"bodyRich": "Una vez que <code>/etc/pve/local/pveproxy-ssl.pem</code> está firmado por Let's Encrypt, abre <strong>Ajustes → Seguridad → HTTPS / SSL</strong>, comprueba que el emisor sea <em>Let's Encrypt</em> y no la CA local de Proxmox, y pulsa <strong>Usar certificado de Proxmox</strong>. Monitor se reinicia y la siguiente carga usa HTTPS en 8008 con una cadena de confianza pública. Las renovaciones ACME posteriores se validan y seleccionan en la siguiente conexión TLS nueva, sin sondeo periódico ni reinicio del servicio por renovación. <strong>Actualizar certificado</strong> sigue disponible en Seguridad como acción explícita de diagnóstico y recuperación."
},
"custom": {
"heading": "Certificado personalizado — cuándo usarlo",
"intro": "Pulsa <strong>Use Custom Certificate</strong> para introducir dos rutas absolutas:",
"intro": "Pulsa <strong>Usar certificado personalizado</strong> e introduce dos rutas absolutas:",
"items": [
"<strong>Certificado</strong> — cadena completa en PEM (<code>.pem</code> o <code>.crt</code>).",
"<strong>Clave privada</strong> — clave correspondiente en PEM (<code>.key</code>)."
"<strong>Clave privada</strong>: clave correspondiente en PEM (<code>.key</code>)."
],
"outro": "Ambos archivos los lee el proceso del Monitor al arrancar. Asegúrate de que se mantengan legibles por el usuario con el que corre la unidad systemd (root por defecto). Ubicaciones comunes cuando ACME se gestiona fuera de Proxmox:",
"code": "# certbot\n/etc/letsencrypt/live/<your-host>/fullchain.pem\n/etc/letsencrypt/live/<your-host>/privkey.pem\n\n# acme.sh\n~/.acme.sh/<your-host>_ecc/fullchain.cer\n~/.acme.sh/<your-host>_ecc/<your-host>.key",
@@ -143,15 +143,15 @@
},
"trustCa": {
"heading": "Confiar en la CA self-signed de Proxmox",
"intro1Rich": "Si prefieres mantener el certificado por defecto generado por Proxmox (sin ACME), puedes parar el warning del navegador importando la CA raíz del clúster en el almacén de confianza del SO o navegador. El Monitor seguirá autodetectando el mismo <code>/etc/pve/local/pveproxy-ssl.pem</code>; lo único que cambia es que el dispositivo que ve el panel ahora reconoce el issuer.",
"intro1Rich": "Para conservar el certificado predeterminado de Proxmox sin ACME, importa la CA raíz del clúster en el almacén de confianza del sistema o navegador. Monitor detecta <code>/etc/pve/local/pve-ssl.pem</code> como certificado alternativo. El cliente confiará en su emisor; la URL aún debe coincidir con un nombre del certificado.",
"intro2Rich": "El archivo de la CA vive en <code>/etc/pve/pve-root-ca.pem</code> en cada nodo. En un clúster la ruta está en el sistema de archivos compartido <code>pmxcfs</code>, así que todos los nodos comparten la misma raíz, y una sola importación cubre el datacenter entero. Cópialo a tu máquina:",
"code": "scp root@<your-host>:/etc/pve/pve-root-ca.pem ./pve-root-ca.pem",
"thenImport": "Después impórtalo en el lado del cliente:",
"items": [
"<strong>Linux (todo el sistema):</strong> <code>sudo cp pve-root-ca.pem /usr/local/share/ca-certificates/pve-root-ca.crt</code> seguido de <code>sudo update-ca-certificates</code>. Los navegadores que usan el almacén del sistema (Chromium, Edge) lo toman tras reiniciar; Firefox usa su propio almacén y necesita la importación manual de abajo.",
"<strong>macOS:</strong> doble clic en el archivo <code>.pem</code>, se abre Keychain Access → añádelo al keychain del <em>Sistema</em> → establece <em>Trust → Always Trust</em>.",
"<strong>Windows:</strong> clic derecho en el archivo → <em>Install Certificate</em> → colócalo en <em>Trusted Root Certification Authorities</em>.",
"<strong>Firefox (cualquier SO):</strong> <em>Settings → Privacy y Security → Certificates → View Certificates → Authorities → Import</em>, marca <em>Trust this CA to identify websites</em>."
"<strong>Linux (todo el sistema):</strong> ejecuta <code>sudo cp pve-root-ca.pem /usr/local/share/ca-certificates/pve-root-ca.crt</code> y después <code>sudo update-ca-certificates</code>. Los navegadores que usan el almacén del sistema (Chromium, Edge) lo reconocen tras reiniciar; Firefox usa su propio almacén y requiere la importación manual siguiente.",
"<strong>macOS:</strong> abre el archivo <code>.pem</code> con doble clic en Acceso a Llaveros, añádelo al llavero <em>Sistema</em> y configura <em>Confiar → Confiar siempre</em>.",
"<strong>Windows:</strong> clic derecho en el archivo → <em>Instalar certificado</em> → guárdalo en <em>Entidades de certificación raíz de confianza</em>.",
"<strong>Firefox (cualquier SO):</strong> <em>Ajustes → Privacidad y seguridad → Certificados → Ver certificados → Autoridades → Importar</em>; marca <em>Confiar en esta CA para identificar sitios web</em>."
],
"standalone": {
"title": "Nodos standalone fuera de un clúster",
@@ -160,9 +160,9 @@
},
"disable": {
"heading": "Deshabilitar HTTPS",
"bodyRich": "Pulsa <strong>Disable HTTPS</strong> en el mismo panel. El servicio del Monitor reinicia de vuelta en HTTP plano — útil si un archivo de certificado personalizado se vuelve no legible y el servicio no vuelve a levantarse. No hay paso de desinstalación aparte; los propios archivos de certificado no se tocan.",
"bodyRich": "Pulsa <strong>Deshabilitar HTTPS</strong> en el mismo panel. Monitor reinicia con HTTP sin cifrar, útil si un certificado personalizado no se puede leer y el servicio no arranca. No hay otra desinstalación y los archivos de certificado no se modifican.",
"stateCallout": {
"title": "Dónde vive el estado",
"title": "Dónde se guarda el estado",
"bodyRich": "<code>/etc/proxmenux/ssl_config.json</code> almacena las rutas de certificado activas y la fuente (<code>none</code>, <code>proxmox</code>, <code>custom</code>). Borrar el archivo equivale a deshabilitar HTTPS — en el siguiente arranque el Monitor recae en HTTP."
}
}
@@ -56,7 +56,7 @@
"<strong>Entrada del portal</strong> — escribe la IP o hostname del servidor del target iSCSI. Se asume el puerto <code>3260</code> a menos que escribas <code>host:port</code>.",
"<strong>Descubrimiento de targets</strong> — ProxMenux llama a <code>iscsiadm --mode discovery --type sendtargets --portal &lt;ip:port&gt;</code>. El servidor responde con cada IQN que permite ver a este initiator. Si el descubrimiento falla, el script muestra el error exacto de <code>iscsiadm</code> y lista las causas comunes (IP incorrecta, firewall, IQN del initiator no autorizado).",
"<strong>Selección del target</strong> — si hay un solo target se selecciona automáticamente; con varios targets se muestra un menú.",
"<strong>Storage ID</strong> — por defecto es <code>iscsi-&lt;último segmento del IQN, máx. 20 caracteres&gt;</code>. Solo letras, dígitos, <code>-</code> y <code>_</code>.",
"<strong>Storage ID</strong> — por defecto es <code>iscsi-&lt;last IQN segment, 20 chars max&gt;</code>. Solo letras, dígitos, <code>-</code> y <code>_</code>.",
"<strong>Content type</strong> — a diferencia de NFS / Samba, el contenido iSCSI está <strong>fijado a <code>images</code></strong>. iSCSI expone dispositivos de bloque raw, no un sistema de archivos, así que Proxmox solo te deja alojar discos de VM ahí."
],
"authTitle": "Autorizar el initiator de Proxmox en el target",
@@ -129,7 +129,7 @@
},
"troubleshoot": {
"heading": "Solución de problemas",
"noMountTitle": "El montaje aparece en la config del pct pero no dentro del contenedor",
"noMountTitle": "El montaje aparece en pct config, pero no dentro del contenedor",
"noMountBody": "Los bind mounts solo se adjuntan cuando el contenedor arranca. Si añadiste el montaje mientras el CT estaba corriendo, reinícialo (<code>pct reboot &lt;ctid&gt;</code>). Si ya está reiniciado y sigue faltando, comprueba <code>pct config &lt;ctid&gt;</code> para confirmar que la entrada existe y que la ruta del host realmente contiene un directorio.",
"noWriteTitle": "El contenedor puede ver el directorio pero no puede escribir",
"noWriteBody": "Casi siempre un problema de permisos. Para contenedores unprivileged, ejecuta de nuevo el fix de permisos del script — las ACLs del directorio del host pueden haber sido reseteadas por otra herramienta (rsync, restore desde backup, <code>chmod</code> manual). Para CIFS, revisa las opciones de montaje en el host: <code>findmnt /mnt/pve/cifs-…</code>, busca valores <code>uid=</code> / <code>gid=</code> / <code>file_mode=</code>.",