Michel Media — Migration Plan
Versie 1 · 2026-05-07 · gebaseerd op DISCOVERY.md
Strategische uitgangspunten
- Eigen alles, voor zover praktisch en betaalbaar.
- Bedrijfskritiek = eigen hardware of cloud waar je voor betaalt (Cloudflare, Mac mini). Niet werk-VPS.
- Cloudflare als platform (Pages, Workers, R2, D1) waar mogelijk, paid tier OK.
- Mac mini als 24/7 hub — productiever maken loont meer dan NAS behouden.
- NAS-exit gepland, niet vandaag uitgevoerd. Camera-vraag eerst beantwoord.
- Cashspot wordt afgesloten, Coolify wordt afgebouwd na de twee resterende deploys gemigreerd zijn.
Filosofie per wave
- Eén wave per Claude-sessie — fris contextvenster, gefocust werken
- Elke wave heeft heldere succes-criteria en een rollback-pad
- Niets weggooien voordat de vervanger 7+ dagen stabiel draait
- DNS swap is laatste stap — services parallel laten draaien tot je weet dat het werkt
- Backup vóór destructieve actie, altijd
Volgorde
Wave 0 → Foundations (Syncthing + parity + R2 fundering) ~3 uur
Wave 1 → SPOF mitigatie (Vaultwarden encrypted export) ~30 min
Wave 2 → Mac mini server prep (Docker + tunnel + Caddy) ~2 uur
Wave 3 → Vaultwarden migratie naar Mac mini ~2 uur
Wave 4 → Paperless migratie naar Mac mini ~3 uur
Wave 5 → soulwise-site → Cloudflare Pages ~1 uur
Wave 6 → dekei1 migratie (decisie + uitvoer) ~3-5 uur
Wave 7 → plex VPS schoonmaak (Coolify + Supabase + Happy) ~2 uur
Wave 8 → NAS audit + Time Machine via Mac mini ~3 uur
Wave 9 → Camera transitie (geparkeerd tot beslissing) tbd
Totaal geschat: 18-25 uur, verspreid over 6-9 weken in eigen tempo.
Wave 0 — Foundations
Doel: Mac mini wordt hot standby voor MacBook. Volledige Claude Code + shell parity. Encrypted backup-pijp naar R2 staat. Hierop bouwen alle andere waves voort.
Prerequisites:
- Mac mini bereikbaar via ssh macmini (al ✓)
- Cloudflare R2 paid tier ingeschakeld (vereist creditcard op CF account, al gekoppeld)
- Syncthing installeren beide kanten
Stappen:
-
Syncthing installatie - MacBook:
brew install syncthing+ start als service - Mac mini:ssh macmini brew install syncthing+ start als service - Pair beide instances via web UI (http://localhost:8384) -
Sync-folders configureren (eenrichtingsverkeer of two-way per folder; zie FAILOVER-PLAYBOOK voor claude-mem-uitzondering)
| Pad | Modus | Reden |
|---|---|---|
~/.claude/ |
two-way | actieve config, nieuwe skills/plugins |
~/.claude-mem/ |
MBP→mini one-way | SQLite single-writer, zie playbook |
~/Documents/michelmedia/ |
two-way | actieve werkmap |
~/Documents/dekei1/ |
two-way | klant-repo |
~/Documents/lurvink/ |
two-way | klant-repo |
~/Documents/og/ |
two-way | werk-repo (afhankelijk van NDA) |
~/.zshrc, ~/.zsh_history |
two-way | shell |
~/.ssh/ |
handmatig kopiëren | beveiligingsoverwegingen |
-
Bootstrap-script opstellen in
~/Documents/michelmedia/infra/bootstrap-mac.sh. Idempotent script dat een verse Mac volledig parity-klaar maakt: - Brew installeer + alle benodigde packages - Apps viabrew install --cask: claude, codex, raycast, etc. - npm/pnpm/python/Ruby toolchain - Stelt SSH config en aliases in - Vaultwarden CLI + bw-unlock script - Claude Code v2.x install + login-instructies - claude-mem plugin install - Verifieer parity: end-to-end Claude Code-sessie test -
R2 fundering - Maak bucket
michelmedia-backupsin CF dashboard (regio EU) - Genereer API token met R2 read/write scope - Installeerresticop MacBook én Mac mini (brew install restic) - Initialiseer encrypted repo:restic init --repo s3:https://<account>.r2.cloudflarestorage.com/michelmedia-backups- Encryptie-passphrase opslaan in Vaultwarden (item: "restic R2 backup passphrase") -
Nightly backup cron op MacBook (LaunchAgent): -
~/.claude/,~/.claude-mem/,~/.ssh/,~/.zshrc, dotfiles → restic snapshot om 03:00 - Logfile naar~/.local/share/restic-backup.log- Telegram notificatie via Spotbot bij slagen + bij falen
Verificatie / succes-criteria:
- ✓ Syncthing toont "Up to date" voor alle folders na 1 uur
- ✓ Bootstrap-script draait zonder fouten op Mac mini en levert werkende Claude Code-sessie
- ✓ restic snapshots op R2 toont gisteren-snapshot
- ✓ End-to-end test: open Claude Code op Mac mini, voer dummy task uit, claude-mem schrijft observations, observations verschijnen in Mac mini's lokale DB
Rollback: - Syncthing pauzeren in UI bij twijfel; per-folder uit te zetten - Bootstrap-script op Mac mini draait niet-destructief (idempotent) - restic snapshots zijn additief, geen impact op live data
Wave 1 — Vaultwarden SPOF mitigatie
Doel: Het ergste single-point-of-failure dichten zonder dat we Vaultwarden verhuizen. Maximaal 30 minuten werk, voorzichtigheidsnet voordat Wave 2/3 plaatsvinden.
Stappen:
- CLI-export:
bw login → bw unlock → bw export --format encrypted_json --password "<sterkte-passphrase>"→ uploaden naar R2 alsvaultwarden/encrypted-export-YYYYMMDD.json - Encrypted file ook kopiëren naar offline USB stick. Stick fysiek opbergen op extern adres (kluis of vertrouwd familieadres).
- Encryptie-passphrase noteren op papier in dezelfde kluis (of in Vaultwarden zelf — paradox).
- Master password van Vaultwarden noteren op papier in kluis.
- Maandelijkse herhaling automatiseren via LaunchAgent + telegram-bericht "vault-export YYYY-MM uploaded".
Verificatie:
- ✓ Test-restore op een tijdelijke Vaultwarden-instance (Docker lokaal) werkt
- ✓ R2 snapshot zichtbaar via aws s3 ls (rclone of wrangler r2)
Rollback: geen — additief, niets te rollbacken.
Wave 2 — Mac mini server prep
Doel: Mac mini klaar maken om Docker-services te hosten op productie-niveau. Reverse proxy + Cloudflare Tunnel + persistent storage.
Stappen:
- Docker Desktop opstarten en in PATH brengen - Auto-start bij login configureren - Resources: 8 GB RAM toewijzen, 4 cores
- Tailscale running zetten (huidige error-state oplossen)
- Folder layout vaststellen:
/Users/michelhelsdingen/Docker/{vaultwarden,paperless,...}voor service-volumes - Cloudflare Tunnel container installeren met eigen tunnel-ID
- Maak nieuwe tunnel "macmini-services" via CF dashboard of
cloudflared tunnel create macmini-services- Token in macOS Keychain - Container start via Docker Compose, auto-restart unless-stopped - Caddy als reverse proxy in Docker (eenvoudig automatisch HTTPS via tunnel) — of route alles via cloudflared tunnel ingress (geen Caddy nodig)
- Test met dummy-service:
nginx-testcontainer achternginx-test.helsdingen.comroute
Verificatie: - ✓ Cloudflare dashboard toont actieve tunnel - ✓ Test-route bereikt nginx-test container vanaf publiek internet via CF Access - ✓ Mac mini reboot test: alle services starten weer automatisch
Rollback: Docker stoppen + tunnel verwijderen. Geen impact op Plex VPS.
Wave 3 — Vaultwarden migratie
Doel: vault.helsdingen.com draait op Mac mini, plex Vaultwarden uitgezet maar containers nog aanwezig (1 week buffer).
Stappen:
- Snapshot maken op plex VPS:
docker stop vaultwarden && tar czf /mnt/docker/backups/vaultwarden-pre-migration-YYYYMMDD.tgz /mnt/docker/vaultwarden/ - Sync naar Mac mini:
rsync -avz plex:/mnt/docker/vaultwarden/ ~/Docker/vaultwarden/ - Mac mini Vaultwarden Docker compose:
- Image
vaultwarden/server:1.35.6(zelfde versie als plex) - Volume mount op~/Docker/vaultwarden- Environment variables overnemen (admin token, signups disabled, etc.) - Tunnel-ingress route:vault.helsdingen.com→http://vaultwarden:80 - Start Mac mini container met aparte test-host eerst:
vault-test.helsdingen.com - Login-test, vault decrypt, browser sync, mobile sync (iOS Bitwarden app)
- Stop plex Vaultwarden container (niet rm)
- DNS swap:
vault.helsdingen.comCNAME wijzigen van plex-tunnel naar mac mini-tunnel - Test live na propagation
- Wachttijd 7 dagen voordat plex Vaultwarden container verwijderd wordt
- Encrypted export pipeline (Wave 1) updaten om Mac mini's volume te exporteren
Verificatie: - ✓ Login succes op vault.helsdingen.com via desktop browser, mobiele app, en bw CLI - ✓ Recent items zichtbaar (geen lege vault) - ✓ Sync van een nieuw item werkt op alle devices - ✓ Mac mini reboot test: Vaultwarden komt weer up
Rollback: - DNS-swap terug naar plex (TTL 5 min) → plex container start opnieuw - Volume op Mac mini blijft als referentie, geen data-verlies
Wave 4 — Paperless migratie
Doel: docs.helsdingen.com draait op Mac mini incl. mail-fetcher en gotenberg/tika. NAS-replicatie als backup-laag.
Stappen:
- Snapshot op plex:
docker compose -f /mnt/docker/paperless/docker-compose.yml stop && tar czf paperless-pre-migration.tgz /mnt/docker/paperless/ - Rsync volume naar Mac mini:
rsync -avz plex:/mnt/docker/paperless/ ~/Docker/paperless/ - Mac mini Docker Compose met identieke services (paperless, redis, gotenberg, tika, mail-fetcher)
- Mail-fetcher:
.env-mailfetcheroverzetten,mail-fetcher.pyook (incl. recente subject-skip update) - Tunnel route:
docs.helsdingen.com→http://paperless:8000 - Test-host eerst:
docs-test.helsdingen.com - Verifieer nieuwe scan@ mail wordt verwerkt door Mac mini-mail-fetcher
- NAS-replicatie inrichten:
- rsync van
~/Docker/paperless/naarterror:/volume1/docker/paperless-mirror/om 04:00 nightly - Plus encrypted snapshot naar R2 (restic) - DNS swap docs.helsdingen.com
- Buffer 7 dagen, dan plex containers stoppen
Verificatie: - ✓ Web-UI laadt op docs.helsdingen.com - ✓ Bestaande documenten zichtbaar - ✓ Nieuwe mail naar scan@ wordt geclassificeerd binnen 5 minuten - ✓ Cron-backup dump naar terror succesvol (eerste run handmatig triggeren) - ✓ R2 snapshot zichtbaar
Rollback: - DNS terug naar plex - Mail-fetcher op plex weer starten
Wave 5 — soulwise-site naar Cloudflare Pages
Doel: Coolify-deploy soulwise-site (nginx static op soulwiseapp.com) verhuizen naar CF Pages. Eerste warm-up voor dekei1.
Stappen:
- Clone
michelhelsdingen/soulwiserepo lokaal (als nog niet aanwezig) - Bouw lokaal als nginx serveerbare output (
dist/ofpublic/) - CF Pages project aanmaken:
soulwise-site - Custom domain
soulwiseapp.com+www.soulwiseapp.com - DNS records swappen
- Verifieer site online
- Coolify deployment uitzetten en verwijderen
- GitHub Actions of CF Git-integratie inrichten voor auto-deploy bij push naar main
Verificatie: - ✓ soulwiseapp.com responds 200 OK - ✓ Visuele check: site identiek aan voor migratie - ✓ Auto-deploy test: push naar main triggert nieuwe deploy
Rollback: - DNS terug naar plex (Coolify deployment niet verwijderen tot stabiel)
Wave 6 — dekei1 migratie
Doel: dekei1.ltcdekei.nl van Coolify Next.js + self-hosted Supabase af.
Eerst beslissing nemen voor de Postgres-laag. Drie opties:
| Optie | Hosting | Migratie-werk | Maandelijkse kosten | Geschikt voor |
|---|---|---|---|---|
| A. CF Pages + Supabase hosted (Frankfurt) | CF + Supabase | medium (DB-export/import) | gratis tier mogelijk | meest pragmatisch, snelst |
| B. CF Pages + D1 | volledig CF | hoog (schema-rewrite, geen pgvector etc.) | gratis ruim | als app simpel genoeg is |
| C. Mac mini Docker (Next + Postgres beide lokaal) | eigen | laag, lift-and-shift | stroom | als je self-host wilt blijven |
Aanbeveling: A mits app niet veel Postgres-extensies gebruikt. Eerst auditeren.
Stappen (uitgaande van A):
- Repo audit:
michelhelsdingen/dekei1. Lijst Postgres extensies, RLS policies, Storage gebruik - Supabase Frankfurt hosted project: bestaande LTC project gebruiken of nieuw aanmaken
- Schema dump van self-hosted:
pg_dumpvan Supabase-db container, restore in hosted project via Studio ofpsql - Storage migratie (indien gebruikt): rsync MinIO bucket → Supabase Storage of R2
- App rebuild met nieuwe SUPABASE_URL en keys, deploy naar CF Pages (Next.js SSR via @cloudflare/next-on-pages)
- Custom domain dekei1.ltcdekei.nl
- Acceptatietest met klant Theo
- Coolify deployment uit, self-hosted Supabase containers nog niet aanraken (Wave 7)
Verificatie: - ✓ Site live op CF Pages - ✓ DB queries werken (login, lijst tonen, schrijven) - ✓ Klant heeft minimaal 7 dagen kunnen testen - ✓ Geen errors in Sentry/CF logs
Rollback: - DNS terug naar plex - Self-hosted Supabase blijft in originele staat tot Wave 7
Wave 7 — plex VPS schoonmaak
Doel: Coolify uitzetten, self-hosted Supabase weg, Happy stack uit, irrelevante containers opruimen. plex VPS draait alleen wat daar logisch hoort.
Eindstaat plex VPS containers: - Immich (server, ML, postgres, redis) - Jellyfin (zit niet in huidige container-list — checken of het via Coolify draaide) - Uptime Kuma - Watchtower - Glances - Portainer (nog overwegen of nodig) - Cloudflared tunnel (alleen voor Immich + Jellyfin) - Optioneel: Homepage, change-detection, AI-news-bot, MEXC bot
Stappen:
- Coolify uitzetten:
docker compose -f /coolify/source/docker-compose.yml down - Self-hosted Supabase 12 containers down + volumes archiveren naar tar in /mnt/docker/backups/
- Happy server stack down (4 containers)
- n8n: blijft draaien op plex of migreren naar Mac mini? Onderdeel van beslissing in Wave 6 (gerelateerd aan dekei1?)
- Cloudflared config updaten — alleen routes overhouden voor diensten die nog op plex draaien
- Check disk usage: zou ~50 GB moeten vrijkomen door Supabase + Coolify cleanup
- Watchtower configuratie verifiëren
Verificatie:
- ✓ Immich + Jellyfin werken op respectievelijke routes
- ✓ Geen 404 of broken routes via cloudflared
- ✓ disk usage /mnt/docker ligt onder 100 GB
Rollback: containers weer starten (volumes blijven), of restore tar.
Wave 8 — NAS audit + Time Machine via Mac mini
Doel: Beslissen of NAS blijft of weggaat. Time Machine van externe SSD af + naar Mac mini SMB share als secondaire bestemming.
Stappen:
- Audit
/volume1/homes(2.7 TB): - Inhoud per top-level folder bepalen - Klasificeer: weggooien / R2 archive / Mac mini lokaal / NAS behouden - Dit kan dagen aan triage zijn — niet één sessie - Audit Plex media op NAS (5.8 GB): verhuizen naar plex VPS Jellyfin of weggooien
- Surveillance migratie afhankelijk van Wave 9 (camera). Tot dan blijft NAS leven.
- Time Machine secondary destination:
- Op Mac mini: enable File Sharing + maak
TimeMachineshare aan (SMB) - Configureer als TM-bestemming in Mac mini's/etc/backup-config- Op MacBook: Systeeminstellingen → Time Machine → Voeg Mac mini toe als 2e doel naast externe SSD - NAS-beslissing: - Als surveillance migreert (Wave 9): NAS leeg en verkopen - Als surveillance blijft: NAS behouden alleen voor camera, andere shares uit
Verificatie: - ✓ Time Machine schrijft naar zowel SSD als Mac mini bij wekelijkse backup - ✓ Geen andere services dependen op NAS shares meer (audit)
Rollback: NAS niet wegdoen voordat 30 dagen volledig draait zonder NAS-toegang.
Wave 9 — Camera transitie (geparkeerd)
Status: Wacht op beslissing. Vrouw gebruikt DS Cam (Synology mobile app). Beelden moeten ergens.
Opties bij beslissing:
- A. NAS behouden voor camera alleen. Andere shares afsluiten. Synology blijft als single-purpose device.
- B. NUC Frigate LXC. Frigate doet object detection + lokaal RTSP. Camerabeelden naar lokale schijf op NUC. DS Cam vervangen door Frigate-app of NVR-alternatief.
- C. Hybride. Cam-streams naar NUC voor detection + opnames, maar DS Cam blijft live-view via Synology als die beelden ontvangt via NUC.
Bij C heeft NUC voldoende capaciteit (cams-lxc gebruikt al 1 GB RAM), maar disk-IO voor opnames is een vraag.
Geen actie tot Michel beslist.
Cross-cutting verwijzing
- FAILOVER-PLAYBOOK.md beschrijft hoe je tussen MacBook ↔ Mac mini schakelt en wat te doen bij elke type uitval
- DISCOVERY.md is de feiten-snapshot waarop dit plan rust. Bij significante infra-wijzigingen herrun
- infra-overview.html / infra.michelmedia.nl is de live dashboard. Ververst niet automatisch — handmatig deploy bij significante wijzigingen