CT217: cobertura de backup declarada y observada¶
20 de octubre de 2026. Sólo fuentes y cuatro llamadas PVE autorizadas desde pmx2: recursos217, config217 filtrada, jobs y una consulta de snapshots. Sin backup, sync, verify, restore, drill, SQL/export, NAS walk, lectura de payload/secretos o cambios runtime. Sólo se redactó este informe.
Declaración runtime, 02:45:36.705338 CEST¶
CT217 figura running en proxmox2. Su config proyectada contiene rootfs zfs-ha:subvol-217-disk-0, size40G; ningún mpN declarado. Se descartaron env y campos lxc.*. /opt/observa y /home/monxas/appdata son rutas de guest bajo el rootfs declarado, sin un mount point PVE separado declarado para ellas; esto no descarta submontajes manuales, NFS interno o exclusiones de paths.
| Job que selecciona217 | enabled | schedule | storage | Selección/exclusión |
|---|---|---|---|---|
backup-lxc-terra |
1 | 01:00 | pbs |
vmid217 explícito, no excluido, nodo compatible |
Es el único job seleccionante observado; no quedaron selecciones pool sin resolver. No se copiaron targets ajenos ni se crea otro scheduler. Declaración de job no equivale a ejecución satisfactoria.
Snapshots listados, 02:46:41.579069 CEST¶
La llamada adicional exacta fue /nodes/proxmox2/storage/pbs/content --content backup --vmid217. Se conservaron hasta tres entradas recientes; la respuesta contenía dos:
| Volid | ctime CEST | size informado |
|---|---|---|
pbs:backup/ct/217/2026-10-19T23:02:36Z |
20oct01:02:36 | 19.924.189.387 B (~18,56 GiB) |
pbs:backup/ct/217/2026-10-19T07:08:28Z |
19oct09:08:28 | 17.079.081.109 B (~15,91 GiB) |
Edad del último ctime: 1h44m05,58s. Size es metadata API, no uso deduplicado ni bytes verificados. No se consultaron worker status/endtime, integridad ni contenido. Los snapshots listados no prueban restore, coherencia de aplicaciones o inclusión de cada ruta.
El último ctime precede a Required instalada a las02:12: no se acredita que ese snapshot contenga esa versión; tampoco se infiere su exclusión sin payload/intervalo del job. La regla tiene su fuente Git. La auditoría anterior registraba a las23:02 «28 invitados con copia PBS<26h»: evidencia agregada reciente compatible con217, no un restore suyo.
Matriz de configuración y persistencia¶
El perfil declara diez servicios y 16 binds Docker absolutos: siete de configuración/secretos y nueve de datos. Un Docker bind dentro del guest no es por ello un mount PVE externo excluido de vzdump. Para todos los paths siguientes rige la condición rootfs anterior, sin comprobación de payload:
| Paths de guest | Fuente disponible / límite de recuperación |
|---|---|
/opt/observa/compose.yaml |
Perfil/hash e identidades de imágenes; no Compose completo ni bindings de secretos reconstruidos |
/opt/observa/conf/prometheus.yml |
Template reconciliado26jobs; autenticación no acreditada por esta auditoría; hash c8… previo no comparado con PBS |
/home/monxas/appdata/prometheus/alerts.yml |
Fuente versionada87reglas; versión actual en PBS no comprobada |
appdata/alertmanager/{alertmanager.yml,telegram-bot-token,vera-alert-secret} |
YAML candidato Git; contenido runtime y secretos no verificados; tres mounts RO |
appdata/blackbox/blackbox.yml, appdata/loki-config/loki-config.yaml |
Paths observados; no fuente completa actual localizada; ausencia Git no demuestra ausencia PBS |
Datos appdata/{alertmanager/data,grafana,healthchecks,loki,prometheus/data,pushgateway,scrutiny/config,scrutiny/influxdb,uptime-kuma} |
Nueve binds de datos; JSON Grafana parciales no equivalen a sus bases; sin prueba de consistencia/restore |
| Named/anonymous volumes | Cero named volumes declarados; no descarta image-declared VOLUME, anónimos ni Docker data-root separado: no se inspeccionó Mounts |
appdata/… abrevia /home/monxas/appdata/…. RepoDigests observados no sustituyen backups de datos ni acreditan disponibilidad de registry. El perfil conserva complete_recovery_spec: false.
Huecos concretos y propuesta mínima¶
- backup-retention.md conserva targets verificados en agosto, anteriores a217. La lectura actual sí acredita su selección: no interpretar la tabla antigua como ausencia de backup ni como inventario actual completo.
- backup-appdata-fixed.sh, líneas28–39, pertenece a VM208; horario retirado el8sept. No declara una copia diaria de
/opt/observani del appdata trasladado. No se propone reactivarlo. - pbs_restore_drill.py, líneas42–44, permite LXC100/123/155/200/251 y config123: excluye217. El drill19oct probó123. No se encontró prueba de restore217; no añadirlo sin más al pool aleatorio con su pila de diez servicios.
normalidadcomprueba jobs y frescura, no mounts/payload/coherencia. El éxito agregado no cierra esos huecos.
En esta fase inicial sólo se acreditaron job declarado y snapshot listado, separados de paths comprobados y restore probado. La observación posterior de las 07:16 añade metadatos de las rutas actuales; no acredita payload ni restauración. Antes de un ensayo futuro siguen pendientes volúmenes Docker no representados, exclusiones del snapshot y extracción/restore aislado con límites revisados. No requiere otro daemon, cron o backup.
Evidencia privada y cierre¶
Archivos0600, fsync de archivo/directorio, sólo metadata filtrada:
~/.local/state/homelab-incident-evidence/ct217-backup-metadata-20261020T004541Z.json, SHA256<REDACTED>.~/.local/state/homelab-incident-evidence/ct217-pbs-snapshots-20261020T004641Z.json, SHA256<REDACTED>.
Las cuatro llamadas de la fase inicial terminaron rc0. En aquella fase no hubo más SSH/PVE tras snapshots, ni cambios en código, perfiles, jobs o almacenamiento.
Observación posterior de los 16 binds de las 07:16 CEST¶
El 20 de octubre, 07:16:46,037910–07:16:47,313624 CEST, una única SSH agregada
por pmx2 revalidó mediante API CT217 en marcha en proxmox2 y proyectó sólo
rootfs/mpN: zfs-ha:subvol-217-disk-0,size=40G, ningún mpN. Dentro del guest
se consultaron metadatos de las 16 rutas de origen ya enumeradas en el perfil,
además del montaje raíz.
- Las 16 rutas existen: 7 archivos regulares y 9 directorios, sin symlink en el último componente de esas rutas.
- Findmnt de cada ruta muestra montaje
/, ZFS y dispositivo 0:54, iguales al rootfs. - Mountinfo consumido en RAM y filtrado bajo esas 16 rutas: 0 submontajes internos observados. No hubo recorrido de archivos, lectura de datos, secretos o bases de datos ni inspect, entorno, Compose o llamadas a aplicaciones.
- La clave nueva
bind_rootfs_metadata_observationdel perfil canónico conserva ruta de origen, tipo, propietario, modo, dispositivo y procedencia. No sustituye las capturas históricas ni modificacomplete_recovery_spec: false.
Estos metadatos actuales no revelan un hueco externo de cobertura por esos binds. No prueban que el snapshot de las 01:02 contenga esas rutas, sus datos o sus permisos, ni sus exclusiones o la consistencia de las bases de datos. Ninguna de las 16 rutas es un socket, dispositivo o proc/sys; no incluir esos recursos o dependencias externas como si fueran datos respaldados. La cobertura declarada del rootfs y un snapshot listado siguen separados de una restauración verificada.
Los propietarios difieren: Healthchecks 999:999, Kuma 0:0, varios datos 1000:1000 y configuración de Prometheus 0:0. El modo 0777 del directorio Pushgateway es un hecho observado; no se cambió ni se declaró una vulnerabilidad por ese dato aislado. No normalizar propietarios con chown recursivo. El checklist existente de restore apagado debe comparar cada archivo con la versión de su snapshot, no con las 89 reglas actuales. No se restauró ni arrancó un guest o servicio en esta comprobación.
Revisión de fuente: namespace e identidad antes de comparar propietarios¶
La inspección apagada del checklist debe distinguir los UID/GID observados
dentro del guest de los que expone su filesystem montado desde el host.
Antes de comparar owners, acreditar el modo y el mapa del snapshot y del destino;
no resolver diferencias con chown recursivo. El perfil de CT217 no acredita aquí
su modo ni un mapa personalizado: esta revisión no afirma que los use.
Se comprobó una brecha del motor genérico: isolate retiraba lxc.idmap como
cualquier otra opción lxc.* antes de arrancar. Una fixture local del flujo
completo aceptaba ese caso y terminaba bien, sin conservar la necesidad de revisión.
El candidato añade una lectura previa pvesm extractconfig de la copia LXC y la
misma guarda antes de modificar la configuración restaurada y durante su prueba
de propiedad para limpieza. Rechaza mapas personalizados, includes, valores
malformados y duplicados. Antes de admitir el modo por defecto, exige una
configuración LXC con un único rootfs no vacío: salida vacía, comentarios,
configuración VM o rootfs ausente/duplicado/vacío fallan antes de restore. No
exige al volumen original el prefijo del VMID temporal. La configuración se consume sólo en RAM; el recibo
privado conserva su SHA y el modo de origen, distinguiendo valor explícito de
default, además de la política exigida al destino. No imprime su contenido.
Esto no debe bloquear la conversión soportada de privilegiado a no privilegiado:
- La definición oficial de configuración
declara el default
unprivileged=0. Se admiten origen explícito0o1, o ausencia de esa opción con ese significado; no se aceptan valores ambiguos. - La API de restore
aplica el
--unprivileged 1solicitado al destino; sólo hereda el modo del backup cuando no hay override. También puede recuperar mapas LXC originales, razón para rechazarlos antes de restaurar en este ensayo conservador. - La extracción PBS
usa el namespace de la configuración de destino. Sin mapa personalizado,
Proxmox define el mapa no privilegiado predeterminado.
El candidato sigue exigiendo destino explícito
1sin mapas/includes antes de editar, etiquetar, arrancar o limpiar; no cambia owners a mano.
La consulta de estas fuentes oficiales describe el mecanismo, no una prueba de conversión en los nodos instalados ni la funcionalidad posterior de aplicaciones. Si el error aparece antes de restore, no se crean recursos del guest; si aparece después, se conserva su configuración sin sanitizar ni etiquetar y se retiene la reserva para revisión, sin stop/destroy automático.
Validación exclusivamente local: 62 pruebas, incluidos origen privilegiado
explícito/default con restore solicitado a modo 1, rechazo de destino aún
privilegiado, mapas/includes y drift durante limpieza. Pasan con Python 3.12 y
3.14; gramática 3.10 comprobada. Los dobles bloquean PVE real; no se ejecutó SSH,
restore, backup, arranque o cambio de configuración runtime. Esto no certifica
el mapa global del host, el contenido de CT217 ni una recuperación completa.
Helper PBS instalado y verificado el20oct13:34–13:37 CEST¶
La fuente de las guardas anteriores está en main. A13:34:22 se reemplazó
/usr/local/bin/pbs_restore_drill.py en proxmox bajo comprobación de identidad y
lock del archivo existente; se preservó root:root0755. Respaldo privado:
/root/rollback-pbs-identity-20261020-76l5v4jd. En proxmox2 el instalador encontró
ya el candidato exacto y terminó already_current, sin escribir ni crear nuevo
backup. No se atribuye esa convergencia a Ansible-pull sin recibo que lo pruebe.
La lectura independiente13:37:53–54 confirma ambos helpers con SHA256
<REDACTED>,
19849bytes, un enlace, root:root0755, y compilación nativa con Python3.13.5.
Cero procesos conocidos de drill, cero cmdlines ilegibles, reserva ausente y
VMID9901/9902 ausentes tanto en la API como en los archivos de configuración.
No se importó ni ejecutó el helper, tampoco help, restore, start, stop o destroy.
Las62pruebas acreditan el comportamiento de fuente; la instalación y compilación no acreditan una conversión real de UID/GID ni recuperación funcional de CT217. La retención vigente se reconcilió aparte con metadatos fechados: políticas PBS y límites. Recuperación del helper de proxmox requiere comprobar candidato y backup antes de reemplazar preservando dueño/modo; no revertir reservas ni recursos de ensayo como parte de ese cambio.