Doel: elke service heeft een gedocumenteerde, geteste backup én restore procedure.
Gouden regel: een backup zonder geverifieerde restore is geen backup.
Transport keuze: twee lagen
Langetermijn architectuur: stateful data hoort op TrueNAS NFS mounts, niet op lokale Docker volumes. Dan doen ZFS snapshots het meeste werk automatisch. Restic wordt de laag voor offsite (cloud) backup van TrueNAS zelf.
| Service | Kritiek | Backup methode | RPO | RTO | Data op NFS? |
|---|---|---|---|---|---|
| Vaultwarden | 🔴 Ja | SQLite hot backup | 24u | 30 min | Nee — lokaal |
| Nextcloud | 🔴 Ja | Maintenance mode + mysqldump | 24u | 1 uur | Nee — lokaal |
| Minecraft | 🟡 Familie | Container stop + volume copy | 24u | 30 min | Nee — lokaal |
| Home Assistant | 🟡 Familie | HA native backup API | 24u | 45 min | Nee — lokaal |
| Immich | 🟡 Familie | pg_dump + NFS voor foto's | 24u | 45 min | Deels |
| Jellyfin | 🟢 Laag | Config stop + copy | 48u | 30 min | Media: Ja |
| Arr stack | 🟢 Laag | SQLite hot backup | 48u | 1 uur | Media: Ja |
| AdGuard | 🟢 Laag | Config hot copy | 1 week | 10 min | Nee — klein |
| Traefik | 🟢 Laag | ACME cert hot copy | 1 week | 15 min | Nee — klein |
| Observability | ⚪ Niet kritiek | Grafana config only | n.v.t. | 15 min | Nee |
| Uptime Kuma | ⚪ Niet kritiek | SQLite hot backup | n.v.t. | 10 min | Nee |
Wat: wachtwoorden en attachments van het hele gezin. Hoogste prioriteit.
Data:
/opt/vaultwarden/data/db.sqlite3 — alle vault data/opt/vaultwarden/data/attachments/ — bijlagen/opt/vaultwarden/data/sends/ — Bitwarden Send bestandenMethode: SQLite hot backup (applicatie blijft draaien)
# Stap 1 — consistente DB snapshot maken (atomic, geen corruptie)
docker exec vaultwarden sqlite3 /data/db.sqlite3 \
".backup '/data/db.backup.sqlite3'"
# Stap 2 — backup naar TrueNAS
restic backup /opt/vaultwarden/data/db.backup.sqlite3 \
/opt/vaultwarden/data/attachments/ \
/opt/vaultwarden/data/sends/
# Stap 3 — opruimen
rm /opt/vaultwarden/data/db.backup.sqlite3
Restore:
# 1. Container stoppen
cd /opt/vaultwarden && docker compose stop
# 2. Data terugzetten
restic restore latest --target /opt/vaultwarden/data
# 3. Backup DB terug naar originele naam
mv /opt/vaultwarden/data/db.backup.sqlite3 /opt/vaultwarden/data/db.sqlite3
# 4. Container starten
docker compose up -d
Verificatie na restore: inloggen via vault.drice.nl, controleer of wachtwoorden aanwezig zijn.
Wat: bestanden, agenda, contacten van het gezin.
Data:
/opt/nextcloud/data/<username>/files/ — gebruikersbestanden/opt/nextcloud/config/ — configuratieMethode: maintenance mode → mysqldump → file backup
# Stap 1 — maintenance mode aan (voorkomt inconsistente state)
docker exec nextcloud php occ maintenance:mode --on
# Stap 2 — database dump
docker exec nextcloud-db mysqldump \
--all-databases \
--single-transaction \
-u root -p"${DB_ROOT_PASSWORD}" \
> /tmp/nextcloud-db-$(date +%Y%m%d).sql
# Stap 3 — bestanden backup
rsync -av /opt/nextcloud/data/ /tmp/nextcloud-data-backup/
# Stap 4 — maintenance mode uit
docker exec nextcloud php occ maintenance:mode --off
# Stap 5 — transport naar TrueNAS
restic backup /tmp/nextcloud-db-*.sql /tmp/nextcloud-data-backup/
Restore:
# 1. Playbook draaien (nieuwe VM + containers)
ansible-playbook playbooks/nextcloud.yml
# 2. Maintenance mode aan
docker exec nextcloud php occ maintenance:mode --on
# 3. Database terugzetten
docker exec -i nextcloud-db mysql -u root -p"${ROOT_PW}" < nextcloud-db.sql
# 4. Bestanden terugzetten
rsync -av nextcloud-data-backup/ /opt/nextcloud/data/
# 5. File ownership corrigeren
docker exec nextcloud chown -R www-data:www-data /var/www/html/data
# 6. Maintenance mode uit + cache legen
docker exec nextcloud php occ maintenance:mode --off
docker exec nextcloud php occ files:scan --all
Wat: spelwerelden van de kids. Verliezen = drama.
Data (huidige situatie — named volumes):
/var/lib/docker/volumes/minecraft_minecraft-creative-data/_data//var/lib/docker/volumes/minecraft_minecraft-survival-data/_data/Data (na migratie naar bind mounts):
/opt/minecraft/creative//opt/minecraft/survival/Methode: RCON save + container stoppen → volume kopiëren
# Stap 1 — wereld opslaan en schrijven uitschakelen
docker exec minecraft-creative rcon-cli save-all
docker exec minecraft-creative rcon-cli save-off
docker exec minecraft-survival rcon-cli save-all
docker exec minecraft-survival rcon-cli save-off
# Stap 2 — container stoppen (garantie op consistente data)
docker compose stop
# Stap 3 — backup
restic backup /opt/minecraft/creative/ /opt/minecraft/survival/
# Stap 4 — server weer starten
docker compose up -d
⚠️ RCON moet geconfigureerd zijn (ENABLE_RCON=true, RCON_PASSWORD via SOPS)
Restore:
# 1. Server stoppen
ssh ubuntu@192.168.2.158
cd /opt/minecraft
sudo docker compose stop
# 2. Beschikbare backups bekijken
ls -lht /mnt/truenas-backups/minecraft/creative/
ls -lht /mnt/truenas-backups/minecraft/survival/
# 3. Wereld terugzetten (vervang de bestandsnaam door de gewenste backup)
sudo rm -rf /opt/minecraft/creative/data/*
sudo tar -xzf /mnt/truenas-backups/minecraft/creative/world-20260910-122312.tar.gz \
-C /opt/minecraft/creative/data/
sudo rm -rf /opt/minecraft/survival/data/*
sudo tar -xzf /mnt/truenas-backups/minecraft/survival/world-20260910-122312.tar.gz \
-C /opt/minecraft/survival/data/
# 4. Server starten
sudo docker compose up -d
Nood-restore (nieuwe VM):
# VM aanmaken
tofu apply -target=proxmox_virtual_environment_vm.minecraft
ansible-playbook playbooks/minecraft.yml
# Dan bovenstaande restore stappen uitvoeren
Verificatie: inloggen op de server, controleer of de wereld intact is.
Wat: domotica automatiseringen, integraties, geschiedenis.
Methode: HA native backup via API (meest betrouwbaar)
# Backup aanmaken via HA API
curl -X POST \
-H "Authorization: Bearer ${HA_TOKEN}" \
http://192.168.2.x:8123/api/backups/full
# Backup ID ophalen
BACKUP_ID=$(curl -s \
-H "Authorization: Bearer ${HA_TOKEN}" \
http://192.168.2.x:8123/api/backups \
| jq -r '.[0].slug')
# Backup downloaden
curl -o /tmp/ha-backup-$(date +%Y%m%d).tar \
-H "Authorization: Bearer ${HA_TOKEN}" \
http://192.168.2.x:8123/api/backups/${BACKUP_ID}/download
# Opslaan naar TrueNAS
restic backup /tmp/ha-backup-*.tar
Restore: HA UI → Settings → System → Backups → Upload & Restore
Wat: familiefoto's en -video's. Kritiek.
Architectuur: foto's op TrueNAS NFS (ZFS snapshots dekken dit), PostgreSQL op lokale VM.
Data:
/mnt/truenas/immich/upload/ — originele bestanden (al op TrueNAS = ZFS snapshot)Methode: pg_dump (hot, database blijft draaien)
# Database dump
docker exec immich-postgres pg_dump \
-U postgres immich \
> /tmp/immich-db-$(date +%Y%m%d).sql
# Alleen de DB backup naar Restic (foto's al op TrueNAS)
restic backup /tmp/immich-db-*.sql
Wat: DNS configuratie (blocklists, rewrites, clients).
Data:
/opt/adguard/data/AdGuardHome.yaml/opt/adguard/data/sessions.dbMethode: hot copy (AdGuard schrijft config atomisch)
restic backup /opt/adguard/data/AdGuardHome.yaml \
/opt/adguard/data/sessions.db
Restore: config deployen via Ansible → eventueel handmatig DNS rewrites controleren.
Wat: Let's Encrypt certificaten (domeinvalidatie duurt uren als je opnieuw moet aanvragen).
Data:
/opt/traefik/data/letsencrypt/acme.jsonMethode: hot copy
restic backup /opt/traefik/data/letsencrypt/acme.json
Let's Encrypt heeft rate limits: max 5 certificaten per domein per week. Backup voorkomt onnodig heruitgifte.
Wat: historische metrics en logs. Niet kritiek — verlies is acceptabel.
Grafana: dashboards en datasources staan in provisioning config (in git). Alleen de SQLite alerting config is de moeite waard.
# Alleen Grafana config
docker exec grafana sqlite3 /var/lib/grafana/grafana.db \
".backup '/tmp/grafana.db'"
restic backup /tmp/grafana.db
Prometheus en Loki: geen backup. Bij verlies gewoon opnieuw deployen — data bouwt vanzelf op.
Restic per service naar TrueNAS via SFTP of REST backend. Pre-commands in backup script voor quiesce.
Alle stateful data op TrueNAS NFS mounts. ZFS snapshots dekken alles automatisch. Restic wordt alleen nog gebruikt voor:
Voor elke kritieke service:
Vastleggen in: docs/dr-test-log.md