Zum Hauptinhalt springen

MEC Multi-Center auf Recast — Runbook (v0 + GitHub + Cockpit)

Zielgruppe: IT, v0-Entwickler, Recast-Betrieb.

Diese Seite bündelt den End-to-End-Weg für MEC-Website-Templates (Rot, Hybrid, Grooß, Grün): Layout in v0, Code in GitHub, Image in GHCR, Betrieb auf Recast, Inhalte aus dem Cockpit.

Kürzere Einstiege: v0 auf Recast (Docker) · Go-Live — MEC auf Recast · v0 Instructions Teil G


Architektur (Überblick)

Multi-Center-Prinzip: Ein Repo = ein Layout (websiteTemplate) = ein Docker-Stack auf Recast. Viele Center teilen dasselbe Image; zur Laufzeit entscheidet die Domain (GET …/api/centers/by-domain), welches Center geladen wird.


Template ↔ GitHub ↔ Recast

AnzeigenamewebsiteTemplateGitHub-RepoGHCR-Image (Beispiel)Recast APP_PORT
MEC Template Rotmec-template-asmg-mec-template-rotghcr.io/sawmuedev/smg-mec-template-rot:latest3001
MEC Template Hybridmec-template-dsmg-mec-template-hybridghcr.io/sawmuedev/smg-mec-template-hybrid:latest3002
MEC Grooßmec-template-groosssmg-mec-template-grooossghcr.io/sawmuedev/smg-mec-template-groooss:latest3003
MEC Grünmec-template-greensmg-mec-template-greenghcr.io/sawmuedev/smg-mec-template-green:latest3004
MEC 2mec-template-csmg-mec-template-c (falls aktiv)ghcr.io/sawmuedev/smg-mec-template-c:latesteigener Port

Jedes Repo enthält lokal RECAST-DEPLOY.md und .env.recast.example — repo-spezifische Kurzreferenz.

Deploy-Dateien im Monorepo (Quelle): deployment-templates/v0-recast/ · Sync-Skript: scripts/sync-mec-recast-deploy-to-template-repos.sh


Was v0 macht — und was nicht

v0 überschreibt nicht automatisch eure Recast-Infrastruktur

v0 arbeitet per GitHub-Integration (Branches v0/…, Merge-PRs). In der Praxis ändern v0-PRs typischerweise:

  • app/, components/, lib/, public/ — Layout, Seiten, API-Clients
  • gelegentlich middleware.ts / Multi-Center-Logik, wenn ihr das in v0 anpasst

In der Regel unangetastet bei normalen Layout-PRs (Stand Template-Repos):

  • Dockerfile, docker-compose.yml, .dockerignore, docker/scripts/
  • .github/workflows/build-push-ghcr.yml
  • app/api/health/, app/api/revalidate/, app/api/cockpit-register/
  • .env.recast.example, RECAST-DEPLOY.md

Risiko: next.config.mjs

v0 setzt beim Initial-Export eine next.config.mjs ohne output: 'standalone'. Ohne diese Zeile bricht der GHCR/Docker-Build ab (.next/standalone fehlt).

Pflicht in jedem Template-Repo:

const nextConfig = {
output: 'standalone',
// … rest (images, redirects, typescript, …)
};

Nach v0-Merges next.config.mjs kurz prüfenoutput: 'standalone' muss erhalten bleiben.

Empfehlung bei v0-Merges

  1. PR-Dateiliste ansehen — Deploy-Pfade sollten nicht gelöscht werden.
  2. next.config.mjs auf output: 'standalone' prüfen.
  3. GitHub Action Build & Publish muss grün sein, bevor Recast pullt.
  4. Bei Verlust: Dateien aus deployment-templates/v0-recast/ oder sync-mec-recast-deploy-to-template-repos.sh erneut syncen.
  5. Multi-Center-Fixes (force-dynamic im Root-Layout, keine fest verdrahteten Center-Namen) auch auf den offenen v0-Branch legen — sonst überschreibt der nächste v0-PR main wieder mit ISR/Hardcodes.

v0 überschreibt also eure App-Dateien im Sinne von Layout-Updates — nicht heimlich das ganze Repo. Deploy-Dateien bleiben, solange v0 sie nicht explizit mitgeneriert und ihr sie nicht beim Merge entfernt. Cockpit-Daten (DB) werden von v0 nie überschrieben.


Einmal-Setup (pro Template-Repo)

  1. v0: Instructions A–J + Teil G (Multi-Center, by-domain) — siehe v0 API Ready-to-Go.
  2. Deploy-Paket aus deployment-templates/v0-recast/ (oder Sync-Skript) ins Repo.
  3. next.config.mjs: output: 'standalone'.
  4. GitHub Action build-push-ghcr.yml → Push auf main baut ghcr.io/sawmuedev/<repo>:latest. Für MapTiler (Rot/Grün): Secret NEXT_PUBLIC_MAPTILER_KEY im GitHub-Repo (gleicher Wert wie Vercel). NEXT_PUBLIC_* wirkt erst nach Image-Build, nicht allein über Recast-.env.
  5. Recast: Verzeichnis z. B. /srv/docker/templates/<repo>/, docker-compose.yml + .env aus .env.recast.example.
  6. Nginx + SSL auf Recast — siehe SETUP-NOTES-for-hoster.md.

Recast .env (Multi-Center, pro Template-Stack)

GHCR_IMAGE=ghcr.io/sawmuedev/smg-mec-template-rot:latest
APP_PORT=3001
COMPOSE_PROJECT_NAME=smg-mec-template-rot

COCKPIT_MULTI_CENTER_MODE=shared
EXPECTED_WEBSITE_TEMPLATE=mec-template-a
DEFAULT_CENTER_SLUG=beispiel-center-slug

NEXT_PUBLIC_DASHBOARD_URL=https://dashboard.cockpit-os.de
COCKPIT_DASHBOARD_URL=https://dashboard.cockpit-os.de
COCKPIT_FRONTEND_CHANNEL=website
REVALIDATION_SECRET=<gleich wie Cockpit-Dashboard>

# Karten (Rot/Grün): gleicher Wert wie Vercel. Wirkt im Browser erst nach GHCR-Rebuild
# mit GitHub Secret NEXT_PUBLIC_MAPTILER_KEY (Next.js backt NEXT_PUBLIC_* beim Build ein).
# NEXT_PUBLIC_MAPTILER_KEY=

COCKPIT_REGISTER_ON_START=false

Nicht setzen (Multi-Center): COCKPIT_CENTER_SLUG, COCKPIT_REGISTER_TOKEN, COCKPIT_DEPLOY_ORIGIN als feste Container-Env.


Alltag: Code-Update (alle Center eines Templates)

v0 ändern → GitHub push/merge → GHCR Action (grün) → Watchtower zieht :latest (ca. 5 Min)

Betrifft alle Center mit demselben websiteTemplate — kein neues Repo, kein neuer Container.

Watchtower (Recast, Prod-Pfad): Stack unter /srv/docker/templates/watchtower/ (smg-mec-watchtower + smg-mec-docker-socket-proxy). Poll alle 5 Minuten, nur Container mit Label com.centurylinklabs.watchtower.enable=true (die vier MEC-Template-Stacks).

Sicherheit (kurz): Watchtower spricht nicht den Docker-Socket direkt an, sondern einen Proxy auf 127.0.0.1:2375 (nicht öffentlich). Images von Watchtower/Proxy sind per Digest gepinnt und aktualisieren sich nicht selbst. Es überwacht fest die vier Template-Container-Namen (nicht nur das Enable-Label — das reicht hinter dem Proxy bei Watchtower 1.20 nicht). EXEC/BUILD/Swarm sind gesperrt. Compose: deployment-templates/v0-recast/watchtower.docker-compose.yml.

Manuell falls der Stack steht: docker compose pull && docker compose up -d im Template-Verzeichnis.


Neues Center (gleiches Template)

SchrittWo
Center anlegen, websiteTemplate passend setzenCockpit
Inhalte pflegenDashboard-Reiter / MCP
Custom Domain eintragenCenter → Website → Aktivierung
DNS A → Recast-IPDomain-Provider / UD (manuell — keine UD-Automatik wie bei Vercel)
SSLRecast (certbot)
Register Production-URLFrontend-Kanäle oder MCP cockpit_register_frontend_deployment
Verbindung testenFrontend-Kanäle → Verbindung prüfen

Kein neuer GHCR-Build nötig.


Cockpit vs. Recast vs. Monorepo center-website

Recast + v0-RepoCockpit Render (cockpit-render)
Frontend-Quellev0-GitHub-Repoapps/center-website im Monorepo
PreviewStaging-Domain / ?center=slugpreview.cockpit-os.de/{slug}
MEC Rot/Hybrid/Grooß/Grün LiveRecast (Zielbild)Legacy, wenn noch nicht umgestellt

Inhalte kommen in beiden Fällen aus dem Cockpit — nur das Layout-Repo unterscheidet sich.


Troubleshooting

SymptomUrsacheFix
Alias-Host (*.cockpit-os.de) lädt Startseite teilweise, Unterseiten 404 / falsches CenterMiddleware mappt Subdomain blind auf Slug (degasperipassagede-gasperi-passage-norderstedt). by-domain findet Center in customDomains, Routing nutzt aber Subdomain als SlugKurz: Primary-DNS auf DB-Slug setzen (de-gasperi-passage-norderstedt.cockpit-os.de). Dauerhaft: Middleware-Patch — bei *.cockpit-os.de zuerst by-domain, dann auf echten Slug umschreiben (apps/center-website/middleware.ts, gleiches Muster in MEC-Template-Repos)
GHCR-Build: .next/standalone not foundoutput: 'standalone' fehltIn next.config.mjs ergänzen, push
Falsches Center / falsches LayoutDomain nicht in Cockpit oder falscher StackcustomDomain + websiteTemplate prüfen; Nginx Host weiterleiten
Hybrid zeigt überall ORO (Logo, Footer, Teaser, Anfahrt)Template ist noch der ORO-v0-Export: Hardcodes + ISR ohne Host-Vary. Nginx-Mapping und by-domain sind dann oft richtig (Titel/Shops vom Host, Rest ORO)Kein Recast-vHost-Fix. Im Hybrid-Repo ORO-Fallbacks entfernen, Texte/Socials aus Center-Surface, Root-Layout force-dynamic. Danach 3–4 Hosts spot-checken — nicht jede Domain einzeln mit Recast durchgehen
404 Template-GuardCenter-Template ≠ EXPECTED_WEBSITE_TEMPLATECockpit-Template oder Recast-Env anpassen
Keine Auto-Aktualisierung nach PublishRevalidateREVALIDATION_SECRET + websitePublicUrlProduction
Karte leer / „MapTiler Key fehlt“NEXT_PUBLIC_MAPTILER_KEY nur auf Vercel, nicht im GHCR-BuildGitHub Secret setzen, Image neu bauen; Watchtower oder Recast pull && up -d
Layout nach Merge nicht auf RecastAction rot, Proxy/Watchtower aus, oder Label fehltGHCR-Action prüfen; docker logs smg-mec-watchtower; ss -lntp | grep 2375 muss 127.0.0.1 zeigen

Siehe auch

Nutzungsstatistik: Seitenaufrufe werden anonymisiert erfasst. Im Umami-Dashboard nach diesem Pfad filtern: /developer-guide/mec-recast-multi-center-runbook