Michel Media — Failover Playbook
Versie 2 · 2026-05-07 — bijgewerkt na Wave 0 uitvoering. claude-mem strategie gewijzigd van Active-Passive Syncthing naar MacBook-only + restic snapshot. Restic primary repo is SFTP naar Mac mini; R2 secondary deferred (Wave 0.5).
Dit document beschrijft hoe je tussen werkomgevingen schakelt, wat te doen bij verschillende uitval-scenario's, en hoe je parity tussen MacBook en Mac mini bijhoudt.
Filosofie
- Eén actieve werkomgeving tegelijk. MacBook is primary, Mac mini is hot standby. We werken niet tegelijk vanaf beide.
- Bewuste wissel. Schakelen gebeurt expliciet, niet stilzwijgend. Sync vóór wissel afronden.
- Documenten als levende bron. Dit playbook is niet eenmalig. Bij elke significante stack-verandering bijwerken.
- Test recoveries vóór ze nodig zijn. Eens per kwartaal failover oefenen.
Wat staat waar
MacBook Pro M4 — primary werkomgeving
- macOS 26.4.1, M4
~/.claude/— Claude Code config (skills, plugins, agents, projects)~/.claude-mem/claude-mem.db— claude-mem werkgeheugen (SQLite, single-writer)~/.zshrc,~/.zsh_history— shell~/.ssh/— keys~/Documents/...— actieve projecten- macOS Keychain — Vaultwarden master password, Google Ads tokens, etc.
- Time Machine → externe SSD (nightly)
- Time Machine → Mac mini SMB share (na Wave 8)
Mac mini M4 Pro — hot standby + 24/7 services + restic SFTP backup target
- macOS 26.4 arm64, M4 Pro, 24 GB RAM, 12 cores
- 192.168.2.214, SSH alias
macmini - Syncthing two-way voor:
claude-config(~/.claude met aggressive ignores),michelmedia,dekei1,lurvink,og - Restic SFTP repo op
~/restic-backups/main/— ontvangt nightly van MBP ~/.claude-mem/zit NIET in Syncthing (zie strategie hieronder), wel in restic-snapshot~/.zshrc— komt via dotfiles GitHub repo + Syncthing van michelmedia~/.ssh/— handmatig gekopieerd (encrypted)- macOS Keychain — handmatig opnieuw ingericht (zie bootstrap-script)
- Docker services (na Wave 3+): Vaultwarden, Paperless, eventueel n8n
- Cloudflare Tunnel container met routes voor zijn services
Restic backup repos
Primary (Wave 0, actief sinds 2026-05-07):
- sftp:macmini:/Users/michelhelsdingen/restic-backups/main
- Encrypted, 40-char passphrase in Vaultwarden item "restic backup passphrase" + lokale ~/.cache/restic-passphrase.txt
- Nightly om 03:30 via LaunchAgent com.michelmedia.restic-backup
- Inhoud: ~/.claude, ~/.claude-mem, ~/.ssh, ~/.zshrc, ~/.zprofile, ~/.gitconfig, ~/.config, ~/Documents/michelmedia
- Retention: 7 daily / 4 weekly / 6 monthly
- Telegram-notificatie via Spotbot bij elke run
Secondary (Wave 0.5, deferred):
- s3:https://<account>.r2.cloudflarestorage.com/noaber-backups
- Off-site, beschermt tegen "huis brandt af"
- Vereist 1-min UI-stap voor S3-keys aanmaken in CF dashboard
GitHub canonical sources
michelhelsdingen/dotfiles(private) — zshrc, gitconfig, ssh-config, Brewfile, bootstrap.sh- Alle klant-repos en eigen tools — push-discipline beperkt verlies bij MBP-uitval tot ongepushte commits
NUC Proxmox — lokale hosting (192.168.2.100, PVE 9.2.2)
Guests: VM 100 Home Assistant · LXC 101 cloudflared tunnel · LXC 102 cams (go2rtc) · LXC 103 topview-backup (klant) · LXC 104 lurvink-backup-puller (klant) · LXC 105 topview-mirror.
Backup-DR (alle 6 guests gedekt): vzdump dagelijks 00:00 (zstd, snapshot, prune 4d/2w/2m) → Synology CIFS (192.168.2.47/home/ha_backup, storage nas), job backup-028a2a26-648a. Restore bij NUC-uitval: nieuwe Proxmox-host → CIFS-mount nas → pct restore/qmrestore uit /mnt/pve/nas/dump/. Dus: nieuwe hardware, restoren, klaar. Geen primair data-verlies.
⚠️ 09-06-2026 gat gedicht: LXC 103+104 (de klant-backup-pullers TopView/Lurvink) stonden NIET in de vzdump-job → bij host-uitval was de hele klant-backup-laag weg. Toegevoegd, nu alle guests gedekt.
VERPLICHT principe bij elke (klant-)backup-inrichting — geen DR-laag die zelf een single-point-of-failure is: 1. Alle guests/diensten in de backup-job (verifieer job-lijst vs wat draait). 2. Het backup-systeem zélf óók backuppen (pullers/mirrors off-host). 3. Off-host / off-site (nooit alleen op de bron-host). 4. Restore-pad gedocumenteerd. 5. Dekking + actualiteit periodiek verifiëren.
Plex VPS — werk-eigendom, na Wave 7
- Immich (foto's), Jellyfin (media), Uptime Kuma, monitoring tooling
- Niet bedrijfskritiek — uitval = verlies van foto's/film, geen werk-stop
Vaultwarden offline kluis-papier
- Master password
- Restic R2 passphrase
- USB-stick met
vaultwarden/encrypted-export-YYYYMMDD.json - Bootstrap-credentials: SSH key naar plex/macmini, CF Global API Key fingerprint
claude-mem strategie (v2)
Het probleem
claude-mem.db is SQLite op MacBook (~/.claude-mem/claude-mem.db, ~5 GB total folder). De claude-mem worker op poort 37777 schrijft real-time tijdens Claude Code sessies. Twee machines die tegelijk schrijven via Syncthing = corruption-risico.
Gekozen aanpak: MacBook-only + restic snapshot (v2, gewijzigd 2026-05-07)
- MacBook = single home voor claude-mem.db (ook structureel, niet flip-baar)
- Geen Syncthing voor
~/.claude-mem/(vermeden om SQLite-corruptie te elimineren) - Nightly restic snapshot naar SFTP-repo op Mac mini (en straks R2)
- Bij MacBook-uitval: restic-restore op Mac mini, max 24h verlies acceptabel
Voordelen vs. v1 Active-Passive
- Geen wisseldiscipline meer — werkt op één machine, geen ritueel bij wissel
- Geen single-writer race mogelijk
- Geen Syncthing-conflict-files in een SQLite database (zou direct corrupt zijn)
- Verlies bounded: max 24 uur sinds laatste snapshot
Nadelen
- Mac mini heeft niet "live" claude-mem context (alleen gisteren-snapshot)
- Bij snel wisselen machines: korte tijd geen werkgeheugen
- In de praktijk niet erg: Michel werkt sequentieel op één machine
Restore op Mac mini bij MBP-uitval
ssh macmini
export RESTIC_PASSWORD_FILE="$HOME/.cache/restic-passphrase.txt"
export RESTIC_REPOSITORY="/Users/michelhelsdingen/restic-backups/main"
restic snapshots --tag macbook | head -3
restic restore latest --target / --include /Users/michelhelsdingen/.claude-mem
# claude-mem worker start vanzelf bij volgende Claude Code-sessie
(Op Mac mini local SFTP-pad gebruikt geen sftp: prefix omdat het de lokale repo zelf is.)
Restore op nieuwe Mac (na MBP-diefstal of brand)
# 1. Bootstrap Mac met dotfiles (zie README in dotfiles repo)
# 2. Get passphrase uit Vaultwarden
bw get item "restic backup passphrase" | jq -r '.login.password' > ~/.cache/restic-passphrase.txt
chmod 600 ~/.cache/restic-passphrase.txt
# 3. Restore vanaf primary (Mac mini SFTP) of secondary (R2)
export RESTIC_PASSWORD_FILE="$HOME/.cache/restic-passphrase.txt"
export RESTIC_REPOSITORY="sftp:macmini:/Users/michelhelsdingen/restic-backups/main"
# of: export RESTIC_REPOSITORY="s3:https://<acct>.r2.cloudflarestorage.com/noaber-backups"
restic snapshots
restic restore latest --target ~ --include /Users/michelhelsdingen/.claude --include /Users/michelhelsdingen/.claude-mem
Failover-scenario's
Scenario A — MacBook stuk, ben thuis
Recovery-tijd: 5-10 min.
- Loop naar Mac mini (of open via SSH/VNC vanaf andere device)
- Open Claude Code op Mac mini — alle skills, plugins, configs beschikbaar via Syncthing
- claude-mem context: restore vanuit lokale restic-repo:
bash export RESTIC_PASSWORD_FILE="$HOME/.cache/restic-passphrase.txt" export RESTIC_REPOSITORY="/Users/michelhelsdingen/restic-backups/main" restic restore latest --target / --include /Users/michelhelsdingen/.claude-mem - Open shell — zsh history en aliases werken via Syncthing
- Start werk waar je was. claude-mem heeft max-24h-oude context.
Wat ontbreekt: wat MacBook tussen laatste 03:30-snapshot en uitval deed (max 24 uur claude-mem werkgeheugen-verlies). Documents/code: max paar minuten via Syncthing.
Scenario B — MacBook gestolen, op pad
Recovery-tijd: 30-60 min.
- Vanaf elke device: log in op iCloud → "Find my Mac" → wipe op afstand
- Vanaf elke device: log in op vault.helsdingen.com via web (of telefoon Bitwarden app)
- Als telefoon ook weg: gebruik USB-stick uit kluis met vault-export, importeer in nieuwe Bitwarden-instance op telefoon
- Loop later thuis naar Mac mini, switch naar primary (Scenario A)
Wat ontbreekt: zelfde als A, plus laatste git-commits die niet gepusht waren (verlies). Daarom: discipline om vaak te pushen.
Scenario C — Plex VPS uit (werk koppelt af, hosting incident)
Recovery-tijd: afhankelijk van wanneer Wave 3+ uitgevoerd.
Voor Wave 3 (huidige staat, post Wave 0.6 + 0.8): Vaultwarden en Paperless niet bereikbaar tijdens outage, maar data is veilig: - Vaultwarden: daily encrypted_json export op R2 + lokaal MBP. Nieuwe instance opzetten = 30-45 min (zie RESTORE-VAULTWARDEN.md). In tussentijd Bitwarden web of laatste lokale export gebruiken. - Paperless: daily GPG-encrypted tar.gz op R2 + Synology NAS. Nieuwe instance opzetten op Mac mini Docker = 30-60 min (zie RESTORE-PAPERLESS.md). Mail-fetcher staat stil tijdens outage; mails blijven in info@/scan@ inbox tot fetcher weer draait.
Na Wave 3+: Vaultwarden + Paperless draaien op Mac mini. plex VPS uit = alleen Immich/Jellyfin/Coolify niet bereikbaar. Geen werk-stop, ook geen restore nodig.
Scenario D — Brand thuis, ben elders
Recovery-tijd: 1-2 dagen (nieuwe Mac kopen + restoren).
⚠️ Voor de R2 secondary repo (Wave 0.5) is uitgevoerd is dit scenario zwaarder: alleen GitHub (code) + Vaultwarden web (credentials) overgebleven, claude-mem werkgeheugen verloren. Snel Wave 0.5 doen voor volledige dekking.
- Koop nieuwe Mac (of leen tijdelijk apparaat)
- Run bootstrap-script vanaf GitHub:
git clone https://github.com/michelhelsdingen/dotfiles && ./dotfiles/bootstrap.sh - Vaultwarden web (vault.helsdingen.com) of USB-stick uit externe kluis
- Na Wave 0.5: restic restore vanuit R2 voor
~/.claude/+~/.claude-mem/ - Plex VPS draait nog (andere fysieke locatie) → werk hervat
Wat ontbreekt: alles op MacBook + Mac mini lokaal dat niet in GitHub of R2 stond. Surveillance-beelden zijn weg (Synology weg).
Scenario F — Michel zelf uit (ziek, ongeval, langdurig afwezig)
Recovery-tijd: afhankelijk van wie de stand-in is en hun technische bekwaamheid.
Belangrijke continuity-overwegingen voor net-startende eenmanszaak zonder team:
Wat een stand-in moet kunnen: 1. Klanten informeren over afwezigheid (Theo Lurvink, Theo QuickSlide, Bart Hulshof, Hans Rikhof, Mart Schutten) 2. Toegang tot e-mail (info@michelmedia.nl, info@noaber.ai) voor lopende correspondentie 3. Moneybird openen voor lopende facturen (eerste live factuur 1 juni QS) 4. Bij urgentie: een externe partij inschakelen voor lopende klant-projecten
Voorbereiding (TODO, vóór 1 juli ZZP-voltijd): 1. Vertrouwd persoon (vrouw of beste vriend) krijgt: - Locatie van Vaultwarden master password (kluis-papier) - Locatie van USB-stick met vault-export - Lijst klant-contactgegevens + lopende projecten samenvatting - Een korte runbook: "wat te doen als Michel langdurig uit" 2. Document op papier in dezelfde kluis als vault-credentials: - Klant-namen + relatie ("Theo van Lurvink Textiel" = vriend, persoonlijk reachable) - Bankrekening + saldo-locatie - Verzekeringen (incl. arbeidsongeschiktheid als afgesloten) - Boekhouder-/accountant-contact (voor IB-aangifte buiten wijl Michel kan) 3. Voltijds-ZZP per 1 juli betekent dat Michel het enige inkomen levert — overweeg AOV verzekering voor ziekte/arbeidsongeschiktheid
Niet IT-kwestie alleen. Wel IT-relevant: bij langdurige afwezigheid kan stand-in geen MacBook openen zonder password (FileVault) en geen klant-systemen bedienen zonder Vaultwarden-toegang.
Mitigatie tot betere continuity-doc bestaat: - Vrouw kent Vaultwarden master password (geheim niveau verschilt — eigen keuze hoever bij dit te delen) - Op kluis-papier ligt: master password + USB-locatie + telefoon-code voor 2FA-app
Scenario E — Cloudflare account compromise
Recovery-tijd: dagen tot weken.
Catastrofaal scenario want CF is "het zenuwstelsel". Mitigatie: - 2FA op CF account verplicht (al ingericht?) - API keys minimaal verspreid (Global API Key alleen voor Claude scripts, Bearer tokens voor andere tools) - Backup van R2 niet via R2 zelf maar ook lokaal op Mac mini disk
Volledige preventie + recovery: vereist apart Identity Recovery Plan doc, niet hier.
Maandelijkse parity-check
Ritueel op de eerste maandag van de maand. ~15 min.
# 1. Versie-vergelijk Claude Code op beide machines
ssh macmini "claude --version"
claude --version
# 2. Versie-vergelijk claude-mem
ssh macmini "ls ~/.claude/plugins/marketplaces/thedotmack/claude-mem"
ls ~/.claude/plugins/marketplaces/thedotmack/claude-mem
# 3. Sync-status beide machines
syncthing cli show system
ssh macmini "syncthing cli show system"
# 4. Restic snapshot recent?
restic -r s3:... snapshots --last 5
# 5. Vault-export laatste maand aanwezig in R2?
rclone ls r2:michelmedia-backups/vaultwarden/
# 6. Test failover discipline (op Mac mini):
# open Claude Code, doe dummy task, check claude-mem schreef.
# sluit, switch terug naar MBP-primary mode.
Output noteren in ~/Documents/michelmedia/infra/parity-checks/YYYY-MM.md. Zo zie je over tijd of er drift ontstaat.
Bootstrap een verse Mac
~/Documents/michelmedia/infra/bootstrap-mac.sh (zie Wave 0). Volgorde:
- Install Homebrew
brew bundlemet Brewfile (apps + CLI tools)- Restore SSH keys vanuit Vaultwarden of veilige bron
- Restore
~/.claude/vanuit Syncthing-pair óf restic-restore vanuit R2 - Login Claude Code (
claude login) - Install claude-mem plugin
- Restore
~/.claude-mem/claude-mem.db(zelfde bron) - Vaultwarden CLI:
bw login, master password vanuit kluis-papier - Hardlink/sync
~/Documents/michelmedia/ - Test: open Claude Code, run "claim hello", check claude-mem schreef
Document onderhoud
Bij elke wave-uitvoering update je deze documenten:
- DISCOVERY.md als infra significant wijzigt
- MIGRATION-PLAN.md waves afkruisen + aanpassingen noteren
- FAILOVER-PLAYBOOK.md scenario's bijwerken als nieuwe risk-laag erbij komt
- infra-overview.html redeploy
Aan het eind van de complete migratie (alle waves doorlopen) overweeg een v2 van deze documenten met afgekruiste items en herziene "wat staat waar" tabel.