Backups¶
Architecture¶
graph LR
subgraph cluster["Proxmox cluster"]
galahad[galahad
LXC 100 dns-failover
LXC 102 vault]
lancelot[lancelot
LXC 101 logs
LXC 103 pbs]
end
subgraph penny["penny (RPi 4)"]
volumes[Volumes Docker
staging → /mnt/ssd/.restic-staging]
configs[Configs bind-mount
/mnt/ssd/config/*]
nfs[NFS server
/mnt/ssd/pbs-datastore]
end
galahad -->|PBS API| PBS[PBS LXC 103
192.168.1.33]
lancelot -->|PBS API| PBS
PBS -->|NFS mount| nfs
volumes --> restic
configs --> restic
restic[restic backup 3h
chiffre AES-256] --> B2[Backblaze B2
gabin-homelab-backups/restic]
vault102[LXC 102 vault] -->|restic-direct 2h| B2vault[Backblaze B2
restic-vault]
Git[Configs + Scripts] -->|git push| GitHub[GitHub
homelab-config prive]
Chiffrement : AES-256 cote client (restic pour penny + Vaultwarden). PBS chiffre au niveau datastore (AES-256-GCM).
Regle 3-2-1 :
- 3 copies : live (SSD/eMMC) + PBS local (penny SSD via NFS) + Backblaze B2 (restic chiffre)
- 2 supports : SSD/eMMC + cloud
- 1 copie hors-site : Backblaze B2
Proxmox Backup Server (PBS)¶
Infrastructure¶
| Element | Detail |
|---|---|
| LXC | 103 "pbs" sur lancelot, unprivileged, Debian 13, IP 192.168.1.33 |
| Datastore "main" | /mnt/datastore (bind-mount depuis lancelot /mnt/pbs-nfs) |
| Stockage reel | NFS sur penny, export /mnt/ssd/pbs-datastore (65536 chunk dirs) |
| NFS export | all_squash anonuid=100034 (UID mappe du LXC unprivileged) |
| UI | backup.home.gabin-simond.fr via Traefik → 192.168.1.33:8007 |
| Auth | Authelia OIDC realm "authelia" + comptes locaux break-glass |
Comptes PBS¶
Voir comptes.md pour la convention complete.
| Compte | Role | Usage |
|---|---|---|
root@pam |
Superuser | Break-glass uniquement |
gabins@authelia |
Admin sur / |
Login quotidien UI via OIDC 2FA |
gabins@pbs |
Admin sur / |
Break-glass si Authelia down |
svc-pve-backup@pbs!pve |
DatastorePowerUser sur /datastore/main |
Jobs backup PVE Datacenter |
Backup des LXC via PBS¶
Les deux nodes PVE (galahad + lancelot) envoient leurs LXC directement au PBS via l'API native. Plus besoin de vzdump-daily.sh + rsync + pull vers penny.
| LXC | Contenu | Node PVE | Criticite |
|---|---|---|---|
| 100 (dns-failover) | AdGuard secondaire | galahad | Moyenne |
| 101 (logs) | Loki + Grafana | lancelot | Faible |
| 102 (vault) | Vaultwarden | galahad | Critique |
| 103 (pbs) | PBS lui-meme | lancelot | Moyenne (reconstructible) |
vzdump hook temporaire
Les LXC sont backupes en mode stop (pas snapshot) car les rootfs sont sur stockage local (dir, pas ZFS). Le hook /usr/local/bin/vzdump-permfix-hook.sh corrige un bug de permissions sur pct.conf pour les LXC unprivileged. A supprimer quand les rootfs seront migres sur ZFS (mode snapshot natif).
vzdump-permfix-hook.sh¶
Hook vzdump enregistre dans /etc/vzdump.conf sur galahad et lancelot :
Le hook lance un watcher en arriere-plan a backup-start qui surveille l'apparition de pct.conf dans le tmpdir et corrige ses permissions (chmod a+rX dirs, chmod a+r fichiers) pour que lxc-usernsexec (UID 100000) puisse les lire.
Vault — restic-direct vers B2¶
Vaultwarden (LXC 102 sur galahad) dispose d'un backup restic independant, direct vers B2. Ce backup est complementaire de PBS et garantit une copie hors-site meme si PBS ou le NFS sont en panne.
| Element | Detail |
|---|---|
| Script | /usr/local/bin/vault-backup.sh dans LXC 102 |
| Cron | Quotidien 02h00 |
| Repo | b2:gabin-homelab-backups:restic-vault |
| Retention | 7 daily / 4 weekly / 6 monthly |
| Methode | SQLite atomic snapshot (.backup API) + /opt/vaultwarden/ complet |
| Notification | ntfy (low OK, high FAIL) |
penny — restic vers B2¶
Ce qui est sauvegarde¶
Volumes Docker (stages puis backup) :
| Donnee | Volume | Criticite |
|---|---|---|
| Beszel (historique monitoring) | config_beszel-data |
Faible |
| Portainer (config Docker) | config_portainer-data |
Moyenne |
Configs avec secrets :
| Donnee | Chemin | Criticite |
|---|---|---|
| Authelia (DB SQLite + cle OIDC + config + secrets) | /mnt/ssd/config/authelia/ |
Critique |
| AdGuard (config avec rewrites) | /mnt/ssd/config/adguard/ |
Haute |
| Traefik (config + dynamic routes) | /mnt/ssd/config/traefik/ |
Haute |
| Homepage (dashboard config) | /mnt/ssd/config/homepage/ |
Faible |
| Scripts systeme | /mnt/ssd/config/scripts/ |
Moyenne |
| Boot config (cmdline, config.txt) | /mnt/ssd/config/boot/ |
Haute |
| System config (fstab, sysctl) | /mnt/ssd/config/system/ |
Haute |
Via Git (a chaque modification)¶
| Donnee | Repo | Visibilite |
|---|---|---|
| Configs applicatives (Traefik, AdGuard, Homepage, etc.) | homelab-config |
Prive |
| Config systeme (boot, fstab, udev, sysctl, crontab) | homelab-config |
Prive |
| Scripts (monitor, backup, vzdump, proxmox) | homelab-config |
Prive |
Templates Authelia (.example, sans secrets) |
homelab-config |
Prive |
| Documentation | homelab-doc |
Public |
Script homelab_backup.sh¶
Execution : cron quotidien a 3h (0 3 * * *)
Fonctionnement :
- Verification preflight (
.restic-envpresent,resticinstalle) - Stage chaque volume Docker vers
/mnt/ssd/.restic-staging/<label>/ restic backup: staging + configs → B2 (chiffre AES-256)- Nettoyage du staging
restic forget: retention 7 daily / 4 weekly / 6 monthly + prune- Notification ntfy (succes ou echec avec duree)
Verification d'integrite : restic-check-monthly.sh (1er du mois, 4h)
- Verification structure (indexes, packs)
- Verification 10% donnees aleatoires (detection bit rot)
- Alerte ntfy en cas d'echec
Destinations¶
| Destination | Chemin | Retention | Chiffrement | Cout |
|---|---|---|---|---|
| Backblaze B2 (restic penny) | gabin-homelab-backups/restic |
7d / 4w / 6m | AES-256 client-side | Gratuit (<10 Go) |
| Backblaze B2 (restic vault) | gabin-homelab-backups/restic-vault |
7d / 4w / 6m | AES-256 client-side | Gratuit |
| PBS datastore "main" (NFS penny) | /mnt/ssd/pbs-datastore |
Configuree dans PBS | AES-256-GCM | Gratuit |
Ce qui n'est PAS sauvegarde (reconstructible)¶
| Donnee | Raison |
|---|---|
| Images Docker | docker compose pull |
| Cache Docker (overlay2) | Reconstruit automatiquement |
| Certificats TLS (Traefik) | Regeneres par Let's Encrypt |
| Logs | Ephemeres, pas critiques |
| Tailscale state | Re-auth suffit (tailscale up) |
| Proxmox config | Reinstallation via scripts (proxmox-post-install.sh) |
| PBS LXC 103 | Reconstructible (config + datastore sur NFS penny) |
Restauration¶
Restaurer un LXC depuis PBS¶
# Via l'UI PBS (backup.home.gabin-simond.fr) :
# 1. Selectionner le snapshot dans le datastore "main"
# 2. Bouton "Restore" → choisir le node PVE cible
#
# Via CLI PVE :
pvesh create /nodes/<node>/lxc -archive <PBS-backup-ID> -storage local
Restaurer Vaultwarden depuis restic B2¶
# Depuis LXC 102 (ou un nouveau LXC)
source /root/.restic-env && export RESTIC_PASSWORD RESTIC_REPOSITORY B2_ACCOUNT_ID B2_ACCOUNT_KEY
restic restore latest --target /tmp/restore --tag vault
cp -a /tmp/restore/opt/vaultwarden/. /opt/vaultwarden/
# Restaurer le snapshot SQLite propre
cp /tmp/restore/var/backups/vault/db.sqlite3 /opt/vaultwarden/data/db.sqlite3
rm -rf /tmp/restore
systemctl restart vaultwarden
Restaurer un volume Docker (penny)¶
source /root/.restic-env && export RESTIC_PASSWORD RESTIC_REPOSITORY B2_ACCOUNT_ID B2_ACCOUNT_KEY
restic restore latest --target /tmp/restore --include "/mnt/ssd/.restic-staging/beszel"
docker compose stop beszel
docker run --rm \
-v config_beszel-data:/data \
-v /tmp/restore/mnt/ssd/.restic-staging/beszel:/source:ro \
alpine sh -c "rm -rf /data/* && cp -a /source/. /data/"
docker compose up -d beszel
rm -rf /tmp/restore
Restaurer une config (penny)¶
source /root/.restic-env && export RESTIC_PASSWORD RESTIC_REPOSITORY B2_ACCOUNT_ID B2_ACCOUNT_KEY
restic restore latest --target /tmp/restore --include "/mnt/ssd/config/authelia"
docker compose stop authelia
cp -a /tmp/restore/mnt/ssd/config/authelia/. /mnt/ssd/config/authelia/
docker compose up -d authelia
rm -rf /tmp/restore
Restauration complete (nouveau RPi)¶
Voir break-glass.md pour la procedure pas-a-pas.
- Installer DietPi
- Cloner
homelab-configdepuis GitHub - Suivre le README (copier boot, udev, fstab, network, docker)
- Restaurer
.restic-envdepuis la cle USB chiffree restic restore latestdepuis B2- Restaurer les volumes et configs
- Regenerer les secrets Authelia si necessaire (voir README)
docker compose up -d
Credentials restic¶
# /root/.restic-env (chmod 600, gitignored)
RESTIC_PASSWORD=<mot-de-passe-chiffrement>
RESTIC_REPOSITORY=b2:gabin-homelab-backups:restic
B2_ACCOUNT_ID=<keyID>
B2_ACCOUNT_KEY=<applicationKey>
Ce fichier doit etre sur la cle USB chiffree
Sans .restic-env, les backups B2 sont illisibles. Perte de ce fichier = perte des backups.
Bucket gabin-homelab-backups sur Backblaze B2, region US West.
Application key limitee a ce bucket uniquement (read + write).
Voir aussi¶
- Comptes PBS — convention comptes et tokens
- Monitoring — checks backup freshness
- Break-glass — procedure reconstruction d'urgence