Zum Hauptinhalt springen

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):

PfadTypisch fürDNS-Ziel
Render (Cockpit Multi-Tenant)Nicht-MEC / PreviewRender LB + CNAME
Vercel (v0 Shared/Dedicated)v0 ohne RecastVercel (A / cname.vercel-dns.com)
Recast (Docker/GHCR)MEC: ein GitHub-Repo pro Template, Recast pullA-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):

VariableZweck
RENDER_API_KEY + RENDER_FRONTEND_SERVICE_IDCockpit-Template auf Render
VERCEL_API_TOKENoptional VERCEL_TEAM_ID
UD_RESELLING_LOGIN + UD_RESELLING_PASSWORDDNS bei UD Reseller (domainreselling.de)
UD_DNS_API_KEYDNS bei UD Kundenaccount (Zusatzprodukt DNS API, Format prefix.secret)
COCKPIT_DISABLE_DNS_PROVIDER_WRITE=1Notfall: 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

ModusSpeicherortWann
Dedicated (1 Center = 1 Projekt)ShoppingCenter.vercelProjectIdStandard v0 pro Center
Shared (Multi-Center, ein Layout)Organization.vercelProjectsByTemplate[websiteTemplate] → Fallback vercelSharedProjectId + vercelProjectMode=sharedTeil 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:

  1. Optional: ShoppingCenter.vercelProjectId (Center-Override)
  2. Organization.vercelProjectsByTemplate[websiteTemplate]
  3. Fallback: Organization.vercelSharedProjectId

Automatisch beim Deploy-Register:

  • Vercel Env: VERCEL_PROJECT_ID, optional COCKPIT_VERCEL_PROJECT_MODE=shared
  • Route POST /api/cockpit-register → Cockpit speichert vercelProjectId in 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).
  • websiteTemplate im Cockpit muss zum Template-Repo/Container passen (z. B. nur Rot-Center auf dem mec-template-a-Stack).

Soll-DNS pro Center-Domain (Recast)

RecordNameWert
A@IP des Recast-Root-Servers
Awwwgleiche 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?

SchrittWerAktion
1IT / RedaktioncustomDomain (+ ggf. customDomains) im Cockpit — Tab Aktivierung
2Domain-Inhaber (MEC, Center, UD)A-Record auf Recast-IP setzen
3Recast (Hosting-Partner)SSL: certbot --nginx -d domain.de -d www.domain.de
4Recast (falls mehrere Template-Container)Nginx: Domain → richtiger Container-Port (s. unten)
5Template-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-a127.0.0.1:3001, mec-template-d127.0.0.1:3002
  • Pro Domain (oder Map-Datei): Nginx leitet auf den passenden Port — abhängig vom websiteTemplate des 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), Nginx server_name _; mit proxy_set_header Host $host;
  • Siehe auch SETUP-NOTES-for-hoster.md im 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):

VariablePflichtHinweis
NEXT_PUBLIC_DASHBOARD_URLjaAPI-Basis für Browser + Server
REVALIDATION_SECRETjaidentisch zum Cockpit-Dashboard
EXPECTED_WEBSITE_TEMPLATEempfohlenz. B. mec-template-a
COCKPIT_CENTER_SLUGnein (Production)nur Preview/Default — sonst „gewinnt“ ein Center
COCKPIT_REGISTER_TOKENnein (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

FeatureRender / VercelRecast (MEC)
Button Go-Live registriert Domain bei Vercel/Renderjanein (kein Vercel-prj_…)
UD-Automatik setzt CNAME/A auf Vercel/Render-Solljamanuell: 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-domainjaja — Pflicht
cockpit_dns_status (Ist-DNS lesen)jaja — prüft, ob Domain erreichbar ist
Revalidate nach Publishjaja — 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)

AnzeigenamewebsiteTemplateTypisches Repo / GHCR-Image
MEC Template Rotmec-template-asmg-mec-template-a
MEC Template Hybridmec-template-dsmg-mec-template-d
MEC Grooßmec-template-groosssmg-mec-template-grooss
MEC 2mec-template-csmg-mec-template-c
MEC Grünmec-template-greensmg-mec-template-green
MEC Small Assetsmec-template-small-assetssmg-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)

FeldZweckUD / Go-Live
websitePublicUrlStagingPreview / Staging (z. B. *.vercel.app, staging.…)Nein — nur Revalidate & Verbindungstest
websitePublicUrlProductionLive-Origin (Custom Domain auf Vercel)Ja — wird nach Go-Live oft automatisch gesetzt
websitePublicUrlLegacy (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

  1. Custom Domain(s) im Tab Aktivierung eintragen und speichern.
  2. Hosting wählen: Cockpit-Template (Render) oder v0/Vercel; bei Vercel Projekt-ID / Modus setzen.
  3. DNS-Vorschau (Dry-Run) — zeigt geplante Schritte ohne Änderung.
  4. 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):

APIEnvWann
ResellerUD_RESELLING_*Domain/DNS-Zone im Reseller-Portal (domainreselling.de)
Kunden-DNS-APIUD_DNS_API_KEYDomain 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):

AktionWann
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 wwwmallos-center-website.onrender.com)
UnberührtMX, 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-status
  • POST /api/centers/{centerId}/go-live-domain — Body: { "dryRun": false, "applyUdDns": true, "domains": ["beispiel.de"] } (optional: domains für Vorschau vor dem Speichern; sonst nur gespeicherte Domains aus der DB)

Erwartbare Fehler (kein Server-500):

HTTPCodeBedeutung
400NO_CUSTOM_DOMAINSKeine Domain gespeichert — Tab Aktivierung ausfüllen und Website-Konfiguration speichern
400VERCEL_PROJECT_MISSINGVercel-Modus, aber keine projectId
404CENTER_NOT_FOUNDCenter-ID unbekannt
503VERCEL_NOT_CONFIGUREDVERCEL_API_TOKEN fehlt in der Dashboard-Umgebung

Fehlerbehebung (Go-Live-Schritte)

SchrittMeldungUrsache / Lösung
render:…401 UnauthorizedRENDER_API_KEY am Dashboard-Service (Render) ist falsch oder abgelaufen → Render → Account Settings → API Keys → neuen Key setzen
render:…service not foundRENDER_FRONTEND_SERVICE_ID am Dashboard-Service ist falsch (Platzhalter) → echte ID aus mallos-center-website → Settings (Format srv_…) setzen
render:…Key fehltRENDER_API_KEY und RENDER_FRONTEND_SERVICE_ID in der Dashboard-Umgebung setzen — oder Domain manuell in mallos-center-website → Custom Domains
ud:…Zone nicht gefundenDomain liegt weder in UD Reseller noch im Kunden-DNS-API-Portfolio (andere Nameserver, z. B. Azure DNS)
ud:…fetch failed / nicht erreichbarUD-API vom Dashboard-Server nicht erreichbar — Reseller: api.domainreselling.de, Retail: dnsapi.united-domains.de
ud:…CNAME is not allowed for a zonenameApex braucht A @ → 216.24.57.1, nicht CNAME @ — nach Dashboard-Deploy Go-Live erneut ausführen
verifyDNS/HTTPS aktivDomain 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_status
  • cockpit_go_live_domain
  • cockpit_register_frontend_deployment (mit vercelProjectId, 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_…"
    }
    (vercelSharedProjectId optional 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)

  1. Domain im Cockpit unter Center → Website → Aktivierung eintragen — oder per MCP: cockpit_update_center_website_config mit Top-Level customDomain: "example.de" (nicht contentConfig). Beim Go-Live kann die Domain auch direkt an cockpit_publish_website_live mitgegeben werden.

  2. 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.“

  3. Assistent ruft cockpit_publish_website_live auf (dryRun: true, dann false).

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):

QuelleWas ausgelesen wird
ÖffentlichDNS-Lookup + HTTPS — zeigt z. B. auf Render oder Vercel
Vercel-APIDomain am Projekt? verified?
UD ResellingQueryDNSZoneRRList — 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).

ZielPfad-ModusBeispiel
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 / SymptomBedeutungMaßnahme
401 … Unauthorized auf *-preview.de / VercelRoute existiert, Secret falschREVALIDATION_SECRET auf Vercel = identisch zu Render mallos-dashboard
HTML statt JSON / SyntaxError <!DOCTYPEKeine API-Route — Catch-all liefert Startseiteapp/api/revalidate/route.ts deployen; ggf. www.-Domain im Center eintragen (Apex redirectet oft)
skipped … 404Route fehlt komplettWie oben — Route + Secret
✅ Revalidated … mallos-center-website.onrender.comCockpit-Multi-Tenant OKNormal — 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 SystemDomains & Go-Live; pro Zeile Aktivierung → Center → Website → Reiter Aktivierung.

So testen:

  1. /dashboard/domains öffnen — Plattform-Badges (Render, UD Reseller, UD Retail) prüfen.
  2. Center mit Custom Domain suchen — DNS/SSL-Badges und Live-URL prüfen.
  3. Prüfen klicken — ruft POST /api/centers/{centerId}/verify-domains auf (Status-Update, kein UD-Write).
  4. 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 @/www werden 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