Backup / Restore — Aurora Nexus (MVP Safe)
(depuis `BACKUP_RESTORE.md`)
Objectif : disposer d’un rollback clair avant toute livraison client (cf. docs/MVP_SAFE_ROLLOUT.md).
1) Backup (recommandé)
Postgres (obligatoire)
- Préflight + backup DB :
bash ops/preflight_safe_rollout.sh - Backup DB seul :
bash ops/backup_postgres.sh- sortie par défaut :
tmp/backups/postgres_YYYYmmdd_HHMMSS.sql.gz
- sortie par défaut :
- Backup quotidien automatisé :
bash ops/install_postgres_backup_timer.sh- timer systemd :
aurora-nexus-postgres-backup.timer - horaire :
06:00 UTC - script :
ops/backup_postgres_daily.sh - garde-fou : attend que l'ingestion n'ait plus de jobs
queued,queued_retryourunning, puis 15 minutes de calme depuis le dernierfinished_at - timeout garde-fou : 180 minutes ; en cas de timeout, le backup échoue explicitement et le sentinel n'est pas rafraîchi
- rétention locale : 2 jours par défaut via
POSTGRES_BACKUP_RETENTION_DAYS=2
- timer systemd :
Le dernier backup réussi est publié dans tmp/backups/postgres_latest.json. /api/ops/health utilise ce fichier pour le composant components.postgres_backup; ne pas modifier ce fichier manuellement pour faire passer le monitoring.
Commandes utiles :
systemctl list-timers --all aurora-nexus-postgres-backup.timer
sudo systemctl start aurora-nexus-postgres-backup.service
journalctl -u aurora-nexus-postgres-backup.service -n 100 --no-pagerLe dump Postgres est un dump logique complet quotidien. Il est volontairement conservé même si un backup OVH existe : OVH couvre surtout le niveau infrastructure/volume, alors que le dump logique facilite une restauration applicative ciblée. En cas d'incident juste avant le backup quotidien suivant, la perte théorique maximale côté Postgres correspond aux écritures depuis le dernier dump réussi, hors restauration OVH plus globale.
Qdrant (optionnel mais recommandé)
Qdrant est sauvegardé quotidiennement par snapshots de collections :
- Backup manuel :
bash ops/backup_qdrant.sh - Backup automatisé :
aurora-nexus-qdrant-backup.timer- horaire :
06:30 UTC - garde-fou : attend l'ingestion idle avant snapshot
- sortie :
tmp/backups/qdrant_YYYYmmdd_HHMMSS.tar.zstsizstdest disponible, sinon.tar.gz - sentinel :
tmp/backups/qdrant_latest.json - rétention locale : 2 jours par défaut via
QDRANT_BACKUP_RETENTION_DAYS=2
- horaire :
Le script liste les collections via l'API Qdrant, crée un snapshot par collection, télécharge chaque snapshot localement dans un dossier temporaire, archive ce dossier, vérifie que l'archive est non vide, supprime le dossier brut local, puis supprime le snapshot temporaire côté Qdrant pour éviter l'accumulation dans le volume Qdrant.
Le backup réel compressé du 2026-08-10 a produit une archive tar.zst de 3 303 204 632 octets pour une taille brute de 3 906 194 432 octets, avec 4 collections et 4 snapshots.
Exemple API REST équivalent :
QDRANT_URL="http://127.0.0.1:${HOST_QDRANT_PORT:-16500}"
for c in "${QDRANT_COLLECTION:-aurora_documents}" "${QDRANT_CACHE_COLLECTION:-llm_cache_semantic}"; do
curl -sf -X POST "${QDRANT_URL}/collections/${c}/snapshots" | python -c "import sys,json; print(json.load(sys.stdin)['result']['name'])"
doneEnsuite, télécharger le snapshot renvoyé :
curl -sf "${QDRANT_URL}/collections/<collection>/snapshots/<name>" -o "tmp/backups/qdrant_<collection>_<name>.snapshot"MinIO (optionnel mais recommandé)
MinIO est sauvegardé quotidiennement via export logique mc mirror :
- Backup manuel :
bash ops/backup_minio.sh - Backup automatisé :
aurora-nexus-minio-backup.timer- horaire :
07:00 UTC - garde-fou : attend l'ingestion idle avant miroir
- buckets par défaut :
aurorarag-uploads,aurorarag-artifacts,aurorarag-backups - sortie :
tmp/backups/minio_YYYYmmdd_HHMMSS.tar.zstsizstdest disponible, sinon.tar.gz - sentinel :
tmp/backups/minio_latest.json - rétention locale : 2 jours par défaut via
MINIO_BACKUP_RETENTION_DAYS=2
- horaire :
Le script utilise le service Compose minio-init et l'image minio/mc déjà prévue par le projet. Les credentials MinIO restent injectés par Compose et ne sont pas affichés dans les logs. Le miroir brut est archivé puis supprimé uniquement après vérification d'une archive non vide.
Attention : le premier miroir MinIO peut être long si le bucket contient beaucoup de petits objets. Le backup brut initial du 2026-08-10 occupait environ 7,6 Go sur disque et plus d'un million de fichiers. Le backup réel compressé du 2026-08-10 a produit une archive tar.zst de 2 033 320 174 octets pour une taille brute utile de 5 520 116 098 octets, avec 3 buckets et 1 006 897 fichiers.
2) Restore (rollback)
Postgres
- Vérifier que la stack est démarrée :
docker compose up -d postgres - Restaurer :
bash ops/restore_postgres.sh tmp/backups/postgres_YYYYmmdd_HHMMSS.sql.gzNotes :
- Cette restauration n’efface pas automatiquement le schéma existant ; elle rejoue le dump SQL.
- En cas de conflit, restaurer sur une base vierge est plus simple (runbook “prod” à formaliser si besoin).
Qdrant
Décompresser d'abord l'archive dans un dossier de travail :
mkdir -p tmp/restore/qdrant
tar --zstd -xf tmp/backups/qdrant_YYYYmmdd_HHMMSS.tar.zst -C tmp/restore/qdrant
# fallback gzip :
# tar -xzf tmp/backups/qdrant_YYYYmmdd_HHMMSS.tar.gz -C tmp/restore/qdrantRestaurer ensuite les snapshots extraits via l'API Qdrant en ciblant les collections concernées. La procédure détaillée de restauration collection par collection reste à formaliser avant un exercice DR complet.
MinIO
Décompresser d'abord l'archive dans un dossier de travail :
mkdir -p tmp/restore/minio
tar --zstd -xf tmp/backups/minio_YYYYmmdd_HHMMSS.tar.zst -C tmp/restore/minio
# fallback gzip :
# tar -xzf tmp/backups/minio_YYYYmmdd_HHMMSS.tar.gz -C tmp/restore/minioRestaurer les buckets depuis le miroir extrait avec mc mirror en sens inverse vers MinIO. Vérifier d'abord la destination et les permissions, puis restaurer bucket par bucket.
3) Limites actuelles
- Postgres, Qdrant et MinIO sont automatisés par timers systemd séparés.
/api/ops/healthexposecomponents.postgres_backup,components.qdrant_backupetcomponents.minio_backup.- Kuma surveille chaque famille de backup avec une sonde JSON dédiée.
- Les backups restent locaux. Une destination distante ou hors serveur reste recommandée pour couvrir une perte complète de la machine.