Mayday Hetzner Staging Deploy
Overview
Mayday-Rhynern-Webseite (Next.js + Payload CMS) von Railway auf Hetzner umziehen, als Staging unter staging.mayday-rhynern.de. Produktive mayday-rhynern.de (alte Wordpress-Site) bleibt unangetastet — Cutover separat.
Problem Frame
Railway wird abgeloest (AWS-First-Policy, Mayday explizit als Hetzner-Projekt geplant). Staging-Deploy heute Abend als kontrollierter erster Schritt, ohne Produktion zu gefaehrden.
Scope Boundaries
- In Scope: Staging-Subdomain, App + Postgres + R2-Anbindung + Cloudflared-Tunnel, basic Smoke-Test
- Out of Scope (heute): Daten-Migration aus Railway (Conny baut Test-Inhalte zur Not neu), Domain-Cut auf
mayday-rhynern.de, MailerSend-Production-Config, Stripe-Live-Keys, Cloudflare-Access-Layer
Hosting-Entscheidung
Bare Docker + Cloudflared-Tunnel auf bestehendem av-tools-shared-01 (cx23, 46.225.16.231). Kein Coolify, kein neuer Server. Pattern analog Stirling/Uptime-Kuma laut av-tools.
Cutoff-Kriterien
- 21:30 Hard-Stop — wenn nicht durch, letzte funktionierende Stelle dokumentieren, weiter morgen
- Postgres-Container kommt nicht hoch → abbrechen, ist Hauptpfad
- Next.js-Build schlaegt auf Server fehl → Image lokal bauen + via Docker Hub / GHCR pushen als Plan B (kostet zusaetzliche 30 min, nicht heute)
Implementation Units
- Unit 1: Repo-Pfad in Vault korrigieren + R2-Setup pruefen
Goal: Vault-Eintrag und R2-Bucket-Status klar fuer den Deploy.
Files:
- Modify:
intern/projekte/mayday-webrelaunch/_index.md(Repo-URL ergaenzen:marvin-khl/mayday-rhynern) - Modify:
intern/kunden/mayday.mdfalls noetig
Approach: Cloudflare-MCP nutzen um R2-Bucket-Status zu checken (existiert mayday-media-Bucket schon? Credentials in 1Password?). Wenn nicht existiert: anlegen.
Verification: R2-Bucket-Name + Access/Secret-Key + Endpoint stehen bereit fuer Env-Vars.
- Unit 2: Postgres-Container auf av-tools-shared-01
Goal: Postgres 16 mit persistentem Volume und einem mayday-DB-User auf 127.0.0.1:5432 (lokal-only).
Files (auf Server):
- Create:
/opt/mayday-db/docker-compose.yml - Create:
/opt/mayday-db/.env(DB-Passwort, 0600 root)
Approach: Eigener Service-Ordner (nicht in mayday-app gemischt, damit Postgres-Restart die App nicht zwingt). postgres:16-alpine, bind 127.0.0.1:5432, named volume mayday_pgdata.
Verification: docker exec mayday-db psql -U mayday -c "SELECT 1" gibt 1 zurueck.
- Unit 3: Mayday-App-Container bauen + deployen
Goal: Next.js-Standalone-Image aus dem Repo gebaut, App-Container laeuft auf 127.0.0.1:3010, schreibt in den Postgres-Container.
Files (lokal):
~/source/Kunden/mayday/Dockerfile(existiert, multi-stage build)
Files (auf Server):
- Create:
/opt/mayday/docker-compose.yml - Create:
/opt/mayday/.env(alle Runtime-Env-Vars laut.env.example, 0600 root) - Repo geklont nach
/opt/mayday/source/
Approach: Build direkt auf dem Server (kein Registry-Push noetig, Pattern wie av-tools). NEXT_PUBLIC_SITE_URL=https://staging.mayday-rhynern.de als Build-Arg. DATABASE_URL zeigt auf den Postgres-Container via docker-network. PAYLOAD_SECRET + REVALIDATE_SECRET frisch generiert. PREVIEW_PASSWORD setzen damit Site nur fuer Berechtigte sichtbar.
Verification: curl http://127.0.0.1:3010/login auf dem Server gibt 200 + HTML mit Payload-Login.
- Unit 4: Cloudflared-Ingress + DNS fuer staging.mayday-rhynern.de
Goal: https://staging.mayday-rhynern.de zeigt auf den App-Container ueber den existierenden av-tools-Tunnel.
Files (auf Server):
- Modify:
/etc/cloudflared/config.yml(neue Ingress-Regelstaging.mayday-rhynern.de→http://localhost:3010)
Files (Cloudflare):
- DNS-CNAME
staging.mayday-rhynern.de→<av-tools-tunnel-id>.cfargotunnel.com
Approach: Mayday-Rhynern-Zone in Marvins Cloudflare-Account erstmal pruefen (vermutlich da, weil mayday-rhynern.de live laeuft auf Wordpress). CNAME via Cloudflare-MCP execute setzen (DNS-Update, nicht Tunnel-Route weil Tunnel ist im agenticventures.de-Zone-Setup aber Tunnel kann auch andere Zonen bedienen wenn der Account Zugriff hat).
Verification: curl -I https://staging.mayday-rhynern.de/login → 200, dann im Browser Login-Seite mit Payload-Branding.
- Unit 5: Initial-Admin anlegen + Conny Bescheid sagen
Goal: Conny kann sich in Payload einloggen und Test-Content pflegen.
Approach: Beim ersten Admin-Login (Payload-First-User-Flow) Admin-User mit Marvin-Email + frisches Passwort. Conny-Account dann als zweiter User mit ihrer Mail. Kurze Mail an Conny mit Login-URL + Preview-Passwort.
Verification: Conny kommt rein und kann ein Test-Event anlegen.
Vault-Doku-Updates nach Deploy
intern/capabilities/hetzner/av-tools.md— Services-Tabelle ergaenzen (mayday auf Port 3010)intern/projekte/mayday-webrelaunch/_index.md— Historie + Naechste Meilensteine aktualisieren (Hetzner-Deploy ✓, Domain-Cut auf prod ist naechster Schritt)
Risks & Dependencies
| Risk | Mitigation |
|---|---|
| Docker-Build auf cx23 (4 GB RAM) zu langsam / OOM | Wenn fehlschlaegt, Image lokal bauen + via GHCR push. Nicht heute Abend, dann morgen |
| R2-Bucket nicht existiert / Keys verloren | Lokal media-Folder Fallback im Dockerfile, R2 nachziehbar |
| MailerSend-Key nicht greifbar | Staging kann ohne Email-Versand laufen — Buchungen werden eingelegt, Bestaetigungs-Mails koennen erstmal blocken |
| Falsche Zone-Permission Cloudflare | DNS via UI als Fallback, Tunnel-Ingress geht trotzdem |
Sources
- Source-Repo: https://github.com/marvin-khl/mayday-rhynern
- Pattern-Ref: payload-r2-railway-setup
- Hetzner-Host-Doku: av-tools
- Projekt-Header: _index