Aller au contenu principal

Backup

Statut

Document opérationnel — v1.1 — 2026-06-20.

Objectif

Permettre une restauration complète de DMV après un sinistre (perte de données, corruption, suppression accidentelle, panne Supabase).

La stratégie repose sur des sauvegardes PostgreSQL quotidiennes automatisées, conservées 7 jours, avec checksums d'intégrité.

Ce qui est sauvegardé

ÉlémentMéthodeCouvert
Base PostgreSQL (schéma + données)pg_dump format custom
Politiques RLSIncluses dans le dump + policies.csv diagnostic
Triggers, fonctions, extensionsIncluses dans le dump
Schéma lisibleschema.sql.gz
Données lisibles (INSERT)data.sql.gz
Edge FunctionsCode source dans git✅ (via git)

Ce qui n'est pas sauvegardé

ÉlémentImpactAction
Storage Supabase (buckets acteurs, publications, documents)Perte des logos, bannières, PDFsSync manuel via supabase storage download ou AWS S3 CLI
État déployé des Edge FunctionsDivergence possible avec gitsupabase functions download si état prod ≠ git
Configuration projet Supabase (Auth, SMTP, providers)Reconfiguration manuelleSnapshot via dashboard Supabase
Rôles globaux PostgreSQLGérés par Supabase, non exportables par pg_dumpN/A

Scripts

Deux scripts distincts selon l'environnement.

Version macOS (backup_supabase.sh)

Utilisé pour déclencher un backup manuel depuis la machine de développement. Le script versionné est désormais api/ops/backup_supabase_mac.sh. Le fichier racine backup_supabase.sh reste un wrapper local stable, utilisé aussi par le cron macOS.

Mode recommandé : fournir des variables PostgreSQL explicites dans dmv-public/.env.local ou dans l'environnement shell :

SUPABASE_DB_HOST=<host PostgreSQL Supabase ou pooler>
SUPABASE_DB_PORT=5432
SUPABASE_DB_NAME=postgres
SUPABASE_DB_USER=<postgres.<project_ref> ou utilisateur dédié>
SUPABASE_DB_PASSWORD=<Settings → Database → mot de passe>

Ordre de résolution des credentials du script macOS :

  1. variables explicites SUPABASE_DB_*
  2. configuration supabase db dump --linked --dry-run du projet dmv-backoffice
  3. dérivation du host depuis NEXT_PUBLIC_SUPABASE_URL

Usage :

./backup_supabase.sh
./backup_supabase.sh -m "avant migration users"
OUT_DIR=~/Backups/supabase ./backup_supabase.sh

Le host PostgreSQL n'est dérivé depuis NEXT_PUBLIC_SUPABASE_URL qu'en dernier recours.

Cron macOS

La machine locale peut exécuter un backup quotidien via crontab.

Commande actuellement utilisée :

0 9 * * * /Users/sylvain/dev/dmv/backup_supabase.sh --no-interactive >> /Users/sylvain/dev/dmv/backups/cron.log 2>&1

Le script macOS exporte explicitement un PATH compatible cron/launchd (Homebrew, /usr/bin, /bin, etc.) pour garantir la disponibilité de pg_dump, pg_restore et psql hors shell interactif.

Version VPS (backup_supabase_vps.sh)

Utilisé pour les sauvegardes automatiques sur le VPS Debian. Lit les credentials depuis /srv/dmv/api/.env (variables DB_* de Laravel).

Contenu d'un backup

Chaque exécution crée un dossier horodaté dans le répertoire de sortie :

backups/
└── 2026-05-17_02-00-00/
├── full.backup # dump complet format custom (pour pg_restore)
├── full.backup.sha256
├── schema.sql.gz # schéma lisible compressé
├── schema.sql.gz.sha256
├── data.sql.gz # données lisibles compressées
├── data.sql.gz.sha256
├── schemas.list # liste des schémas
├── policies.csv # politiques RLS
├── triggers.csv # triggers
├── functions.csv # fonctions et signatures
├── meta.txt # métadonnées de session
└── backup.log # log complet de l'exécution

Cron VPS

Le backup tourne automatiquement chaque nuit à 2h00 sur le VPS, lancé sous l'utilisateur deploy.

Fichier : /etc/cron.d/dmv-backup

0 2 * * * deploy /var/www/backup_supabase.sh --no-interactive >> /var/log/dmv/backup-cron.log 2>&1

Le log cron /var/log/dmv/backup-cron.log est géré par logrotate (rotation quotidienne, 7 fichiers, compressés).

Rétention

7 jours de backups datés conservés sur le VPS dans /srv/dmv/backups/. Les dossiers plus anciens sont supprimés automatiquement à chaque exécution.

En local macOS, la rotation est identique par défaut : 7 jours de backups datés dans /Users/sylvain/dev/dmv/backups/.

Déploiement initial sur le VPS

Commandes à exécuter une seule fois. postgresql-client (pg_dump, pg_restore, psql) est inclus dans deployment/install.sh depuis la v1.1 — si le VPS a été installé avant, l'ajouter manuellement.

# ── 1. postgresql-client (si VPS installé avant la v1.1) ─────────────────────
sudo apt-get install -y postgresql-client

# ── 2. Répertoires ────────────────────────────────────────────────────────────
sudo mkdir -p /var/www/backups /var/log/dmv
sudo chown deploy:deploy /var/www/backups /var/log/dmv

# ── 3. Script de backup ───────────────────────────────────────────────────────
# Depuis la machine locale :
scp backup_supabase_vps.sh deploy@<vps>:/var/www/backup_supabase.sh

# Sur le VPS :
sudo chmod +x /var/www/backup_supabase.sh
sudo chown deploy:deploy /var/www/backup_supabase.sh

# ── 4. Cron ───────────────────────────────────────────────────────────────────
sudo cp ops/cron.d/dmv-backup /etc/cron.d/dmv-backup
sudo chmod 644 /etc/cron.d/dmv-backup

# ── 5. Logrotate ──────────────────────────────────────────────────────────────
sudo cp ops/logrotate.d/dmv-backup /etc/logrotate.d/dmv-backup

# ── 6. Test immédiat ──────────────────────────────────────────────────────────
sudo -u deploy /var/www/backup_supabase.sh -m "test installation"
# Vérifier : ls -lh /var/www/backups/

Restauration

La restauration s'effectue depuis full.backup avec pg_restore.

Vérification de l'intégrité avant restore :

sha256sum -c full.backup.sha256

Restauration vers une base cible :

export PGPASSWORD="<mot de passe>"

pg_restore \
--dbname="postgresql://postgres@db.<ref>.supabase.co:5432/postgres?sslmode=require" \
--clean --if-exists \
--no-owner --no-privileges \
full.backup

Options :

  • --clean --if-exists : supprime les objets existants avant de les recréer (utile si la base n'est pas vide).
  • --no-owner --no-privileges : ne recrée pas les rôles propriétaires ni les ACL (Supabase les gère de son côté).

Vérification manuelle

Pour tester qu'un backup est lisible sans le restaurer :

pg_restore --list full.backup | head -50

Points ouverts

  • Backup Storage Supabase (buckets acteurs, publications, documents) : non couvert, à traiter via la CLI Supabase ou l'API S3 compatible.
  • Alerte en cas d'échec du cron : actuellement silencieux hors log. À connecter à une alerte Slack ou email.
  • Backup off-site : les backups sont sur le même VPS que l'application. Une copie vers un stockage externe (S3, Backblaze) est recommandée pour un DR complet.