Backup base de données
Version métier : voir Sauvegarde de la base de données.
Pipeline 100 % shell CI — pas de commande Symfony associée. Le job tourne directement sur le runner GitLab.
Description
Section intitulée « Description »Dump complet de la base MySQL applicative toutes les 4 heures, poussé par rsync (clé SSH dédiée) sur $BACKUP_SERVER_URL avec :
- un fichier horodaté
~/internal/${MYSQL_NAME}_YYYYMMDD_HHMMSS.sql(historique) ; - un fichier
~/internal/${MYSQL_NAME}_latest.sql(restauration rapide).
La rétention est gérée par le schedule complémentaire Purge des backups.
Déclenchement
Section intitulée « Déclenchement »Planification GitLab (via pipeline_schedules API, 2026-04-23) :
- Description :
Backup database - ID du schedule :
4081502 - Cron :
0 */4 * * *(fuseau :Europe/Paris) — 00:00, 04:00, 08:00, 12:00, 16:00, 20:00 Paris. - Branche :
refs/heads/master - État : actif
- Variable injectée :
SCHEDULE_TYPE=backup
Job CI : backup_job dans ci-jobs/.scheduled-ci.yml (stage backup).
Pas de commande Symfony : tout se passe en shell sur le runner, qui ouvre deux connexions SSH (une vers $DATABASE_SERVER_URL pour le dump, une vers $BACKUP_SERVER_URL pour le dépôt rsync).
Fonctionnement
Section intitulée « Fonctionnement »before_script: installeopenssh-client rsync, démarressh-agent, charge$DEPLOYER_SSH_PRIVATE_KEY.- Dump : SSH sur
$USER@$DATABASE_SERVER_URLqui exécute :La sortie stdout est redirigée versFenêtre de terminal docker run --rm --network mysql --env MYSQL_PWD=${MYSQL_PWD} mysql:latest \mysqldump -h mysql -u $MYSQL_USER $MYSQL_NAMEbackup.sqllocal au runner. - Clé de backup : écrit
$BACKUP_PRIVATE_KEYdansbackup_key(chmod 600). - Upload horodaté :
Fenêtre de terminal rsync -avz -e "ssh -i backup_key -o StrictHostKeyChecking=no -p ${SSH_PORT}" \backup.sql \$BACKUP_USER@$BACKUP_SERVER_URL:~/internal/${MYSQL_NAME}_$(date +%Y%m%d_%H%M%S).sql - Upload « latest » : même
rsyncvers~/internal/${MYSQL_NAME}_latest.sql(écrase l’alias). after_script:rm -f backup_key backup.sql(nettoyage sur le runner).
Entités impactées
Section intitulée « Entités impactées »Aucune entité applicative. Le job dump la base entière (schéma + données).
Gestion des erreurs
Section intitulée « Gestion des erreurs »- Pas de retry. Un échec de connexion SSH, un
mysqldumpen erreur ou unrsyncrefusé fait échouer le pipeline GitLab. - Pas de vérification d’intégrité du SQL : pas de
--single-transaction, pas de--quick. Le dump est lancé sur une base en production, donc potentiellement non cohérent transactionnellement.
TODO(review) : considérer l’ajout de
--single-transaction --quick --routines --triggersaumysqldumppour garantir la cohérence InnoDB.
Dépendances externes
Section intitulée « Dépendances externes »- Serveur DB (
$DATABASE_SERVER_URL) — doit exposer le réseau Dockermysqlet avoirdockerdisponible pour lancermysql:latest. - Serveur de backup (
$BACKUP_SERVER_URL, utilisateur$BACKUP_USER) — destination des.sql. - Runner GitLab — stockage temporaire de
backup.sqlle temps du rsync.
Observabilité
Section intitulée « Observabilité »- Logs :
GitLab > Build > Pipelines > backup_job. Dernier run consultable via https://gitlab.com/w-ap.fr/erevo/internal-api/-/pipeline_schedules. - Pas couvert par Sentry (job shell, pas de code PHP). Un échec n’est visible que dans GitLab.
TODO(review) : envisager un alerting dédié (webhook GitLab vers Sentry Cron Monitoring, Slack, Discord) — un backup raté est un incident critique, le canal GitLab seul est fragile.
Références code
Section intitulée « Références code »- Job CI :
ci-jobs/.scheduled-ci.yml(jobbackup_job) - Commande Symfony associée : aucune
Variables CI consommées
Section intitulée « Variables CI consommées »$DEPLOYER_SSH_PRIVATE_KEY,$SSH_PORT,$USER,$APP_NAME$DATABASE_SERVER_URL,$MYSQL_USER,$MYSQL_PWD,$MYSQL_NAME$BACKUP_PRIVATE_KEY,$BACKUP_USER,$BACKUP_SERVER_URL