Le pire moment pour découvrir que vos sauvegardes sont « sécurisées » est lors d’une restauration. Le deuxième pire moment est
pendant un audit où quelqu’un demande, calmement, pourquoi les dumps de la base de production sont stockés dans un objet
de stockage en texte clair avec un horodatage dans le nom de fichier.
Docker facilite le déploiement des applications. Il facilite aussi la sauvegarde de la mauvaise chose, le chiffrement au
mauvais endroit, puis la découverte que votre processus de restauration dépend d’un secret qui vivait sur la machine
que vous venez de perdre. Ceci est un guide pour les équipes qui exploitent des systèmes en production et veulent un chiffrement
qui survive aux vrais désastres—y compris les erreurs opérationnelles.
Modèle de menace d’abord, outils ensuite
« Chiffrer les sauvegardes » n’est pas une exigence ; c’est un souhait vague. Les exigences sont spécifiques :
qui ne doit pas lire les sauvegardes, quelles défaillances vous pouvez tolérer, et comment vous restaurerez lorsque la moitié de votre infrastructure est en feu et que l’autre moitié attend un contrôle des changements.
Commencez par trois modèles de menace courants :
-
Compromission du stockage cloud : fuite de credentials, politique de bucket incorrecte, ou compte interne devenu malveillant.
Le chiffrement doit encore empêcher l’exfiltration de données lisibles. -
Ransomware / attaquant sur l’hôte : l’attaquant peut lire les fichiers locaux et peut-être vos scripts de sauvegarde.
Le chiffrement peut aider ou non selon l’endroit où résident les clés. -
Erreur opérateur : la plus courante. Quelqu’un téléverse un dump « temporaire » dans un endroit partagé, ou fait une rotation de clés sans plan de restauration.
Le chiffrement doit réduire le rayon d’impact et les restaurations doivent rester routinières.
Pour les environnements Docker, la vérité opérationnelle est la suivante : vous ne « sauvegardez pas Docker ». Vous
sauvegardez les données derrière les conteneurs, plus suffisamment de métadonnées pour les reconstruire. Le chiffrement doit
envelopper l’artéfact que vous stockez et déplacez effectivement—pas seulement le disque, pas seulement le transport, et
définitivement pas « quelque part dans la pile que nous supposons chiffrée ».
Faits intéressants et contexte historique
- Fait 1 : La culture de sauvegarde Unix ancienne considérait les bandes comme « sécurité physique ». Le chiffrement était rare parce que la bande restait dans une armoire verrouillée—jusqu’à ce que ce ne soit plus le cas.
- Fait 2 : GPG (années 1990) est devenu l’outil par défaut pour « chiffrer un fichier » pour les ops parce qu’il fonctionnait hors ligne et multi-plateforme, pas parce qu’il était simple.
- Fait 3 : Beaucoup d’échecs de « chiffrement des sauvegardes » sont en réalité des échecs de disponibilité des clés : le texte chiffré est correct ; la restauration ne peut pas déchiffrer à temps.
- Fait 4 : Compresser avant de chiffrer est une bonne pratique de longue date parce que le chiffrement détruit les redondances et rend la compression inefficace.
- Fait 5 : L’essor du stockage objet a rendu les « sauvegardes hors site » bon marché et courantes—ce qui a aussi rendu les expositions publiques accidentelles un titre récurrent de l’industrie.
- Fait 6 : La déduplication et le chiffrement sont en guerre froide depuis des années : le chiffrement randomise les données et peut tuer l’efficacité de la déduplication à moins d’être conçu correctement.
- Fait 7 : Un nombre surprenant d’équipes sauvegardent encore les « conteneurs » (images) au lieu de sauvegarder l’état, puis se demandent pourquoi la base de données est vide après restauration.
- Fait 8 : La rotation des clés est plus vieille que le cloud. La difficulté a toujours été la compatibilité avec les anciennes données et les rituels opérationnels prévisibles.
Une idée paraphrasée fiable de Richard Cook (ingénierie de la résilience) : le succès et l’échec proviennent souvent du même travail quotidien ; la différence est le contexte
(idée paraphrasée).
Le chiffrement des sauvegardes est exactement cela. Le même pipeline qui vous protège peut aussi vous laisser sans issue—selon que votre chemin de restauration a été traité comme une fonctionnalité de première classe.
Principes : chiffrer sans casser les restaurations
1) Chiffrez l’artéfact que vous stockez, pas la machine que vous rêvez d’avoir
Le chiffrement de disque (LUKS, chiffrement EBS cloud, datasets ZFS chiffrés) est une bonne hygiène. Mais
les sauvegardes sont conçues pour être portables. Vous les copierez sur d’autres machines, d’autres buckets, d’autres
régions, peut‑être sur un laptop pendant un incident. Le chiffrement doit donc voyager avec l’artéfact de sauvegarde.
2) Le chemin de restauration est le produit
Si le déchiffrement nécessite un VPN vers un datacenter mort, vous avez construit un piège. Les restaurations doivent fonctionner depuis un démarrage à froid : nouvel hôte, outils minimaux, clés obtenables via un processus contrôlé mais disponible.
3) Préférez des workflows crypto simples aux idées trop ingénieuses
Les hiérarchies de clés complexes et les schémas sur mesure peuvent être corrects et quand même impossibles à restaurer à 03:00.
La plupart des équipes s’en tirent mieux avec :
- Un fichier par artéfact de sauvegarde
- Compression puis chiffrement (en streaming si volumineux)
- Chiffrement basé sur les destinataires (pas de passphrases partagées)
- Récupération de clés documentée et testée
4) Séparez confidentialité et intégrité, mais vérifiez les deux
Les modes de chiffrement modernes (et des outils comme age) fournissent un chiffrement authentifié : confidentialité plus intégrité.
Néanmoins, vous devez vérifier le checksum de l’artéfact et tester le déchiffrement et la restauration. La corruption silencieuse n’est pas souhaitable.
5) Prévoyez la perte de clés, pas seulement le vol
La plupart des organisations s’obsèdent à empêcher le vol et ignorent la perte. La perte est ce qui vous mène à des sauvegardes « parfaitement sécurisées »
que vous ne pouvez pas restaurer. Votre gestion des clés devrait inclure :
- Au moins deux chemins de récupération indépendants (par ex., deux opérateurs, ou vault + break-glass)
- Rotation documentée
- Journaux d’accès
- Drills de restauration réguliers
Que sauvegarder dans Docker (et quoi éviter)
Les conteneurs sont des cattle ; les volumes et systèmes externes sont les pets que vous devez réellement protéger. En termes Docker,
votre périmètre de sauvegarde est généralement :
- Volumes nommés (par ex., répertoire de données Postgres, uploads de l’application)
- Bind mounts où l’état vit (prudence avec les permissions et la dérive de chemins)
- Dumps logiques de base de données (pg_dump, mysqldump) ou sauvegardes physiques (pg_basebackup, xtrabackup)
- État de configuration : docker-compose.yml, fichiers env (mais traitez les secrets avec précaution), configurations de reverse proxy
- Secrets : pas dans git, pas dans la sauvegarde sauf si vous avez une raison et une stratégie de protection séparée
Choses que l’on sauvegarde souvent par erreur :
- Couches/images de conteneurs (vous pouvez reconstruire ; aussi les images peuvent contenir des secrets si vous êtes négligent)
- /var/lib/docker en bloc (possible, mais fragile entre versions/stockage ; et c’est énorme)
- Caches runtime (gaspillant et pouvant ralentir les restaurations)
Opinion : sauvegardez les données et une définition de déploiement reconstruisible. Si votre restauration dépend de copier
un répertoire d’état du démon Docker entre hôtes, vous êtes déjà en négociation avec le chaos.
Où chiffrer : au repos, en transit, ou dans le pipeline
Chiffrement de transport (TLS)
Nécessaire, mais pas suffisant. TLS protège les données en transit, mais l’extrémité reçoit toujours le texte clair. Si
le bucket est compromis plus tard, TLS n’a rien fait.
Chiffrement côté stockage (SSE)
Le SSE de type S3 (SSE-S3 ou SSE-KMS) est utile, surtout pour la conformité et pour réduire l’impact d’un bucket mal configuré.
Mais cela signifie toujours que le fournisseur de stockage peut déchiffrer, et l’objet est stocké dans une forme qui pourrait être décryptée
avec l’accès aux contrôles appropriés. Ce n’est pas de bout en bout.
Chiffrement côté client (chiffrer avant l’upload)
C’est la recommandation par défaut pour « garder les secrets sûrs ». Vous chiffrez l’artéfact de sauvegarde localement, puis vous téléversez le ciphertext.
Même si votre stockage est compromis, l’attaquant obtient des blobs chiffrés.
Réalité : le chiffrement côté client n’est aussi bon que l’hygiène des clés. Si l’hôte qui chiffre stocke aussi la clé sans protection,
vous avez surtout amélioré le papier de conformité.
Choix cryptographiques : age, GPG, OpenSSL, SSE S3
age : ennuyeux dans le bon sens
age est un outil moderne de chiffrement de fichiers conçu pour être difficile à mal utiliser. Le chiffrement basé sur les destinataires
est simple, la sortie est déterministe pour l’exploitation, et il est moins « mystique » que GPG.
Utilisez-le quand vous voulez un workflow clair et que vous n’avez pas besoin de l’écosystème PGP complet.
Cas d’usage : tarballs chiffrés quotidiens, dumps de bases en streaming, copies hors site.
GPG : puissant, avec des angles vifs
gpg est omniprésent et supporte une gestion de clés complexe. Il a aussi une dette de complexité : modèles de confiance,
porte-clés, pinentry, comportement d’agent, et confusion humaine.
Cas d’usage : lorsque votre organisation dispose déjà d’une distribution de clés PGP et que vous avez besoin d’interopérabilité.
OpenSSL : flexible, mais facile à se tirer une balle dans le pied
OpenSSL peut chiffrer des fichiers avec une passphrase, mais les workflows basés sur des passphrases sont régulièrement mal utilisés :
secrets partagés, passphrases faibles, passphrases embarquées dans des scripts, etc. Si vous utilisez OpenSSL, employez
des modes AEAD modernes et gardez les passphrases hors des listes de processus et de l’historique shell.
Chiffrement côté serveur : bonne base, pas la ligne d’arrivée
SSE aide, particulièrement SSE-KMS avec de fortes frontières IAM et des journaux d’audit. Mais pour les scénarios « compte cloud compromis »,
le chiffrement côté client reste l’histoire la plus forte.
Blague 1 : Si votre clé de chiffrement de sauvegarde est dans le même bucket que les sauvegardes, vous n’avez pas construit de sécurité—vous avez construit une escape room thématique.
Gestion des clés sans sacrifier votre week-end
Choisissez un modèle de clés que vous pouvez opérer sous stress
L’objectif n’est pas « que personne ne puisse jamais déchiffrer ». L’objectif est « seules les personnes autorisées peuvent déchiffrer, et
elles peuvent le faire pendant un incident sans improviser ».
Modèles recommandés
-
Chiffrement basé sur les destinataires (préféré) : recipients age ou clés publiques GPG. Chiffrez pour plusieurs destinataires
(par ex., clé de l’équipe ops + clé break-glass). Pas de passphrase partagée. Pas de goulet d’étranglement humain unique. -
Clé break-glass stockée hors ligne : QR imprimé dans un coffre, ou processus d’export protégé par HSM, selon votre contexte.
L’idée est d’être indépendant de l’hôte de production. - Vault/KMS pour distribution des clés, pas forcément pour le chiffrement : stockez la clé privée ou une clé de données enveloppée dans un système avec un contrôle d’accès fort et des journaux d’audit.
À éviter
- Passphrase unique partagée dans un canal de chat (elle se retrouve ensuite dans les sauvegardes de chat aussi)
- Clés stockées sur le même hôte sans protection supplémentaire
- Rotation de clés sans plan de ré-chiffrement (vous le découvrirez lors de la restauration)
- « On demandera toujours à Alice » dépendance (Alice part en vacances, ou quitte l’entreprise)
Rotation des clés : faites-le sans casser les anciennes restaurations
La rotation exige une fenêtre de compatibilité. Conservez les anciennes clés privées disponibles (sous contrôles) jusqu’à ce que toutes
les sauvegardes chiffrées avec elles aient expiré. Si vous devez révoquer l’accès, ré-chiffrez les archives conservées, et enregistrez quel ID de clé a chiffré quel objet.
Pipelines pratiques de sauvegarde chiffrée (avec chemins de restauration)
Pipeline A : snapshot de volume via tar → compression → age → upload
C’est le cheval de trait pour les cas « volume nommé contenant des fichiers ». Ce n’est pas cohérent pour une base de données à moins que
votre application puisse le tolérer. Pour les bases, préférez les sauvegardes logiques/physiques fournies par la BD elle-même.
Pipeline B : dump logique Postgres streamé et chiffré
Pour beaucoup d’organisations, pg_dump est le compromis idéal : snapshot cohérent, portable, et vous pouvez le streamer pour que le texte clair
n’atterrisse pas sur le disque. Ensuite chiffrez et expédiez.
Pipeline C : stockage objet avec SSE-KMS plus chiffrement côté client
La sécurité en couches est normale. SSE-KMS vous offre des contrôles côté fournisseur et des journaux d’audit ; le chiffrement côté client
vous donne la propriété « la compromission du bucket renvoie encore du ciphertext ».
Réflexion sur le chemin de restauration
Pour chaque pipeline, documentez :
- Où l’artéfact chiffré se trouve
- Comment le récupérer (credentials et qui les possède)
- Comment obtenir la clé de déchiffrement (primaire et break-glass)
- Comment vérifier l’intégrité (checksum/signature)
- Comment restaurer dans un environnement Docker propre
12+ tâches réelles : commandes, sorties et décisions
Voici le type de vérifications que vous effectuez quand vous construisez le système ou déboguez pourquoi une restauration est lente, échoue, ou est suspectement « réussie » mais incomplète.
Chaque tâche inclut : la commande, ce que signifie la sortie, et la décision que vous prenez à partir de celle-ci.
Task 1: Enumerate containers and identify stateful ones
cr0x@server:~$ docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
NAMES IMAGE STATUS
pg postgres:16 Up 3 days
app myco/app:2.8.1 Up 3 days
nginx nginx:1.25 Up 3 days
Meaning: You’re looking for databases, file stores, queues—anything with state.
Decision: Mark pg and likely app as requiring backups beyond redeploying images.
Task 2: List volumes and map them to containers
cr0x@server:~$ docker volume ls
DRIVER VOLUME NAME
local pg_data
local app_uploads
cr0x@server:~$ docker inspect pg --format '{{json .Mounts}}'
[{"Type":"volume","Name":"pg_data","Source":"/var/lib/docker/volumes/pg_data/_data","Destination":"/var/lib/postgresql/data","Driver":"local","Mode":"z","RW":true,"Propagation":""}]
Meaning: pg_data is a named volume; backing up that directory raw risks inconsistency unless the DB is stopped or you use DB-native backups.
Decision: Use pg_dump or pg_basebackup rather than tarring pg_data while running.
Task 3: Verify Docker Compose definition exists and is versioned
cr0x@server:~$ ls -l /srv/app/docker-compose.yml
-rw-r--r-- 1 root root 2481 Jan 2 09:41 /srv/app/docker-compose.yml
Meaning: You can recreate the stack. Without this, restores turn into archaeology.
Decision: Put compose files in version control; keep secrets out of it or use external secret stores.
Task 4: Confirm where secrets come from (env vars vs files)
cr0x@server:~$ docker inspect app --format '{{range .Config.Env}}{{println .}}{{end}}' | grep -E 'PASSWORD|TOKEN|SECRET' || true
DATABASE_URL=postgres://app:REDACTED@pg:5432/app
JWT_SECRET=REDACTED
Meaning: If secrets live in env vars, they can leak via diagnostics, crash dumps, and overly-helpful scripts.
Decision: Decide whether your backups should include secret material. Usually: no. Back up data; recover secrets from a separate controlled path.
Task 5: Create an age key pair (operator workstation or secure host)
cr0x@server:~$ age-keygen -o /secure/keys/backup.agekey
Public key: age1k8t6y7z8n6k5m2p9k4d3s2q1w0e9r8t7y6u5i4o3p2a1s0d9f8g7h6j
Meaning: You now have a recipient public key (safe to distribute) and a private key (treat as break-glass-worthy).
Decision: Store the private key outside the Docker host and outside the backup location. Encrypt to multiple recipients if possible.
Task 6: Encrypt a small test file and verify decryption works
cr0x@server:~$ printf "hello-restore\n" > /tmp/restore-test.txt
cr0x@server:~$ age -r age1k8t6y7z8n6k5m2p9k4d3s2q1w0e9r8t7y6u5i4o3p2a1s0d9f8g7h6j -o /tmp/restore-test.txt.age /tmp/restore-test.txt
cr0x@server:~$ age -d -i /secure/keys/backup.agekey -o /tmp/restore-test.out /tmp/restore-test.txt.age
cr0x@server:~$ cat /tmp/restore-test.out
hello-restore
Meaning: The key is valid, tooling works, and decryption is not “future you’s problem.”
Decision: Bake age install into your restore environment or keep a known-good static binary accessible.
Task 7: Stream a Postgres dump and encrypt it (no plaintext file on disk)
cr0x@server:~$ docker exec -i pg pg_dump -U postgres -d app --format=custom | age -r age1k8t6y7z8n6k5m2p9k4d3s2q1w0e9r8t7y6u5i4o3p2a1s0d9f8g7h6j -o /backups/app_pg.dump.age
cr0x@server:~$ ls -lh /backups/app_pg.dump.age
-rw-r--r-- 1 root root 192M Jan 3 01:00 /backups/app_pg.dump.age
Meaning: You produced an encrypted artifact. The dump traveled through a pipe; the host didn’t store plaintext at rest.
Decision: Adopt streaming for large sensitive backups; reduce the “plaintext residue” problem.
Task 8: Validate you can decrypt and restore that dump into a fresh database
cr0x@server:~$ docker run --rm -d --name pg-restore -e POSTGRES_PASSWORD=restore -p 5433:5432 postgres:16
d4b2f8f15c65f6b6f8b0b76d1cc9d9d2a2b0a6f0d3f0d8f9a1c2b3d4e5f6a7b8
cr0x@server:~$ age -d -i /secure/keys/backup.agekey /backups/app_pg.dump.age | pg_restore -h 127.0.0.1 -p 5433 -U postgres -d postgres --clean --if-exists
Password:
Meaning: This proves the end-to-end restore path, not just encryption.
Decision: Make this a scheduled drill. If you can’t restore into a clean instance, you don’t have backups—you have artifacts.
Task 9: Back up a non-DB volume with tar + compression + encryption
cr0x@server:~$ docker run --rm -v app_uploads:/data:ro -v /backups:/out alpine:3.20 sh -c "cd /data && tar -cf - . | gzip -1" | age -r age1k8t6y7z8n6k5m2p9k4d3s2q1w0e9r8t7y6u5i4o3p2a1s0d9f8g7h6j -o /backups/app_uploads.tgz.age
cr0x@server:~$ file /backups/app_uploads.tgz.age
/backups/app_uploads.tgz.age: age encrypted file
Meaning: You made a portable encrypted archive of file data.
Decision: For file volumes, this is fine. For databases, don’t do this while the DB is live unless you have a consistency mechanism.
Task 10: Restore the encrypted tarball into a new empty volume
cr0x@server:~$ docker volume create app_uploads_restore
app_uploads_restore
cr0x@server:~$ age -d -i /secure/keys/backup.agekey /backups/app_uploads.tgz.age | gunzip -c | docker run --rm -i -v app_uploads_restore:/restore alpine:3.20 sh -c "cd /restore && tar -xvf - | head"
./
./avatars/
./avatars/u123.png
./docs/
./docs/terms.pdf
Meaning: Data is recoverable and lands in a Docker-managed volume.
Decision: Use a restore volume first, then swap it in. Direct restores into live volumes are how you turn a small incident into a long incident.
Task 11: Upload encrypted backups to S3-compatible storage and confirm server-side encryption status
cr0x@server:~$ aws s3 cp /backups/app_pg.dump.age s3://prod-backups/app_pg/2026-01-03/app_pg.dump.age --sse aws:kms
upload: backups/app_pg.dump.age to s3://prod-backups/app_pg/2026-01-03/app_pg.dump.age
cr0x@server:~$ aws s3api head-object --bucket prod-backups --key app_pg/2026-01-03/app_pg.dump.age --query '{Size:ContentLength,SSE:ServerSideEncryption,KMS:SSEKMSKeyId}'
{
"Size": 201326592,
"SSE": "aws:kms",
"KMS": "arn:aws:kms:us-east-1:111122223333:key/REDACTED"
}
Meaning: The object is ciphertext from client-side encryption, and additionally protected by SSE-KMS.
Decision: Keep SSE on. It won’t replace client-side encryption, but it adds guardrails and audit trails.
Task 12: Generate and store a checksum manifest for integrity checks
cr0x@server:~$ sha256sum /backups/app_pg.dump.age /backups/app_uploads.tgz.age > /backups/manifest.sha256
cr0x@server:~$ cat /backups/manifest.sha256
2f9e0f1c0a8c5d4b3e2a1f0e9d8c7b6a5f4e3d2c1b0a9e8d7c6b5a4f3e2d1c0b /backups/app_pg.dump.age
9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b /backups/app_uploads.tgz.age
Meaning: You can detect corruption or partial transfers before you try to restore.
Decision: Store the manifest alongside backups (and ideally also in a separate log system). Verify before decrypting large files.
Task 13: Verify remote object size matches local before restore
cr0x@server:~$ aws s3 ls s3://prod-backups/app_pg/2026-01-03/app_pg.dump.age
2026-01-03 01:02:11 201326592 app_pg.dump.age
Meaning: Size matches expectations; not a guarantee, but catches obvious truncation.
Decision: If size is off, stop. Investigate transfer, multipart upload failures, lifecycle rules, or storage-side corruption.
Task 14: Check lifecycle/immutability posture (ransomware resistance)
cr0x@server:~$ aws s3api get-bucket-versioning --bucket prod-backups
{
"Status": "Enabled"
}
cr0x@server:~$ aws s3api get-object-lock-configuration --bucket prod-backups
{
"ObjectLockConfiguration": {
"ObjectLockEnabled": "Enabled",
"Rule": {
"DefaultRetention": {
"Mode": "GOVERNANCE",
"Days": 30
}
}
}
}
Meaning: Versioning and object lock reduce the chance an attacker (or script bug) deletes your only good backup.
Decision: If you can enable immutability, do it. Encryption protects confidentiality; immutability protects existence.
Task 15: Confirm the restore environment has the right tools before you begin
cr0x@server:~$ age --version
age 1.2.0
cr0x@server:~$ pg_restore --version
pg_restore (PostgreSQL) 16.1
cr0x@server:~$ docker --version
Docker version 24.0.7, build afdd53b
Meaning: Toolchain compatibility is a classic restore failure mode, especially with database restore utilities.
Decision: Keep a known-good restore image or a runbook specifying versions. Don’t discover version mismatches mid-incident.
Playbook de diagnostic rapide
Quand les sauvegardes chiffrées sont « lentes » ou que les restaurations « bloquent », c’est généralement l’un des quatre goulots d’étranglement : CPU, disque, réseau, ou la phase d’application de la base.
Ne devinez pas. Vérifiez dans cet ordre et arrêtez dès que vous trouvez le facteur limitant.
1) Confirmez que vous restaurez le bon artéfact (et qu’il est complet)
- Vérifiez que la taille de l’objet distant correspond aux attentes.
- Vérifiez le manifeste de checksum.
- Décision : si l’intégrité est incertaine, ne procédez pas à la restauration sur une cible en production.
2) Identifiez quelle phase est lente : téléchargement, déchiffrement, décompression ou application
- Chronométrez chaque segment avec des pipelines simples.
- Décision : concentrez l’optimisation là où le temps est réellement passé ; le chiffrement est souvent accusé mais pas coupable.
3) Vérifiez la saturation CPU et les mythes d’entropie
- Les systèmes modernes attendent rarement de l’entropie pour age/GPG en usage normal ; le CPU est le coupable habituel.
- Décision : si le CPU est saturé, envisagez le parallélisme ou des réglages de compression plus rapides, pas un chiffrement plus faible.
4) Vérifiez l’I/O disque et le comportement du système de fichiers
- Les cibles de restauration peuvent être plus lentes que les sources, surtout sur du stockage en réseau.
- Décision : restaurez sur un stockage local rapide, puis déplacez/attachez si possible.
5) Pour les bases de données : la phase d’application domine
pg_restoreet la création d’index peuvent dépasser les temps de téléchargement/déchiffrement.- Décision : ajustez les options de restauration (jobs, paramètres de maintenance) et validez les réglages WAL/checkpoint pour l’environnement de restauration.
Erreurs courantes (symptômes → cause racine → correction)
Mistake 1: “Decrypt failed: no identity found” during restore
Symptoms: age refuses to decrypt; restore blocked immediately.
Root cause: You encrypted to the wrong recipient, lost the private key, or the restore host doesn’t have access to the identity file.
Fix: Encrypt to multiple recipients (team key + break-glass key). Store identity retrieval in the runbook. Test decryption weekly with a small artifact.
Mistake 2: Backups exist but restore yields empty application state
Symptoms: App boots after restore but no users/files/data appear.
Root cause: You backed up images/compose but not volumes or database dumps; or you restored only one of the state components.
Fix: Define a backup inventory: DB + uploads + config. Run restore drills that validate application-level correctness (not just “container is up”).
Mistake 3: Encrypted backups are huge and slow to move
Symptoms: Transfer windows blow out; storage costs climb.
Root cause: Encrypting already-compressed data is fine, but encrypting without compression wastes space; also backing up too much (logs, caches).
Fix: Compress before encrypting; exclude non-critical paths; consider DB-native compression or custom formats.
Mistake 4: “We use SSE-KMS so we’re safe” (until the account is compromised)
Symptoms: Audit passes, but threat modeling doesn’t; a compromised IAM principal can fetch and decrypt.
Root cause: Relying solely on server-side encryption and assuming IAM is unbreakable.
Fix: Add client-side encryption. Treat cloud account compromise as a real scenario, not a theoretical one.
Mistake 5: Passphrase-based encryption embedded in scripts
Symptoms: Anyone with access to the script, process list, or CI logs can decrypt backups.
Root cause: Operational convenience winning a fistfight with security.
Fix: Move to recipient-based encryption. If you must use passphrases, fetch them securely at runtime and keep them out of logs and shell history.
Mistake 6: Volume tar backups of live databases
Symptoms: Restore completes but DB is corrupted or inconsistent; sometimes it “works” until it doesn’t.
Root cause: Filesystem-level capture of a changing database without snapshots or DB coordination.
Fix: Use pg_dump, pg_basebackup, or snapshot mechanisms coordinated with the database. Don’t tar live database directories.
Mistake 7: Key rotation breaks access to old backups
Symptoms: New backups decrypt; old ones don’t; compliance retention becomes a liability.
Root cause: Rotated away old keys without a retention-aware plan.
Fix: Keep old keys available under strict controls until old backups expire, or re-encrypt retained backups as part of rotation.
Trois mini-récits d’entreprise depuis le terrain
Mini-story 1: The incident caused by a wrong assumption
Une entreprise de taille moyenne exécutait une stack Docker Compose : Postgres, une application web, et un volume d’uploads. Ils avaient des « sauvegardes chiffrées »
parce que le disque de la VM était chiffré et le bucket S3 exigeait SSE-KMS. Le job de sauvegarde copiait un pg_dump nocturne dans
le bucket. L’audit passait. Tout le monde dormait.
Puis les clés d’accès cloud d’un développeur ont fui via un job CI mal configuré. L’attaquant n’a pas eu besoin de casser le chiffrement. Avec ces clés,
il a listé le bucket, téléchargé les dumps, et—parce que l’IAM le lui permettait—les a téléchargés. SSE-KMS a fait exactement ce pour quoi il est conçu : il
a déchiffré pour un principal autorisé.
L’hypothèse erronée de l’équipe était subtile : « le chiffrement côté serveur signifie que la compromission du stockage ne peut pas lire les sauvegardes. »
C’est vrai seulement si l’attaquant ne peut pas devenir un principal que le service honore. Dans les environnements cloud, la compromission des credentials est le cœur du problème.
La correction a été le chiffrement côté client vers une clé non accessible à l’environnement compromis. Ils ont chiffré les dumps avec des clés de destinataires détenues
en dehors du compte cloud et téléversé le ciphertext. L’attaquant pouvait toujours voler des objets, mais ce n’étaient que des bruits coûteux.
Mini-story 2: The optimization that backfired
Une autre organisation voulait des sauvegardes plus rapides. Ils ont remarqué que la compression prenait du temps et ont décidé d’« optimiser » en chiffrant d’abord, puis en compressant.
L’idée semblait raisonnable pour les non-spécialistes du stockage : « le chiffrement réduit les données ; la compression les réduira encore plus. » C’est à l’envers en réalité.
Leurs artéfacts de sauvegarde ont explosé. Le temps de transfert a doublé. Les coûts ont augmenté silencieusement jusqu’à ce que la finance remarque. Le temps de restauration
a aussi empiré, car ils devaient maintenant déplacer des objets plus gros avant de pouvoir commencer le déchiffrement et l’application.
Le problème plus profond : ils ont aussi perdu toute chance de déduplication dans leur outil de sauvegarde en aval, parce que le chiffrement randomise le flux.
Ils avaient forcé « des octets uniques chaque jour », ce que les systèmes de stockage interprètent comme « facturez-moi tout ».
Ils sont revenus à la pratique compresser-puis-chiffrer, avec un niveau de compression CPU-faible pour le streaming. Les sauvegardes ont réduit, les transferts se sont stabilisés,
les restaurations ont accéléré, et personne n’a eu à prétendre que le changement initial était « une expérimentation » (ce ne l’était pas).
Mini-story 3: The boring but correct practice that saved the day
Une entreprise régulée exécutait des services Dockerisés sur quelques hôtes. Rien de spécial. Ils faisaient une chose impopulaire : un drill de restauration mensuel.
Pas un exercice sur table. Une vraie restauration dans un environnement jetable, avec une checklist et des timeboxes.
Ils maintenaient aussi deux chemins de déchiffrement : la clé normale dans un système de secrets interne avec RBAC, et une clé privée break-glass stockée hors ligne
avec une procédure de récupération documentée nécessitant deux personnes. C’était ennuyeux, ce qui est le signe que ça fonctionnait.
Pendant un incident—panne de stockage plus reconstruction d’hôte chaotique—ils ont découvert que leur système de secrets était temporairement inaccessible à cause de travaux réseau non liés.
C’est là que beaucoup d’équipes s’arrêtent et commencent à improviser. Ils ne l’ont pas fait. Ils ont invoqué le chemin break-glass, déchiffré les sauvegardes,
restauré Postgres et les uploads, et remis l’activité en route.
Ensuite, le postmortem a été calme. Pas parce qu’ils avaient eu de la chance, mais parce que le chemin de restauration n’était pas théorique. Il avait été pratiqué,
minuté, et rendu intentionnellement ennuyeux.
Blague 2 : Les sauvegardes sont comme les parachutes—si vous ne les testez qu’en laboratoire, vous faites encore de la « recherche », pas de la sécurité.
Checklists / plan étape par étape
Étape par étape : implémenter des sauvegardes chiffrées pour une stack Docker Compose
-
Inventaire de l’état : listez conteneurs, volumes, bind mounts, et dépendances externes (BD, stockages objets).
Décidez ce que signifie « restauration complète » au niveau applicatif. -
Choisissez une méthode de sauvegarde principale par composant :
- Postgres :
pg_dumppour la portabilité ;pg_basebackuppour des restaurations volumineuses plus rapides (avec plus de complexité). - Uploads/fichiers : tar+gzip depuis le volume.
- Postgres :
- Choisissez l’outil et le modèle de chiffrement : age recommandé ; chiffrez pour plusieurs destinataires.
- Concevez la garde des clés : où résident les clés privées, qui peut y accéder, et le chemin break-glass.
- Implémentez des pipelines en streaming : minimisez le texte clair sur disque.
- Générez des métadonnées d’intégrité : manifests de checksum ; signez éventuellement les manifests si vous avez besoin d’une meilleure provenance.
- Expédiez hors site : stockage objet avec versioning et object lock si disponible.
- Testez la restauration : restaurez dans un conteneur/volume frais, validez le comportement applicatif et les comptes de données.
- Planifiez des drills de restauration : au moins mensuellement pour les systèmes critiques ; trimestriellement au minimum pour les moins critiques.
- Journalisez et alertez sur les échecs de sauvegarde : « échec silencieux » est l’état par défaut des scripts non surveillés.
Checklist opérationnelle : avant de faire une rotation de clés
- Listez quels objets de sauvegarde sont chiffrés sous quelle clé (stockez les IDs/recipients des clés dans les métadonnées).
- Définissez les fenêtres de rétention et assurez-vous que les anciennes clés restent disponibles jusqu’à expiration ou ré-chiffrement.
- Effectuez une restauration en utilisant le chemin « ancienne clé » la semaine avant rotation.
- Faites la rotation des clés, puis effectuez immédiatement une restauration en utilisant le chemin « nouvelle clé ».
- Mettez à jour le runbook, pas seulement le code.
Checklist incident : vous devez restaurer maintenant
- Choisissez le point de restauration (RPO) et confirmez qu’il correspond aux besoins métiers.
- Récupérez l’artéfact et vérifiez checksum/taille avant de déchiffrer.
- Obtenez la clé de déchiffrement par le chemin primaire ; si bloqué, invoquez le break-glass.
- Restaurez d’abord sur des cibles propres (nouveaux volumes / nouvelle instance BD).
- Validez au niveau applicatif (connexions, comptes, workflows critiques).
- Ce n’est qu’après que vous redirigez le trafic.
FAQ
1) Dois-je compter sur le chiffrement de disque (LUKS/EBS) pour les sauvegardes ?
Non. Utilisez-le, mais ne comptez pas seulement dessus. Le chiffrement de disque protège un disque. Les sauvegardes bougent. Chiffrez l’artéfact de sauvegarde lui-même pour que la protection voyage avec.
2) Le chiffrement côté serveur (SSE-KMS) suffit-il ?
C’est une bonne base souvent requise, mais ce n’est pas de bout en bout. Si un attaquant obtient un accès IAM qui permet la lecture, SSE va joyeusement déchiffrer pour lui.
Ajoutez le chiffrement côté client pour les scénarios « compte/bucket compromis ».
3) age ou GPG pour les sauvegardes Docker ?
Si vous partez de zéro, choisissez age. Il est plus simple et plus difficile à mal utiliser. Utilisez GPG si votre organisation a déjà une distribution de clés PGP et l’expérience opérationnelle.
4) Où dois-je stocker la clé privée pour déchiffrer les sauvegardes ?
Pas sur l’hôte Docker et pas à côté des sauvegardes. Stockez-la dans un système de secrets contrôlé avec journaux d’audit, plus une copie break-glass hors ligne avec une procédure de récupération documentée.
5) Les sauvegardes doivent-elles inclure les secrets applicatifs ?
Généralement non. Sauvegardez les données et la configuration nécessaires pour redéployer, mais récupérez les secrets depuis un système séparé. Si vous devez sauvegarder des secrets, traitez cette sauvegarde comme de haute sensibilité et isolez l’accès.
6) Comment éviter que le texte clair n’atterrisse sur disque pendant les sauvegardes ?
Stream : dump → compresser → chiffrer → uploader. Les pipes sont vos amis. Validez qu’aucun fichier temporaire intermédiaire n’est créé par vos outils et que les logs ne capturent pas de contenu sensible.
7) Les sauvegardes chiffrées empêchent-elles le ransomware ?
Le chiffrement empêche la lecture non autorisée ; il n’empêche pas la suppression ou le chiffrement par un attaquant. Pour résister aux ransomwares, vous avez besoin d’immuabilité (object lock, versioning, copies hors ligne) et de frontières IAM robustes.
8) Pourquoi les restaurations sont lentes alors que le chiffrement est « rapide » ?
Parce que les restaurations sont généralement dominées par le temps de téléchargement, la décompression, ou l’application/indexation de la base. Mesurez chaque phase. Optimisez le vrai goulot, pas l’outil que vous suspectez.
9) Combien de destinataires devrais-je chiffrer ?
Au moins deux : une clé d’équipe ops (ou clé de service) et une clé de récupération break-glass. Plus de destinataires augmentent la flexibilité opérationnelle mais élargissent aussi qui peut déchiffrer, donc faites-le intentionnellement.
10) Puis-je sauvegarder /var/lib/docker et considérer la tâche faite ?
Vous pouvez, mais vous ne devriez probablement pas. C’est volumineux, sensible aux versions, et mélange caches et état. Sauvegardez les volumes et les artéfacts natifs BD ; laissez l’état du démon Docker de côté sauf si vous avez un besoin prouvé.
Conclusion : prochaines étapes réalisables
Si vous voulez des sauvegardes Docker chiffrées qui se restaurent proprement, arrêtez de traiter le chiffrement comme une case à cocher et traitez la restauration comme une fonctionnalité.
La voie pratique est :
- Inventoriez l’état : volumes, bind mounts, bases de données, et dépendances « cachées ».
- Utilisez des sauvegardes natives BD pour les bases ; tar pour les volumes de fichiers.
- Compressez puis chiffrez (en streaming quand possible).
- Utilisez le chiffrement basé sur les destinataires (age est une valeur sûre par défaut).
- Gardez les clés hors de l’hôte ; fournissez un chemin break-glass indépendant et documenté.
- Rendez les drills de restauration routiniers et mesurables.
- Ajoutez immutabilité/versioning pour protéger l’existence des sauvegardes, pas seulement la confidentialité.
Faites cela, et votre prochaine restauration ne sera pas un thriller. Ce sera du travail. Du travail ennuyeux. Le meilleur type.