Backup Restore Strategy¶
Objetivo¶
Mantener la certificacion DR en VERDE con backup recurrente diario,
retencion clara y evidencia exportable fuera del VPS sin tocar el runtime
productivo.
Restricciones respetadas¶
- SAFE POINT inicial tomado
- sin tocar DNS
- sin tocar firewall
- sin tocar NPM operativo
- sin borrar OpenClaw productivo
- sin detener produccion
Safe Point Inicial¶
- Fecha local:
2026-05-31 - Commit base:
6445ca4e989d3ac287ce658ec4badf96ac006476 git status --shortinicial: limpio- Host remoto:
srv977009 - Contenedores activos:
openclaw-openclaw-gateway-1nginx-proxy-managerportainer
Fase 1 - Inventario exacto de reconstruccion¶
| Activo | Ruta real | Tamano | Critico | Metodo de restore |
|---|---|---|---|---|
| OpenClaw compose | /opt/stacks/openclaw/docker-compose.yml |
3356 B |
si | restaurar archivo versionado o extraer desde openclaw-stack.tgz |
| OpenClaw env | /opt/stacks/openclaw/.env |
969 B |
si | restaurar archivo desde backup al mismo path con permisos 600 |
| OpenClaw config | /opt/stacks/openclaw/config |
715937 B |
si | extraer backup al mismo path y conservar owner operativo |
| OpenClaw workspace | /opt/stacks/openclaw/workspace |
37562 B |
si | extraer backup al mismo path |
| OpenClaw auth-profile-secrets | /opt/stacks/openclaw/auth-profile-secrets |
0 B |
medio | recrear directorio vacio; no contiene la auth efectiva observada |
| NPM compose | /docker/nginx-proxy-manager/docker-compose.yml |
510 B |
si | restaurar archivo y recrear stack |
| NPM data | /docker/nginx-proxy-manager/data |
1149405 B |
si | restaurar arbol completo; incluye database.sqlite, keys.json, nginx/proxy_host/*.conf y logs |
| NPM certificados SSL | /docker/nginx-proxy-manager/letsencrypt |
46827 B |
si | restaurar arbol completo antes de levantar NPM |
| NPM Proxy Hosts | /docker/nginx-proxy-manager/data/nginx/proxy_host/*.conf |
dentro de data |
si | queda cubierto por backup de data; archivos observados 2.conf y 3.conf |
| Portainer volumen activo | /var/lib/docker/volumes/portainer_data_new/_data |
527043 B |
si | extraer backup sobre un volumen nuevo o restaurado y recrear contenedor |
| Portainer config metadata | /var/lib/docker/volumes/portainer_data_new/_data/compose |
dentro de volumen | si | queda cubierta por backup del volumen; se observaron compose/1/docker-compose.yml y compose/2/docker-compose.yml |
| Backup VPS | proveedor Hostinger + reprovision manual del host | externo | si | snapshot si existe; si no, reprovision Ubuntu + Docker + restore de NPM/OpenClaw/Portainer |
Fase 2 - Estrategia de backup restaurable y automatizable¶
OpenClaw¶
- Fuente:
/opt/stacks/openclaw/docker-compose.yml/opt/stacks/openclaw/.env/opt/stacks/openclaw/config/opt/stacks/openclaw/workspace/opt/stacks/openclaw/auth-profile-secrets- Tratamiento:
- copia de archivos y directorios a staging
- backup logico de SQLite para:
config/flows/registry.sqliteconfig/memory/main.sqliteconfig/tasks/runs.sqlite
- eliminacion de
*.sqlite-waly*.sqlite-shmen el snapshot - Salida:
openclaw-stack.tgz
NPM¶
- Fuente:
/docker/nginx-proxy-manager/docker-compose.yml/docker/nginx-proxy-manager/data/docker/nginx-proxy-manager/letsencrypt- Tratamiento:
- copia a staging
- backup logico de SQLite para
/docker/nginx-proxy-manager/data/database.sqlite - Salida:
npm-stack.tgz
Portainer¶
- Fuente:
- volumen
portainer_data_new - mountpoint:
/var/lib/docker/volumes/portainer_data_new/_data - Tratamiento:
- copia byte a byte del volumen a staging
portainer.dbse conserva como archivo binario porque el host lo reporta comodata, no como SQLite legible- Salida:
portainer-volume.tgz
VPS¶
- Cobertura real conseguida en esta etapa:
- reconstruccion documentada del host sin depender de Git para secretos
- backup de componentes aplicacionales y administrativos criticos
- Cobertura externa:
- snapshot del proveedor si esta disponible
- Si no hay snapshot:
- reprovision Ubuntu
24.04 - instalar Docker y Compose
- recrear
proxy-network - restaurar NPM
- restaurar OpenClaw
- restaurar Portainer
Fase 3 - Procedimiento operativo¶
Backup¶
- Verificar SAFE POINT:
git status -sbygit rev-parse HEAD - Ejecutar:
powershell -ExecutionPolicy Bypass -File scripts/dr/Invoke-DrBackupRestoreEvidence.ps1 -HostAlias openclaw-vps - Conservar:
- ruta
BASE=/tmp/dr-green-<timestamp> sha256sumde cada.tgz- stdout completo como evidencia
Backup recurrente diario¶
- Script VPS:
scripts/backup/openclaw-vps-backup.sh- Ruta instalada en VPS:
/root/openclaw-backups/bin/openclaw-vps-backup.sh- Frecuencia:
- diaria
03:00porcrontab - Retencion:
- diarios:
30 dias - semanales:
12copias si la corrida ocurre en domingo - logs:
90 dias - Rutas de salida:
- diarios:
/root/openclaw-backups/daily/<timestamp> - semanales:
/root/openclaw-backups/weekly/<YYYY-weekWW> - logs:
/root/openclaw-backups/logs/openclaw-backup-<timestamp>.log - Artefactos por corrida:
openclaw-stack.tgznpm-stack.tgzportainer-volume.tgzSHA256SUMSmanifest.txt- Seguridad aplicada:
umask 077- directorios
700 - archivos
600 - sin impresion de secretos en stdout ni en logs
Copia externa de evidencia¶
- Script Windows:
scripts/backup/pull-openclaw-backups-to-windows.ps1- Ruta local preparada:
C:\APV\backups\openclaw\- Comportamiento:
- resuelve el backup remoto mas nuevo o uno puntual
- copia por
scp - valida
SHA256SUMS - deja log local en
C:\APV\backups\openclaw\logs\ - Automatizacion:
- no instalada todavia
Task Schedulerqueda como paso opcional posterior a validar almacenamiento, permisos y capacidad local
Verificacion de cron¶
- Script de instalacion:
scripts/backup/install-vps-cron.sh- Entrada instalada:
0 3 * * * /root/openclaw-backups/bin/openclaw-vps-backup.sh >/dev/null 2>&1- Verificar:
crontab -lcrontab -l | grep -F 'openclaw-recurring-backup'- No duplica entradas existentes.
Validacion¶
- Confirmar que el script crea:
openclaw-stack.tgznpm-stack.tgzportainer-volume.tgz- Confirmar extraccion de prueba en:
restore/openclawrestore/npmrestore/portainer- Validar contenido minimo:
- OpenClaw:
.env,docker-compose.yml,config/openclaw.json,config/agents/main/agent/auth-profiles.json - NPM:
data/database.sqlite,data/nginx/proxy_host/*.conf,letsencrypt/live/ - Portainer:
compose/*/docker-compose.yml,portainer.db
Restauracion¶
- Preparar VPS base o staging host con Docker y Compose.
- Restaurar NPM primero:
- extraer
npm-stack.tgzen/docker/nginx-proxy-manager cd /docker/nginx-proxy-manager && docker compose up -d- Restaurar OpenClaw despues:
- extraer
openclaw-stack.tgzen/opt/stacks/openclaw - recrear
proxy-networksi falta:docker network create proxy-network cd /opt/stacks/openclaw && docker compose up -d- Restaurar Portainer al final:
- crear volumen nuevo o reutilizar
portainer_data_new - extraer
portainer-volume.tgzdentro del mountpoint del volumen - recrear contenedor
portainercon mismodocker.sock, puertos y red - Smoke tests obligatorios:
docker psdocker inspect -f '{{.State.Health.Status}}' openclaw-openclaw-gateway-1curl -I https://openclaw.alpuntodeventa.com.ar/curl -k -I https://127.0.0.1:9443curl -I http://127.0.0.1:81
Fase 4 - Persistencia exacta de auth OpenAI¶
- El bind mount
auth-profile-secrets/no guarda la auth efectiva en este despliegue. - Los archivos observados que si persisten auth y estado del agente son:
/opt/stacks/openclaw/config/agents/main/agent/auth-profiles.jsonprofiles:openai:default
/opt/stacks/openclaw/config/agents/main/agent/auth-state.jsonlastGood:openaiusageStats:openai:default
/opt/stacks/openclaw/config/identity/device-auth.jsontokens:operator
- Mecanismo:
- el contenedor monta
./config:/home/node/.openclaw - esos archivos viven en el filesystem del host
- por eso sobreviven a reinicios y recreacion del contenedor
Fase 5 - Simulacion controlada no destructiva¶
- Ejecucion evidenciada:
- staging y backups en
/tmp/dr-green-20260531-011407 - Checksums reales:
openclaw-stack.tgzf2a659b9a4564b2561779d39842b46c83a439e76f389a9c1580313a3d7e9d20fnpm-stack.tgzcf64d4a8bef17a6f8c4c3ea8637e951c0b69abab91cd9461e35f16de10852c43portainer-volume.tgzfd8c9385307ee27c5525c8089baee94aa1eae68e4d8968ac5a212cf8e75c2a32- Restore no destructivo validado por extraccion de:
- OpenClaw:
config/flows/registry.sqliteconfig/memory/main.sqliteconfig/tasks/runs.sqlite
- NPM:
data/nginx/proxy_host/2.confdata/nginx/proxy_host/3.conf
- Portainer:
compose/1/docker-compose.ymlcompose/2/docker-compose.yml
- Resultado:
- los backups se generan
- contienen datos validos
- pueden restaurarse teoricamente sin tocar produccion
Fase 6 - RTO y RPO con evidencia real¶
- La masa total dedicada a restaurar es pequena, menor a
2.5 MBsin compresion pesada adicional. - La simulacion genero y extrajo los tres backups en la misma sesion sin errores de integridad.
- RTO certificado:
- mismo VPS, contenedores o datos restaurados:
30-45 minutos - VPS nuevo desde cero:
90-180 minutos - RPO certificado:
0para la copia obtenida en la simulacion puntual- recurrente esperado:
24 horaspor backup diario
Fase 7 - Implementacion recurrente validada 2026-05-31¶
- SAFE POINT local inicial de esta implementacion:
git status -sb->## main...origin/maingit rev-parse HEAD->32ad551e89714e6a6d16bd99d4a2df7e74f6d878- VPS validado:
hostname->srv977009docker ps-> OpenClawhealthy, NPMup, Portainerup- Corrida manual validada:
/root/openclaw-backups/daily/20260531-014038- Checksums reales de la corrida final:
openclaw-stack.tgz9169e9361aad7ef09e98ab08346d296d3c5ee00da43d47b63c7bbb996986cb00npm-stack.tgz753dad1908e26870aa8e935429df03318f05b7a93ab3050748758c7520788246portainer-volume.tgzee35d0930b602c5f82ce6b24cb6dc6ec19033cab90f5ffb310deb5745af0f7ab- Manifest y log:
manifest.txtpresenteSHA256SUMSpresente- log presente en
/root/openclaw-backups/logs/openclaw-backup-20260531-014038.log - Semanal:
2026-week22creado sin duplicar al repetir la corrida del mismo domingo- Copia externa validada:
C:\APV\backups\openclaw\daily\20260531-014038- log local:
C:\APV\backups\openclaw\logs\pull-openclaw-backups-20260531-014048.log
Fase 8 - Certificacion final¶
- Certificacion final:
VERDE
Base de la decision¶
- Hay evidencia real de inventario, backup y restore de staging.
- La auth OpenAI quedo localizada y no depende del directorio vacio
auth-profile-secrets. - NPM y OpenClaw ya no dependen solo de snapshots implícitos.
- El restore paso de teorico a demostrable en entorno controlado.
Riesgos encontrados¶
- El snapshot del proveedor no fue revalidado en panel en esta sesion.
portainer.dbse respalda como binario propio y no como SQLite logico.- El RPO futuro depende de que cron siga habilitado y de revisar periodicamente los logs de ejecucion.
- La copia externa sigue siendo manual hasta aprobar una automatizacion controlada en Windows.
- Los backups contienen secretos operativos; deben quedar fuera de Git y del workspace.
Checklist de cierre¶
- SAFE POINT inicial:
SI - Inventario completo:
SI - Evidencia backups:
SI - Evidencia persistencia auth:
SI - Riesgos encontrados:
SI - Archivos modificados:
docs/BACKUP-RESTORE-STRATEGY.mddocs/DISASTER-RECOVERY-RUNBOOK.mddocs/PROJECT-STATE.mddocs/ROADMAP.mdscripts/README.mdscripts/dr/README.mdscripts/dr/Invoke-DrBackupRestoreEvidence.ps1- Commit SHA base:
6445ca4e989d3ac287ce658ec4badf96ac006476 git statusfinal: validar al cierre local- Certificacion final:
VERDE - Proximo paso unico recomendado:
automatizar la descarga externa con
Task Schedulersolo despues de validar espacio, politicas de retencion local y resguardo del equipo