Complete implementation ready for Coolify: - Node.js 22 + Fastify + socket.io backend - PostgreSQL 16 + Redis 7 services - Docker Compose configuration - Deployment scripts and documentation Co-Authored-By: Paperclip <noreply@paperclip.ing>
11 KiB
AgentHub Backup & Restore Runbook
Version: 1.0
Date: 2026-04-30
Maintainer: FoundingEngineer
Related ADR: ADR-0004 Déploiement
Table of Contents
- Backup Strategy
- Automated Backups
- Manual Backup
- Restore Procedure
- Disaster Recovery
- Weekly Encrypted Backups
- Troubleshooting
Backup Strategy
AgentHub utilise une stratégie de backup à deux niveaux :
- Backups locaux journaliers : pg_dump à 03:00 UTC, rétention 14 jours sur
/opt/agenthub/backups - Backups distants hebdomadaires : copie chiffrée GPG vers Scaleway Object Storage Paris, rétention 8 semaines
RPO (Recovery Point Objective) : 24 heures
RTO (Recovery Time Objective) : < 30 minutes pour un restore standard
Automated Backups
Les backups sont orchestrés par Ofelia (scheduler Docker) qui exécute le container backup quotidiennement.
Vérifier le statut des backups
# Lister les backups locaux
ls -lh /opt/agenthub/backups/
# Vérifier les logs Ofelia
docker compose -f compose.lan.yml logs ofelia
# Vérifier les logs du dernier backup
docker compose -f compose.lan.yml logs backup | tail -50
Configuration du backup automatique
Le service backup est configuré dans compose.lan.yml et compose.coolify.yml :
- Schedule :
0 0 3 * * *(03:00 UTC tous les jours) - Rétention locale : 14 jours (gérée automatiquement par le script)
- Format : PostgreSQL custom format (
-Fc), optimal pour restore sélectif - Destination :
/opt/agenthub/backups/agenthub_YYYYMMDD_HHMMSS.dump
Manual Backup
Backup manuel immédiat
# Exécuter un backup manuel
docker compose -f compose.lan.yml run --rm backup
# Vérifier que le backup est créé
ls -lh /opt/agenthub/backups/ | tail -1
Backup one-shot hors Docker
# Depuis l'hôte (nécessite psql installé)
PGPASSWORD='<postgres-password>' pg_dump -Fc \
-h localhost \
-p 5432 \
-U agenthub \
-d agenthub \
-f "/opt/agenthub/backups/manual_$(date -u +%Y%m%d_%H%M%S).dump"
Restore Procedure
Pré-requis
- Fichier de backup disponible (
.dump) - Accès au serveur Postgres cible
- Variables d'environnement Postgres configurées (
PGHOST,PGUSER,PGPASSWORD)
Restore standard (production down)
Cas d'usage : restaurer la base de production après corruption ou perte de données.
# 1. Arrêter l'application pour éviter les connexions actives
docker compose -f compose.lan.yml stop app
# 2. Lancer le restore (interactive confirmation)
docker compose -f compose.lan.yml run --rm \
-e PGHOST=postgres \
-e PGDATABASE=agenthub \
-e PGUSER=agenthub \
-e PGPASSWORD="${POSTGRES_PASSWORD}" \
backup \
/usr/local/bin/restore.sh /backups/agenthub_20260430_030000.dump
# 3. Vérifier l'intégrité après restore
docker compose -f compose.lan.yml run --rm postgres \
psql -h postgres -U agenthub -d agenthub -c "SELECT COUNT(*) FROM agents;"
# 4. Redémarrer l'application
docker compose -f compose.lan.yml start app
Restore vers base éphémère (test)
Cas d'usage : valider un backup avant de l'utiliser en production.
# 1. Créer une base de test
docker compose -f compose.lan.yml exec postgres \
psql -U agenthub -d postgres -c "CREATE DATABASE agenthub_test OWNER agenthub;"
# 2. Restore vers la base de test
docker compose -f compose.lan.yml run --rm \
-e PGHOST=postgres \
-e PGDATABASE=agenthub_test \
-e PGUSER=agenthub \
-e PGPASSWORD="${POSTGRES_PASSWORD}" \
-e SKIP_CONFIRMATION=yes \
backup \
/usr/local/bin/restore.sh /backups/agenthub_20260430_030000.dump agenthub_test
# 3. Vérifier la restauration
docker compose -f compose.lan.yml exec postgres \
psql -U agenthub -d agenthub_test -c "\dt"
# 4. Comparer le nombre de tables
PROD_TABLES=$(docker compose -f compose.lan.yml exec postgres \
psql -U agenthub -d agenthub -t -c \
"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='public';")
TEST_TABLES=$(docker compose -f compose.lan.yml exec postgres \
psql -U agenthub -d agenthub_test -t -c \
"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='public';")
echo "Prod tables: ${PROD_TABLES}"
echo "Test tables: ${TEST_TABLES}"
# 5. Cleanup
docker compose -f compose.lan.yml exec postgres \
psql -U agenthub -d postgres -c "DROP DATABASE agenthub_test;"
Disaster Recovery
Scénario 1 : Corruption de la base de production
Impact : Application down, données corrompues
- Arrêter l'application :
docker compose -f compose.lan.yml stop app - Identifier le dernier backup sain :
ls -lht /opt/agenthub/backups/ | head -5 - Restaurer depuis ce backup (voir Restore standard)
- Redémarrer :
docker compose -f compose.lan.yml start app - Smoke test :
curl -fsS http://<host>:3000/healthz
Temps estimé : 5–10 minutes
Scénario 2 : Perte totale du volume pgdata
Impact : Volume Docker perdu, base de données inexistante
- Recréer le volume :
docker volume create <project>_pgdata - Démarrer Postgres :
docker compose -f compose.lan.yml up -d postgres - Attendre que Postgres initialise :
docker compose -f compose.lan.yml logs -f postgres - Restaurer le dernier backup (voir Restore standard)
- Redémarrer l'application :
docker compose -f compose.lan.yml up -d
Temps estimé : 10–15 minutes
Scénario 3 : Perte totale du serveur
Impact : Serveur hôte down, backups locaux inaccessibles
- Provisionner un nouveau serveur (voir
scripts/bootstrap.shdans le repo) - Télécharger le backup hebdomadaire chiffré depuis Scaleway Object Storage :
aws s3 cp \ "s3://${S3_BUCKET}/weekly/agenthub_<date>.dump.gpg" \ /tmp/backup.dump.gpg \ --endpoint-url "${S3_ENDPOINT}" - Déchiffrer le backup :
gpg --decrypt /tmp/backup.dump.gpg > /tmp/backup.dump - Copier le backup dans le volume :
mkdir -p /opt/agenthub/backups mv /tmp/backup.dump /opt/agenthub/backups/ - Lancer la stack :
docker compose -f compose.lan.yml up -d - Restaurer (voir Restore standard)
Temps estimé : 30–60 minutes (selon taille du backup et bande passante)
Weekly Encrypted Backups
Les backups hebdomadaires (dimanche 03:00 UTC) sont chiffrés GPG et uploadés vers Scaleway Object Storage.
Vérifier les backups distants
# Lister les backups sur Scaleway
aws s3 ls "s3://${S3_BUCKET}/weekly/" --endpoint-url "${S3_ENDPOINT}"
Télécharger et déchiffrer un backup distant
# Télécharger
aws s3 cp \
"s3://${S3_BUCKET}/weekly/agenthub_20260427_030000.dump.gpg" \
/tmp/backup.dump.gpg \
--endpoint-url "${S3_ENDPOINT}"
# Déchiffrer (nécessite la clé privée GPG correspondante)
gpg --decrypt /tmp/backup.dump.gpg > /tmp/backup.dump
# Restaurer
# (voir section Restore Procedure)
Configuration S3 et GPG
Les variables d'environnement suivantes doivent être configurées dans .env :
S3_ENDPOINT=https://s3.fr-par.scw.cloud
S3_BUCKET=agenthub-backups-paris
AWS_ACCESS_KEY_ID=<scaleway-access-key>
AWS_SECRET_ACCESS_KEY=<scaleway-secret-key>
GPG_RECIPIENT_KEY=<gpg-public-key-id>
Troubleshooting
Le backup automatique ne s'exécute pas
Symptômes : Aucun nouveau backup depuis > 24h
- Vérifier que le service Ofelia est up :
docker compose -f compose.lan.yml ps ofelia - Vérifier les logs Ofelia :
docker compose -f compose.lan.yml logs ofelia | grep backup-daily - Vérifier les labels du service
backupdanscompose.lan.yml:labels: ofelia.enabled: "true" ofelia.job-exec.backup-daily.schedule: "0 0 3 * * *" ofelia.job-exec.backup-daily.command: "/usr/local/bin/backup.sh" - Relancer Ofelia :
docker compose -f compose.lan.yml restart ofelia
Le restore échoue avec "permission denied"
Cause probable : Mauvais utilisateur Postgres ou base verrouillée
- Vérifier que l'application est arrêtée :
docker compose -f compose.lan.yml stop app - Tuer les connexions actives :
docker compose -f compose.lan.yml exec postgres \ psql -U postgres -d postgres -c \ "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='agenthub';" - Relancer le restore
Backup file is empty or missing
Cause probable : pg_dump a échoué (credentials, réseau, espace disque)
- Vérifier les logs du container backup :
docker compose -f compose.lan.yml logs backup - Vérifier l'espace disque sur l'hôte :
df -h /opt/agenthub/backups - Tester manuellement pg_dump :
docker compose -f compose.lan.yml run --rm backup \ pg_dump -h postgres -U agenthub -d agenthub --version
GPG encryption fails lors du backup hebdomadaire
Cause probable : GPG_RECIPIENT_KEY manquant ou invalide
- Vérifier que la clé GPG est importée dans le container :
docker compose -f compose.lan.yml run --rm backup gpg --list-keys - Importer la clé publique si manquante :
docker compose -f compose.lan.yml run --rm backup \ gpg --import /path/to/public-key.asc - Vérifier la variable d'environnement
GPG_RECIPIENT_KEYdans.env
Drill de restore (procédure mensuelle recommandée)
Objectif : Valider que les backups sont restaurables et complets.
# 1. Sélectionner un backup récent
BACKUP_FILE="/opt/agenthub/backups/$(ls -t /opt/agenthub/backups/ | head -1)"
echo "Testing backup: ${BACKUP_FILE}"
# 2. Restore vers base éphémère
# (voir section "Restore vers base éphémère (test)")
# 3. Vérifier le checksum du backup
sha256sum "${BACKUP_FILE}" > /tmp/backup-checksum.txt
cat /tmp/backup-checksum.txt
# 4. Comparer le nombre de tables
# (voir section "Restore vers base éphémère (test)")
# 5. Cleanup et documenter
# Enregistrer le résultat du drill dans un log de suivi
Fréquence recommandée : 1 fois par mois minimum
Contacts et Escalation
- Responsable technique : FoundingEngineer
- Documentation source :
agenthub/docs/RUNBOOK-restore.md - Scripts :
agenthub/scripts/{backup,restore}.sh - ADR associé : ADR-0004