Go-Live: DNS, Render, Vercel, Recast & United Domains
Automatisierung für Custom Domains — ohne Datenverlust (nur additive DB-Felder und optionale API-Schritte).
Hosting-Pfade (Kurzüberblick):
| Pfad | Typisch für | DNS-Ziel |
|---|---|---|
| Render (Cockpit Multi-Tenant) | Nicht-MEC / Preview | Render LB + CNAME |
| Vercel (v0 Shared/Dedicated) | v0 ohne Recast | Vercel (A / cname.vercel-dns.com) |
| Recast (Docker/GHCR) | MEC: ein GitHub-Repo pro Template, Recast pull | A-Record → Recast-Server-IP |
Die Abschnitte unten zu Vercel Go-Live und UD-Automatik gelten primär für Render/Vercel. Für MEC auf Recast siehe den eigenen Abschnitt MEC auf Recast.
Voraussetzungen (IT)
Dashboard-Umgebung (Render/Produktion):
| Variable | Zweck |
|---|---|
RENDER_API_KEY + RENDER_FRONTEND_SERVICE_ID | Cockpit-Template auf Render |
VERCEL_API_TOKEN | optional VERCEL_TEAM_ID |
UD_RESELLING_LOGIN + UD_RESELLING_PASSWORD | DNS bei UD Reseller (domainreselling.de) |
UD_DNS_API_KEY | DNS bei UD Kundenaccount (Zusatzprodukt DNS API, Format prefix.secret) |
COCKPIT_DISABLE_DNS_PROVIDER_WRITE=1 | Notfall: UD nur lesen, kein DNS-Write |
Migration: packages/database/migrations/20260531120000_add_hosting_dns_vercel_ud_SAFE.sql
v0 Team-Template (empfohlen)
Einmalig: Golden Project + v0 Team-Template + Vercel Shared Env (COCKPIT_DASHBOARD_URL, REVALIDATION_SECRET, COCKPIT_FRONTEND_CHANNEL).
Pro Center: nur bei Dedicated (1 Projekt pro Center): COCKPIT_REGISTER_TOKEN + COCKPIT_CENTER_SLUG im Vercel-Projekt — Cockpit prüft, dass Token und Slug zusammenpassen.
Shared Multi-Center (1 Vercel-Projekt, viele Domains): kein Center-Token/Slug als feste Projekt-Env. Stattdessen: COCKPIT_VERCEL_PROJECT_MODE=shared, DEFAULT_CENTER_SLUG nur für Preview, Register pro Center über Go-Live oder MCP. Details: Env-Box unter Frontend-Kanäle → Technik.
→ Schritt-für-Schritt: v0 Team-Template einrichten
Center ↔ Vercel-Projekt
| Modus | Speicherort | Wann |
|---|---|---|
| Dedicated (1 Center = 1 Projekt) | ShoppingCenter.vercelProjectId | Standard v0 pro Center |
| Shared (Multi-Center, ein Layout) | Organization.vercelProjectsByTemplate[websiteTemplate] → Fallback vercelSharedProjectId + vercelProjectMode=shared | Teil G / ein Vercel-Projekt pro Template-Familie |
IT pflegt Shared-Projekte einmalig unter Dashboard → Organisationen → Reiter Hosting (z. B. /dashboard/organizations/mec?tab=hosting). Pro MEC-Website-Template eine prj_… — im UI z. B. MEC Template Rot (mec-template-a), MEC Template Hybrid (mec-template-d), MEC Grooß (mec-template-grooss), MEC 2 (mec-template-c), MEC Grün (mec-template-green), MEC Small Assets (mec-template-small-assets). Center mit Shared-Modus brauchen keine eigene projectId — Go-Live löst automatisch aus dem Center-websiteTemplate auf.
MCP/Claude (Bulk): cockpit_bulk_center_hosting — z. B. alle Center mit MEC Template Rot (mec-template-a) auf vercel + shared und Org-Map prj_… in einem Schritt (dryRun=true zuerst).
Auflösungsreihenfolge bei shared:
- Optional:
ShoppingCenter.vercelProjectId(Center-Override) Organization.vercelProjectsByTemplate[websiteTemplate]- Fallback:
Organization.vercelSharedProjectId
Automatisch beim Deploy-Register:
- Vercel Env:
VERCEL_PROJECT_ID, optionalCOCKPIT_VERCEL_PROJECT_MODE=shared - Route
POST /api/cockpit-register→ Cockpit speichertvercelProjectIdin Meta und am Center
Manuell: Website-Management → Frontend-Kanäle (v0) oder Tab Center → Website → Aktivierung (Block „Go-Live“).
MEC auf Recast (Docker / GHCR)
Kontext: Für MEC betreiben wir pro Website-Template ein eigenes v0-GitHub-Repo (z. B. smg-mec-template-a, smg-mec-template-d, smg-mec-template-grooss). Recast hostet die fertigen Docker-Images aus GHCR — kein Vercel-Projekt pro Center, kein neues Repo pro Center.
Das entspricht Teil G (Multi-Center) in den v0-Instructions: ein Layout pro Template-Familie, viele Domains; Inhalte pro Center aus der Cockpit-API (by-domain).
Architektur (DNS vs. App)
DNS (pro Center-Domain) Recast-Server Cockpit
───────────────────── ───────────── ───────
center-a.de ──A──► Recast-IP ──► Nginx ──► Container template-a ──► by-domain?domain=center-a.de
center-b.de ──A──► Recast-IP ──► Nginx ──► Container template-a ──► Center B (gleiches Image)
center-c.de ──A──► Recast-IP ──► Nginx ──► Container template-d ──► Center C (Hybrid-Image)
- DNS entscheidet nur: Domain → Recast-Server-IP (nicht Vercel, nicht Render).
- Welches Center geladen wird, klärt die App über
GET …/api/centers/by-domain?domain={host}(Host-Header muss in Nginx durchgereicht werden). websiteTemplateim Cockpit muss zum Template-Repo/Container passen (z. B. nur Rot-Center auf demmec-template-a-Stack).
Soll-DNS pro Center-Domain (Recast)
| Record | Name | Wert |
|---|---|---|
| A | @ | IP des Recast-Root-Servers |
| A | www | gleiche IP (oder CNAME www → Apex — je nach Provider) |
Nicht nötig: Vercel-CNAME (cname.vercel-dns.com), Render-CNAME, prj_…-Registrierung bei Vercel.
Wer macht was?
| Schritt | Wer | Aktion |
|---|---|---|
| 1 | IT / Redaktion | customDomain (+ ggf. customDomains) im Cockpit — Tab Aktivierung |
| 2 | Domain-Inhaber (MEC, Center, UD) | A-Record auf Recast-IP setzen |
| 3 | Recast (Hosting-Partner) | SSL: certbot --nginx -d domain.de -d www.domain.de |
| 4 | Recast (falls mehrere Template-Container) | Nginx: Domain → richtiger Container-Port (s. unten) |
| 5 | Template-Repo (v0) | resolveCenter() / Middleware — Host → by-domain |
Neues MEC-Center (gleiches Template): Domain + Cockpit-Daten + DNS + SSL — kein neues GitHub-Repo, kein neuer GHCR-Build. Code-Update für alle Center einer Familie: ein Push im Template-Repo → GHCR → Recast pull.
Nginx auf Recast
Zwei übliche Varianten:
Variante A — ein Container pro Template (empfohlen bei mehreren Repos):
- z. B.
mec-template-a→127.0.0.1:3001,mec-template-d→127.0.0.1:3002 - Pro Domain (oder Map-Datei): Nginx leitet auf den passenden Port — abhängig vom
websiteTemplatedes Centers im Cockpit - Optional im Container:
EXPECTED_WEBSITE_TEMPLATE=mec-template-a— falsches Routing → 404 statt falsches Layout
Variante B — ein Multi-Tenant-Container (Dockerfile.center-website):
- Alle Domains → ein Port (z. B.
3000), Nginxserver_name _;mitproxy_set_header Host $host; - Siehe auch
SETUP-NOTES-for-hoster.mdim Repo-Root
Deploy-Paket für v0-Repos (ein Repo pro Template): deployment-templates/v0-recast/ — Details: v0 auf Recast (Docker).
Env auf Recast (pro Template-Container)
Für Multi-Center pro Template-Repo (Teil G):
| Variable | Pflicht | Hinweis |
|---|---|---|
NEXT_PUBLIC_DASHBOARD_URL | ja | API-Basis für Browser + Server |
REVALIDATION_SECRET | ja | identisch zum Cockpit-Dashboard |
EXPECTED_WEBSITE_TEMPLATE | empfohlen | z. B. mec-template-a |
COCKPIT_CENTER_SLUG | nein (Production) | nur Preview/Default — sonst „gewinnt“ ein Center |
COCKPIT_REGISTER_TOKEN | nein (Production Shared) | Register/URL pro Center über Cockpit/MCP, nicht als globale Container-Env |
COCKPIT_CENTER_SLUG + COCKPIT_REGISTER_TOKEN pro Stack gelten für Dedicated Recast (ein Center = ein Compose-Stack) — nicht für MEC „ein Repo pro Template, viele Domains“.
Cockpit Go-Live / UD-Automatik vs. Recast
| Feature | Render / Vercel | Recast (MEC) |
|---|---|---|
| Button Go-Live registriert Domain bei Vercel/Render | ja | nein (kein Vercel-prj_…) |
| UD-Automatik setzt CNAME/A auf Vercel/Render-Soll | ja | manuell: A auf Recast-IP (UD-Zone kann trotzdem per Hand/API gesetzt werden — Cockpit-Soll ist derzeit Render/Vercel) |
customDomain im Cockpit für by-domain | ja | ja — Pflicht |
cockpit_dns_status (Ist-DNS lesen) | ja | ja — prüft, ob Domain erreichbar ist |
| Revalidate nach Publish | ja | ja — wenn websitePublicUrl + REVALIDATION_SECRET auf Recast |
Praktisch: Domain im Cockpit speichern, DNS beim Domain-Provider auf Recast-IP umstellen, SSL auf Recast, Verbindung unter Frontend-Kanäle testen. Optional MCP: cockpit_register_frontend_deployment mit origin=https://www.center.de (AgencyOS-Key).
MEC-Template ↔ Repo (Referenz)
| Anzeigename | websiteTemplate | Typisches Repo / GHCR-Image |
|---|---|---|
| MEC Template Rot | mec-template-a | smg-mec-template-a |
| MEC Template Hybrid | mec-template-d | smg-mec-template-d |
| MEC Grooß | mec-template-grooss | smg-mec-template-grooss |
| MEC 2 | mec-template-c | smg-mec-template-c |
| MEC Grün | mec-template-green | smg-mec-template-green |
| MEC Small Assets | mec-template-small-assets | smg-mec-template-small-assets (typisch) |
Org-Reiter Hosting (vercelProjectsByTemplate) betrifft Vercel Shared — für Recast irrelevant; dort zählt die GHCR-Image-Zuordnung auf dem Server.
Siehe auch: v0 Recast Deploy, v0 Instructions Teil G, SETUP-NOTES-for-hoster.md.
Preview vs. Live (Website-URLs)
| Feld | Zweck | UD / Go-Live |
|---|---|---|
websitePublicUrlStaging | Preview / Staging (z. B. *.vercel.app, staging.…) | Nein — nur Revalidate & Verbindungstest |
websitePublicUrlProduction | Live-Origin (Custom Domain auf Vercel) | Ja — wird nach Go-Live oft automatisch gesetzt |
websitePublicUrl | Legacy (Production → Staging) | Abwärtskompatibel |
Deploy-Register: Body environment: preview | production (Vercel: VERCEL_ENV wird mitgeschickt).
Ohne environment gilt die Origin als Staging, wenn der Hostname z. B. *.vercel.app, staging.…, preview.… oder v0.… ist — sonst bei manueller Pflege das Feld Preview / Staging im Dashboard nutzen.
Migration: 20260601120000_add_website_url_staging_production_SAFE.sql (bestehende websitePublicUrl wird aufgeteilt, nicht gelöscht).
Center-Detail (Karte „Website-Technologie“), Vorschau- und SEO-Reiter: Links zur Live-Website nutzen dieselbe Logik — Production-URL aus Cockpit (websitePublicUrlProduction, Custom Domain oder Legacy websitePublicUrl). Ohne Eintrag: https://{center-slug}.cockpit-os.de (nicht mehr mallos-center-website.onrender.com/{slug}).
Ablauf Go-Live
- Custom Domain(s) im Tab Aktivierung eintragen und speichern.
- Hosting wählen: Cockpit-Template (Render) oder v0/Vercel; bei Vercel Projekt-ID / Modus setzen.
- DNS-Vorschau (Dry-Run) — zeigt geplante Schritte ohne Änderung.
- Go-Live ausführen — registriert Domain bei Render/Vercel, ersetzt abweichende A/AAAA/CNAME bei UD (
delrr+addrr), prüft Status.
UD: automatischer DNS-Umzug
Go-Live unterstützt zwei United-Domains-APIs (automatische Erkennung pro Domain):
| API | Env | Wann |
|---|---|---|
| Reseller | UD_RESELLING_* | Domain/DNS-Zone im Reseller-Portal (domainreselling.de) |
| Kunden-DNS-API | UD_DNS_API_KEY | Domain im normalen UD-Portfolio, Zusatzprodukt DNS API gebucht |
Priorität: zuerst Reseller-Zone prüfen, sonst Retail-Portfolio. Cockpit liest die Ist-Zone und vergleicht sie mit dem Soll (Render oder Vercel):
| Aktion | Wann |
|---|---|
Löschen (delrr) | Alter A, AAAA oder CNAME auf @ / www, der nicht zum Cockpit-Soll passt (z. B. alte Hoster-IP oder falscher CNAME) |
Setzen (addrr) | Fehlende Soll-Records (Render: A @ → 216.24.57.1, CNAME www → mallos-center-website.onrender.com) |
| Unberührt | MX, TXT, NS, SOA — E-Mail & Verifikationstexte bleiben erhalten |
Dry-Run listet konkret, welche Records entfernt und gesetzt würden.
GET …/dns-status zeigt unter pendingSync, was Go-Live ändern würde.
Domains nicht bei UD (anderer Nameserver): weiterhin manuelle Anleitung im Aktivierung-Tab — dort greift die UD-Automatik nicht.
API (Session):
GET /api/centers/{centerId}/dns-statusPOST /api/centers/{centerId}/go-live-domain— Body:{ "dryRun": false, "applyUdDns": true, "domains": ["beispiel.de"] }(optional:domainsfür Vorschau vor dem Speichern; sonst nur gespeicherte Domains aus der DB)
Erwartbare Fehler (kein Server-500):
| HTTP | Code | Bedeutung |
|---|---|---|
| 400 | NO_CUSTOM_DOMAINS | Keine Domain gespeichert — Tab Aktivierung ausfüllen und Website-Konfiguration speichern |
| 400 | VERCEL_PROJECT_MISSING | Vercel-Modus, aber keine projectId |
| 404 | CENTER_NOT_FOUND | Center-ID unbekannt |
| 503 | VERCEL_NOT_CONFIGURED | VERCEL_API_TOKEN fehlt in der Dashboard-Umgebung |
Fehlerbehebung (Go-Live-Schritte)
| Schritt | Meldung | Ursache / Lösung |
|---|---|---|
render:… | 401 Unauthorized | RENDER_API_KEY am Dashboard-Service (Render) ist falsch oder abgelaufen → Render → Account Settings → API Keys → neuen Key setzen |
render:… | service not found | RENDER_FRONTEND_SERVICE_ID am Dashboard-Service ist falsch (Platzhalter) → echte ID aus mallos-center-website → Settings (Format srv_…) setzen |
render:… | Key fehlt | RENDER_API_KEY und RENDER_FRONTEND_SERVICE_ID in der Dashboard-Umgebung setzen — oder Domain manuell in mallos-center-website → Custom Domains |
ud:… | Zone nicht gefunden | Domain liegt weder in UD Reseller noch im Kunden-DNS-API-Portfolio (andere Nameserver, z. B. Azure DNS) |
ud:… | fetch failed / nicht erreichbar | UD-API vom Dashboard-Server nicht erreichbar — Reseller: api.domainreselling.de, Retail: dnsapi.united-domains.de |
ud:… | CNAME is not allowed for a zonename | Apex braucht A @ → 216.24.57.1, nicht CNAME @ — nach Dashboard-Deploy Go-Live erneut ausführen |
verify | DNS/HTTPS aktiv | Domain funktioniert — Render/UD-Fehler betreffen nur die Automatisierung, nicht zwingend die Live-Website |
Test (IT): GET /api/test-env — Felder RENDER_API_TEST, UD_DNS_API_TEST (Retail), UD_RESELLING_* gesetzt.
AgencyOS / MCP:
cockpit_dns_statuscockpit_go_live_domaincockpit_register_frontend_deployment(mitvercelProjectId,vercelProjectMode)
Org Shared-Projekt (Super-Admin):
- UI: Organisation → Reiter Hosting (z. B.
/dashboard/organizations/mec?tab=hosting) GET/PATCH /api/organizations/{slug}/hosting— Body z. B.:({"vercelProjectsByTemplate": {"mec-template-green": "prj_…","mec-template-grooss": "prj_…"},"vercelSharedProjectId": "prj_…"}vercelSharedProjectIdoptional als Fallback; slug oder Org-UUID)
Redaktion: Verbindungsübersicht (Tab Aktivierung)
Bei Hosting Cockpit (Render) zeigt die Übersicht nur Cockpit-relevante Punkte — keine v0/Vercel-Zeilen. Texte sind redaktionsfreundlich formuliert; technische Details stehen unter „Technische Details“ (aufklappbar).
Bei Hosting v0/Vercel erscheinen zusätzlich Vorschau-, Live- und Sync-Status.
Redaktion: Website live (v0 + MCP)
-
Domain im Cockpit unter Center → Website → Aktivierung eintragen — oder per MCP:
cockpit_update_center_website_configmit Top-LevelcustomDomain: "example.de"(nichtcontentConfig). Beim Go-Live kann die Domain auch direkt ancockpit_publish_website_livemitgegeben werden. -
In v0 bauen; wenn fertig im Chat (mit Cockpit-MCP):
„Die Website ist fertig und soll live gehen. Domain: example.de — bitte UD prüfen und live schalten.“
-
Assistent ruft
cockpit_publish_website_liveauf (dryRun: true, dannfalse).
Im Dashboard unter Frontend-Kanäle (v0) gibt es den kopierbaren Chat-Text und einen kompakten Status (UD/DNS).
Verbindungsübersicht (Dashboard)
Im Tab Center → Website → Aktivierung und unter Website-Management → Frontend-Kanäle (v0) zeigt die Verbindungsübersicht auf einen Blick:
- Cockpit-Website aktiv, Layout-Template, Cockpit-Preview
- Custom Domain / DNS / SSL (Live)
- Hosting Render vs. Vercel, Preview-URL, Live-URL
- Auto-Update (Revalidate) nach Publish
Button Testen prüft Erreichbarkeit und Revalidate — ohne Datenbankänderung.
Abschnitt „DNS: wohin zeigt die Domain?“ (read-only, GET …/dns-status):
| Quelle | Was ausgelesen wird |
|---|---|
| Öffentlich | DNS-Lookup + HTTPS — zeigt z. B. auf Render oder Vercel |
| Vercel-API | Domain am Projekt? verified? |
| UD Reselling | QueryDNSZoneRRList — Ist-Records vs. Soll (Render/Vercel) |
Voraussetzung IT: VERCEL_API_TOKEN, UD_RESELLING_* und/oder UD_DNS_API_KEY auf dem Dashboard (Render).
Revalidate: Render (Multi-Center) vs. dedizierte v0-Live-Domain
Das Dashboard invalidiert parallel alle konfigurierten Ziele (CENTER_WEBSITE_URL + Staging/Production-URL des Centers).
| Ziel | Pfad-Modus | Beispiel |
|---|---|---|
Cockpit Center-Website auf Render (mallos-center-website…) | /{centerSlug}/… | /allen-center-trier/shops |
| Eigene v0/Vercel-Live-Domain (nur ein Center, Root-Routing) | /shops, /news, … | /shops auf alleencenter.com |
| Recast / v0 Template-Repo (MEC Multi-Center) | /shops, /news, … (Root) | /shops auf center-a.de — Center via by-domain |
Wenn die Live-Domain keine Route POST /api/revalidate mit gleichem REVALIDATION_SECRET hat, wird dieses Ziel im Log als übersprungen gemeldet — die Render-Instanz wird trotzdem aktualisiert. Für Auto-Update auf der echten Domain: Cockpit-Revalidate-Route aus dem Monorepo (apps/center-website/app/api/revalidate/route.ts) in das v0-Projekt übernehmen und Secret auf Vercel setzen.
Typische Render-Log-Meldungen (und Fix)
| Log / Symptom | Bedeutung | Maßnahme |
|---|---|---|
401 … Unauthorized auf *-preview.de / Vercel | Route existiert, Secret falsch | REVALIDATION_SECRET auf Vercel = identisch zu Render mallos-dashboard |
HTML statt JSON / SyntaxError <!DOCTYPE | Keine API-Route — Catch-all liefert Startseite | app/api/revalidate/route.ts deployen; ggf. www.-Domain im Center eintragen (Apex redirectet oft) |
skipped … 404 | Route fehlt komplett | Wie oben — Route + Secret |
✅ Revalidated … mallos-center-website.onrender.com | Cockpit-Multi-Tenant OK | Normal — externe v0-Domain ist separat zu fixen |
Im Dashboard prüfen: Center → Website-Kanäle / Aktivierung → Verbindung testen (mit Revalidate). Status „Erreichbar — Sync prüfen“ statt fälschlich „Verbunden“, bis Secret und Route passen.
Portfolio-Übersicht (System)
Was: Unter System → Domains & Go-Live (/dashboard/domains) eine read-only Tabelle aller Center mit Custom Domains, Hosting-Kanal (Render/Vercel), DNS-/SSL-Status und Link zur Aktivierung des Centers.
Warum: Kein zweites „Domain hinzufügen“ auf globaler Ebene — die UD-Reselling-API und Go-Live-Orchestrierung bleiben zentral im Aktivierung-Tab (POST …/go-live-domain, applyUdDns).
Wer ist betroffen: IT/Super Admin (Überblick), Center-Betrieb (Weiterleitung zur richtigen Center-Seite).
Wo: Sidebar System → Domains & Go-Live; pro Zeile Aktivierung → Center → Website → Reiter Aktivierung.
So testen:
/dashboard/domainsöffnen — Plattform-Badges (Render, UD Reseller, UD Retail) prüfen.- Center mit Custom Domain suchen — DNS/SSL-Badges und Live-URL prüfen.
- Prüfen klicken — ruft
POST /api/centers/{centerId}/verify-domainsauf (Status-Update, kein UD-Write). - Prüfen — Go-Live mit UD dort ausführen wie bisher.
Legacy-API: POST/DELETE /api/domains antworten mit 410 — Domains nur noch pro Center (Aktivierung) pflegen; Portfolio unter GET /api/domains/portfolio.
Hinweise
- UD-API (Reseller oder Kunden-DNS-API) setzt Records nur, wenn die DNS-Zone bei UD existiert. Abweichende A/AAAA/CNAME auf
@/wwwwerden beim Go-Live ersetzt; MX/TXT bleiben stehen. - Domains bei anderen Providern: weiterhin manuelle Anleitung im Aktivierung-Tab.
- Apex-Domains (.de): oft A-Record statt CNAME `@ — Vercel/Render-Vorgaben aus API übernehmen.
Nutzungsstatistik: Seitenaufrufe werden anonymisiert erfasst. Im Umami-Dashboard nach diesem Pfad filtern: /dashboard/go-live-dns-vercel-ud