Aller au contenu

Sauvegarder et restaurer la base de la passerelle

La base de la passerelle porte les comptes, les condensats des clés d’accès, les plans de dépense et l’historique de consommation qui sert à facturer. Cette page décrit comment en prendre une copie, et comment la remettre en place.

Les deux moitiés comptent autant. Une sauvegarde qu’on n’a jamais restaurée n’est pas une sauvegarde, c’est un fichier : elle ne devient une procédure que le jour où quelqu’un a remonté une base depuis zéro et vérifié que l’installation repart. La section « Éprouver la sauvegarde » ci-dessous est donc la plus importante de la page.

Fenêtre de terminal
export DATABASE_URL="postgresql://<utilisateur>:<mot-de-passe>@<hôte>:<port>/<base>"
cd gateway-db
./sauvegarder.sh --sortie /var/sauvegardes/passerelle-$(date +%Y%m%d-%H%M%S).sql.gz

Le script affiche ensuite l’inventaire de ce qu’il a emporté — une ligne par table, avec son nombre de lignes. Gardez-le. C’est ce que vous comparerez après une restauration.

sauvegarde écrite : /var/sauvegardes/passerelle-20260801-030000.sql.gz (412K)
Contenu sauvegardé — ce sont ces nombres qu'on doit retrouver après restauration :
table | lignes
-------------------------+--------
plans | 4
request_logs | 18742
schema_migrations | 20
users | 37

--sortie est obligatoire, et le script n’écrase jamais un fichier existant. Il n’engendre pas de nom à votre place : un horodatage automatique donnerait l’apparence d’une politique de rétention là où il n’y en a pas.

Il est créé en 0600, lisible par son seul propriétaire. Traitez-le comme une clé :

  • chiffrez-le avant de le déplacer ;
  • sortez-le de la machine qui porte la base — une sauvegarde sur le disque qui vient de mourir ne sauvegarde rien ;
  • détruisez les copies devenues inutiles. Une sauvegarde antérieure à la migration 015 contient les clés de tous vos porteurs en clair, et c’est alors le seul endroit au monde où elles existent.

Tout le contenu de la base : comptes et condensats de clés, plans, fournisseurs, modèles, endpoints, attributions de rôles, politiques d’autorisation, révocations, sessions, journaux d’audit, et request_logs — l’historique de consommation.

Et le registre schema_migrations, ce qui n’est pas un détail : une base restaurée sans son registre est une base que le script de migration croit vierge, et sur laquelle il rejouerait la chaîne entière depuis la première migration, sur des données vivantes.

Absent de la sauvegarde Pourquoi Ce que ça vous laisse à faire
Les rôles PostgreSQL et leurs mots de passe pg_dump ne copie que le contenu d’une base, jamais les objets globaux du serveur recréer les comptes de connexion sur le serveur cible
Les propriétaires et les droits ils désignent des rôles qui n’existent peut-être pas sur la destination reposer un droit accordé à la main hors du produit
La base elle-même le fichier décrit un contenu, pas une existence — pas de CREATE DATABASE dedans créer la base vide avant de restaurer
Les clés de vos fournisseurs la base stocke le nom de la variable d’environnement, jamais la clé redonner son environnement à la passerelle
ADMIN_API_KEY elle vit dans l’environnement de la passerelle, pas en base la redonner aussi

La dernière ligne mérite d’être dite en clair : une base restaurée ne fait pas une installation qui repart. Il lui faut aussi son environnement.

Si le script refuse : « pg_dump 16 ne peut pas sauvegarder un serveur PostgreSQL 17 »

Section intitulée « Si le script refuse : « pg_dump 16 ne peut pas sauvegarder un serveur PostgreSQL 17 » »

C’est le refus le plus fréquent, et il est correct. pg_dump ne sait pas lire un serveur d’une version majeure postérieure à la sienne ; un serveur en conteneur est souvent plus récent que le client fourni par la distribution.

Installez le client de la version du serveur et placez-le en tête de PATH :

Fenêtre de terminal
export PATH="/usr/lib/postgresql/17/bin:$PATH"
pg_dump --version

Aucun fichier n’a été écrit tant que ce refus s’affiche.

La restauration ne demande que psql — ni pg_restore, ni un client de la version du serveur. Un fichier pris sur un serveur 17 se restaure avec un client 16.

La base de destination doit exister et être vide :

Fenêtre de terminal
createdb -h <hôte> -U <utilisateur> proxy
export DATABASE_URL="postgresql://<utilisateur>:<mot-de-passe>@<hôte>:<port>/proxy"
cd gateway-db
./restaurer.sh /var/sauvegardes/passerelle-20260801-030000.sql.gz

Tout passe dans une transaction unique : une restauration interrompue ne laisse pas une base à moitié remplie, elle ne laisse rien.

Le script affiche à son tour l’inventaire. Comparez-le à celui de la sauvegarde : les nombres doivent être identiques, table par table.

Restaurer par-dessus une base qui contient déjà quelque chose

Section intitulée « Restaurer par-dessus une base qui contient déjà quelque chose »

Sans rien de plus, le script refuse et ne touche à rien :

erreur: la base de destination contient déjà 14 table(s).
Restaurez dans une base vide (createdb), ou relancez avec --ecraser pour remplacer
le contenu actuel. Rien n'a été touché.

--ecraser demande explicitement le remplacement. Il efface le schéma et les données de la destination avant de restaurer, dans la même transaction que la restauration :

Fenêtre de terminal
./restaurer.sh /var/sauvegardes/passerelle-20260801-030000.sql.gz --ecraser

Le geste destructeur n’est jamais celui par défaut. C’est délibéré : la commande la plus courante ne doit pas être celle qui coûte le plus cher quand on se trompe de terminal.

  1. Comparer les deux inventaires, ligne à ligne.

  2. Vérifier que le schéma est au niveau attendu. Ce message-ci est celui qu’on veut voir :

    Fenêtre de terminal
    ./migrate.sh
    base à jour, aucune migration à appliquer.

    S’il annonce des migrations à appliquer, la base restaurée n’est pas au schéma que vous croyez : arrêtez-vous et lisez Appliquer les migrations de la base avant de continuer.

  3. Redonner son environnement à la passerelleADMIN_API_KEY et les clés de vos fournisseurs, qui ne sont pas dans la sauvegarde.

  4. Contrôler de bout en bout : authentifier une clé connue contre la passerelle, et ouvrir la liste des comptes dans la console d’administration.

À faire avant d’en avoir besoin, et à refaire après chaque changement de version du serveur. L’essai se fait sur une base de côté ; la production n’est jamais touchée.

Fenêtre de terminal
# 1. Une sauvegarde de la vraie base.
export DATABASE_URL="postgresql://<utilisateur>:<mot-de-passe>@<hôte>:<port>/proxy"
cd gateway-db
./sauvegarder.sh --sortie /tmp/essai-de-restauration.sql.gz
# 2. Une base vide, à côté, sur le même serveur.
createdb -h <hôte> -U <utilisateur> essai_de_restauration
# 3. La sauvegarde y est restaurée.
DATABASE_URL="postgresql://<utilisateur>:<mot-de-passe>@<hôte>:<port>/essai_de_restauration" \
./restaurer.sh /tmp/essai-de-restauration.sql.gz
# 4. Le schéma est complet : rien à rejouer.
DATABASE_URL="postgresql://<utilisateur>:<mot-de-passe>@<hôte>:<port>/essai_de_restauration" \
./migrate.sh
# 5. On efface la base d'essai et le fichier.
dropdb -h <hôte> -U <utilisateur> essai_de_restauration
shred -u /tmp/essai-de-restauration.sql.gz

Les deux inventaires affichés aux étapes 1 et 3 doivent coïncider, et l’étape 4 doit répondre « base à jour, aucune migration à appliquer. » Tant que cet aller-retour n’a pas été fait une fois sur votre installation, vous avez des fichiers, pas une sauvegarde.

Avant toute migration de schéma, et sans exception avant celle qui remplace les clés en clair par leur condensat (015-hacher-les-cles-api). Cette migration est irréversible : après elle, aucune requête, aucun écran, aucun accès à la base ne retrouve une clé. Une erreur à cet endroit ne se rattrape pas — les clés de tous vos porteurs sont perdues, et se régénèrent une par une.

La procédure complète des migrations, et ce que 015 fait exactement, sont dans Appliquer les migrations de la base.

Les autres moments où la sauvegarde est due : avant une montée de version du serveur PostgreSQL, avant un déplacement de la base d’une machine à une autre, et à intervalle régulier.

  • Ils ne planifient rien. Ni tâche périodique, ni rétention, ni rotation. La cadence, la durée de conservation et l’emplacement hors machine sont des décisions d’exploitation qui vous appartiennent — le produit n’a pas à les prendre à votre place. Ce qu’il vous doit, c’est une commande qui s’appelle depuis le planificateur de votre choix, et c’est ce qu’il vous donne.
  • Ils ne chiffrent ni ne transfèrent le fichier. Vos outils le font mieux, et embarquer une clé de chiffrement dans le produit déplacerait le problème sans le résoudre.
  • Ils ne font pas de sauvegarde continue — pas de restauration à un instant choisi. Cela relève de l’archivage des journaux de transaction de PostgreSQL, qui se configure sur le serveur.