Sauvegarder et restaurer une instance gitrust

À qui s'adresse cette page

Administrateurs qui souhaitent mettre en place une sauvegarde fiable et tester la restauration. Pour comprendre la stratégie 3-2-1 adaptée à gitrust, consultez Stratégie de sauvegarde.


Ce qu'il faut sauvegarder

Gitrust repose sur trois sources de vérité distinctes :

Source Chemin / objet Critique Fréquence recommandée
Base de données PostgreSQL database gitrust Oui Quotidien minimum
Dépôts Git bare GIT_REPOS_BASE_PATH (ex. /opt/gitrust/data/repos) Oui Quotidien minimum
Clé SSH hôte SSH_HOST_KEY_PATH (ex. /opt/gitrust/data/ssh_host_ed25519_key) Oui Une seule fois, puis conserver
Fichier .env /opt/gitrust/.env Oui À chaque modification

La clé SSH hôte est immuable après le premier démarrage. Si vous la perdez, tous vos utilisateurs devront supprimer leur entrée known_hosts et re-vérifier le fingerprint.


Sauvegarder

Sauvegarde PostgreSQL (pg_dump)

BACKUP_DIR="/var/backups/gitrust"
DATE=$(date +%Y%m%d-%H%M%S)
mkdir -p "$BACKUP_DIR"

pg_dump \
  -h localhost \
  -U gitrust \
  --format=custom \
  --file="${BACKUP_DIR}/pg-${DATE}.dump" \
  gitrust

echo "Dump : ${BACKUP_DIR}/pg-${DATE}.dump"
# Purger les sauvegardes de plus de 30 jours
find "$BACKUP_DIR" -name "pg-*.dump" -mtime +30 -delete

Le format --format=custom est compressé et restaurable avec pg_restore. Le fichier contient la structure ET les données.

Sauvegarde des dépôts bare (rsync)

REPOS_SRC="/opt/gitrust/data/repos"
REPOS_DST="/var/backups/gitrust/repos"

rsync \
  --archive \
  --delete \
  --hard-links \
  --checksum \
  "${REPOS_SRC}/" "${REPOS_DST}/"

Les dépôts bare Git sont consistants en lecture même pendant un git push actif : Git garantit l'atomicité au niveau du pack.

Sauvegarde de la clé SSH hôte et du .env

BACKUP_DIR="/var/backups/gitrust"
DATE=$(date +%Y%m%d-%H%M%S)

tar czf "${BACKUP_DIR}/config-${DATE}.tar.gz" \
  /opt/gitrust/data/ssh_host_ed25519_key \
  /opt/gitrust/data/ssh_host_ed25519_key.pub \
  /opt/gitrust/.env

chmod 600 "${BACKUP_DIR}/config-${DATE}.tar.gz"

Script complet backup.sh

#!/usr/bin/env bash
# /opt/gitrust/scripts/backup.sh
set -euo pipefail

BACKUP_DIR="${BACKUP_DIR:-/var/backups/gitrust}"
DATE=$(date +%Y%m%d-%H%M%S)
PG_USER="gitrust"
PG_DB="gitrust"
REPOS_SRC="/opt/gitrust/data/repos"
SSH_KEY="/opt/gitrust/data/ssh_host_ed25519_key"
ENV_FILE="/opt/gitrust/.env"

mkdir -p "$BACKUP_DIR"

echo "[1/3] Dump PostgreSQL..."
pg_dump -U "$PG_USER" --format=custom \
  --file="${BACKUP_DIR}/pg-${DATE}.dump" "$PG_DB"

echo "[2/3] Rsync dépôts bare..."
mkdir -p "${BACKUP_DIR}/repos"
rsync --archive --delete --checksum \
  "${REPOS_SRC}/" "${BACKUP_DIR}/repos/"

echo "[3/3] Archive config sensible..."
tar czf "${BACKUP_DIR}/config-${DATE}.tar.gz" \
  "$SSH_KEY" "${SSH_KEY}.pub" "$ENV_FILE"
chmod 600 "${BACKUP_DIR}/config-${DATE}.tar.gz"

echo "Sauvegarde terminée dans $BACKUP_DIR"
find "$BACKUP_DIR" -name "pg-*.dump" -mtime +30 -delete
find "$BACKUP_DIR" -name "config-*.tar.gz" -mtime +90 -delete

Planifier via cron :

# Sauvegarder chaque nuit à 2h00
0 2 * * * /opt/gitrust/scripts/backup.sh >> /var/log/gitrust-backup.log 2>&1

Restaurer

Avant toute restauration

# 1. Arrêter gitrust
sudo systemctl stop gitrust   # ou : docker compose stop gitrust

# 2. Vérifier les fichiers de sauvegarde disponibles
ls -lh /var/backups/gitrust/pg-*.dump | tail -5
ls -lh /var/backups/gitrust/config-*.tar.gz | tail -3
du -sh /var/backups/gitrust/repos/

Restaurer la base PostgreSQL

DUMP="/var/backups/gitrust/pg-20260417-020000.dump"

sudo -u postgres psql -c "DROP DATABASE IF EXISTS gitrust;"
sudo -u postgres psql -c "CREATE DATABASE gitrust OWNER gitrust;"

pg_restore \
  -h localhost \
  -U gitrust \
  --dbname=gitrust \
  --verbose \
  "$DUMP"

Vérification :

psql "postgres://gitrust:MOT_DE_PASSE@localhost:5432/gitrust" \
  -c "SELECT COUNT(*) FROM users; SELECT COUNT(*) FROM repositories;"

Restaurer les dépôts bare

REPOS_SRC="/var/backups/gitrust/repos"
REPOS_DST="/opt/gitrust/data/repos"

rsync --archive --delete "${REPOS_SRC}/" "${REPOS_DST}/"
sudo chown -R gitrust:gitrust "${REPOS_DST}"

Restaurer la clé SSH hôte et le .env

ARCHIVE="/var/backups/gitrust/config-20260417-020000.tar.gz"

sudo tar xzf "$ARCHIVE" -C /
sudo chown gitrust:gitrust /opt/gitrust/data/ssh_host_ed25519_key*
sudo chmod 600 /opt/gitrust/data/ssh_host_ed25519_key
sudo chmod 644 /opt/gitrust/data/ssh_host_ed25519_key.pub
sudo chmod 600 /opt/gitrust/.env

Redémarrer et vérifier

sudo systemctl start gitrust
sleep 3
curl -s -o /dev/null -w "%{http_code}" http://localhost:4000/
# Attendu : 302

Tester la restauration (drill trimestriel)

Une sauvegarde non testée n'est pas une sauvegarde. Testez sur une VM distincte :

# Sur une VM de test vierge — restaurer, puis vérifier :
git clone ssh://git@VM_TEST:2222/admin/un-depot-connu.git /tmp/drill-test
ls /tmp/drill-test/
# Les fichiers doivent correspondre à l'état au moment de la sauvegarde

Pour aller plus loin