gooddeploy
Handbuch · Kapitel 15

Umzug von Vercel

Schritt für Schritt von Vercel zu gooddeploy: Next.js-App mit Postgres und eigener Domain, ohne dass die Seite ausfällt. Vercel läuft weiter, bis bei gooddeploy alles geprüft ist; am Ende steht eine Checkliste zum Abhaken.

Überblick

So läuft der Umzug eines Projekts ab:

  1. Zugang und CLI einrichten,
  2. Projekt vorbereiten,
  3. Variablen von Vercel übernehmen,
  4. Datenbank wählen: Postgres bei gooddeploy oder die bisherige behalten,
  5. erstes Deploy und prüfen,
  6. Kunden abnehmen lassen,
  7. live schalten,
  8. eigene Domain umstellen,
  9. Vercel abschalten, erst wenn alles läuft.

Bis Schritt 8 ändert sich für Besucher nichts: Die Domain zeigt weiter auf Vercel. Hast du viele kleine Seiten, ziehst du sie einzeln um, eine nach der anderen; jede bekommt ein eigenes gooddeploy-Projekt.

1. Zugang und CLI

In der Pilotphase richtet goodDEV deinen Zugang ein: Schreib an gooddeploy@gooddev.de, du bekommst einen Zugang für deine E-Mail-Adresse in einem Team. Selbst registrieren geht noch nicht.

curl -fsSL https://gooddeploy.de/install.sh | sh
gooddeploy version
gooddeploy login --email du@agentur.de
gooddeploy whoami

Für den Umzug brauchst du mindestens Version 0.0.3-alpha.3 (wegen env import); eine ältere holst du mit gooddeploy update. login zeigt einen Code und schickt dir eine E-Mail mit einem Link; dort gibst du den Code ein. Alles Weitere unter Testzugang. Betreust du Projekte in mehreren Teams (z. B. ein Team je Kunde), meldest du dich mit --team "<Name>" für das richtige Team an (siehe Mehrere Teams).

Für Schritt 3 brauchst du außerdem die Vercel-CLI, angemeldet und mit dem Vercel-Projekt verknüpft (vercel link im Projektordner).

2. Projekt vorbereiten

gooddeploy baut genau den letzten Commit (HEAD), nicht deine Arbeitskopie. Prüfe im Projektordner:

  • Alles ist committet, das Lockfile auch (package-lock.json, pnpm-lock.yaml oder yarn.lock).
  • next build und danach next start laufen lokal ohne Fehler.
  • Die Node-Version steht in engines.node der package.json.
  • Keine Git-Submodule und kein Git LFS; Bun als Paketmanager geht noch nicht (siehe Was gebaut werden kann).

Next.js

  • Setze in der next.config output: "standalone": kleineres Image, schnellerer Start. Ohne läuft die App auch, deploy weist dich dann mit ⚠ darauf hin.
  • Migrationen: gooddeploy startet die App mit node server.js, nicht mit npm start. Ein start-Skript wie prisma migrate deploy && next start läuft deshalb nicht. Sollen Migrationen beim Start laufen, geht das heute mit einer eigenen server.js, dann aber ohne output: "standalone". Wie das geht, steht unter Migrationen ausrollen.
  • Build-Variablen: NEXT_PUBLIC_… werden beim Build in das JavaScript eingebaut. Sie müssen in Previews und Live gleich sein, sonst lehnt promote ab (BUILD_ENV_MISMATCH). Unterscheiden sie sich bei Vercel (z. B. NEXT_PUBLIC_SITE_URL), wähle für beide Umgebungen denselben Wert oder lies die Adresse zur Laufzeit.
  • Seiten, die beim Build die Datenbank abfragen, brechen ab: Beim Build gibt es keine Datenbank. Mach sie dynamisch (siehe Häufige Fehler).
  • Weiterleitungen: Stehen in deiner vercel.json redirects, zieh sie in die redirects() der next.config um; die gelten bei gooddeploy unverändert. Für statische Seiten (auch Next.js mit output: "export") übernimmst du sie in die gooddeploy.json, siehe Weiterleitungen.
  • Vercel-eigene Dienste wie Vercel Blob, Global Config (früher Edge Config), Web Analytics oder Cron-Jobs aus vercel.json gibt es bei gooddeploy nicht. Schreib sie auf eine Liste und kläre vorher, wie du sie ersetzt (siehe Was es noch nicht gibt).

Große Dateien ausschließen

Agentur-Repos enthalten oft Dateien, die die Seite nicht braucht. Über 100 MB (komprimiert) lehnt gooddeploy den Upload ab. Leg eine .gooddeployignore im Projekt-Root an, gleiche Syntax wie .gitignore:

docs/
design/
*.psd
*.fig
**/raw/
*.mov
git add .gooddeployignore
git commit -m "gooddeploy: große Dateien beim Upload weglassen"

Die Datei muss committet sein, gooddeploy liest sie aus dem Commit. Details unter Große Dateien ausschließen.

3. Variablen von Vercel übernehmen

Zuerst verknüpfst du den Ordner mit einem neuen gooddeploy-Projekt. Ob du dabei Postgres anlegst, entscheidest du in Schritt 4; lies ihn also vorher.

gooddeploy link kunde-website

link fragt, ob es das Projekt anlegen soll, und danach „Postgres anlegen?“. Projektnamen haben 3 bis 30 Zeichen: Kleinbuchstaben, Ziffern, Bindestriche.

Dann holst du die Variablen je Umgebung von Vercel und übernimmst sie. Ohne --environment holt vercel env pull die Werte für Development, deshalb gibst du die Umgebung immer an (Quelle: Quellen zu Vercel):

vercel env pull --environment=production .env.vercel-production
gooddeploy env import .env.vercel-production --production

vercel env pull --environment=preview .env.vercel-preview
gooddeploy env import .env.vercel-preview --preview

rm .env.vercel-production .env.vercel-preview

Nimm je Umgebung eine eigene, neue Datei: Gibt es die Datei schon, ergänzt vercel env pull sie nur, und Werte der anderen Umgebung blieben stehen. Sind die Werte in beiden Umgebungen gleich, reicht ein Import mit --both. env import zeigt vorher nur die Namen, nie die Werte, und fragt, bevor es etwas setzt:

  Aus .env.vercel-production nach kunde-website (Live), nur Namen:
  API_URL:              neu
  STRIPE_SECRET_KEY:    neu
  NEXT_PUBLIC_SITE_URL: neu, Build-Variable
  DATABASE_URL:         übersprungen: setzt gooddeploy für die eigene Datenbank; eine externe einzeln mit gooddeploy env add DATABASE_URL
  VERCEL_OIDC_TOKEN:    übersprungen: Variable von Vercel
? 3 Variable(n) in kunde-website setzen? (J/n)
✓ 3 Variable(n) aus .env.vercel-production in kunde-website gesetzt

Übersprungen werden mit Hinweis:

WasWarumWas du tust
DATABASE_URL, DATABASE_URL_UNPOOLEDgooddeploy setzt sie für die eigene Datenbanknichts, oder bei externer Datenbank einzeln setzen (Schritt 4)
VERCEL, VERCEL_…, TURBO_…Variablen von Vercel selbst, bei gooddeploy ohne Bedeutungnichts; nutzt dein Code z. B. VERCEL_URL, ersetze es durch eine eigene Variable
PORT, NODE_ENV, HOSTNAME, GOODDEPLOY_…setzt gooddeploy selbstnichts
mehrzeilige Werte (z. B. private Schlüssel)gooddeploy unterstützt sie noch nichtBase64-kodiert in einer Zeile setzen und in der App dekodieren
leere Werte, ungültige NamenNamen nur aus A-Z, 0-9 und _prüfen, ob du sie brauchst

Einen mehrzeiligen Wert setzt du so (hier ein Schlüssel aus einer Datei, macOS und Linux):

base64 < private-key.pem | tr -d '\n' | gooddeploy env add PRIVATE_KEY_BASE64 --both

In der App: Buffer.from(process.env.PRIVATE_KEY_BASE64 ?? "", "base64").toString("utf8").

Achtung, geheime Werte bei Vercel: Variablen vom Typ „Secret“ (früher „Sensitive“) gibt Vercel nach dem Speichern nicht mehr heraus, und legst du Variablen für Production oder Preview mit der Vercel-CLI an, ist „Secret“ der Standard. Rechne also damit, dass viele Werte fehlen: vercel env pull schreibt für sie einen Platzhalter statt des echten Werts in die neue Datei (siehe Quellen zu Vercel). env import erkennt solche Platzhalter nicht und würde sie übernehmen. Sieh dir die Dateien deshalb vor dem Import an und lösch die Zeilen ohne echten Wert. Diese Variablen setzt du einzeln mit gooddeploy env add NAME --both aus deinem Passwortmanager oder dem Konto des jeweiligen Dienstes.

Prüfen, was angekommen ist (Werte maskiert):

gooddeploy env ls

Alles zu den Befehlen unter Umzug von Vercel: env import. Lösch die Dateien nach dem Import; sie enthalten deine Geheimnisse und gehören nie ins Git.

4. Datenbank

Du hast zwei Wege. Entscheide vor gooddeploy link, denn Postgres legst du derzeit nur beim Anlegen des Projekts selbst an; nachträglich richtet goodDEV sie für dich ein.

Weg A: Postgres bei gooddeploy

Beim Anlegen „Postgres anlegen?“ mit Enter bestätigen (im Skript: gooddeploy link kunde-website --yes --postgres). Deine App bekommt dann bei jedem Start DATABASE_URL (über einen Verbindungs-Pool) und DATABASE_URL_UNPOOLED (für Migrationen), dieselben Namen wie bei Vercel und Neon. Live hat eine eigene Datenbank, alle Previews teilen sich eine zweite. Prisma und Drizzle einrichten: Datenbank in deiner App nutzen.

Daten übernehmen: Die Datenbank bei gooddeploy ist nur aus deiner App erreichbar, nicht von deinem Rechner, und einen Befehl zum Einspielen einer Sicherung gibt es noch nicht (kommt später, ebenso ein Umzug direkt aus der alten Datenbank in einem Schritt). Bis dahin spielt goodDEV deine Daten ein.

Zieh eine Sicherung der bisherigen Datenbank im Format von pg_dump -Fc:

pg_dump -Fc "<bisherige Verbindungs-URL>" -f kunde-website.dump
  • Nimm dafür die direkte Adresse ohne Pool (bei Neon die URL ohne -pooler). Dein pg_dump sollte mindestens die Hauptversion der Quelle haben; bei gooddeploy läuft Postgres 17.
  • Gib die Datei sicher an goodDEV, nicht als E-Mail-Anhang; den Weg sprechen wir mit dir ab. Wir spielen sie in die Live-Datenbank ein und sagen dir Bescheid.
  • Plane dafür einen Zeitpunkt, an dem auf der alten Seite niemand Daten ändert, oder gleiche später ab. Alles, was nach dem Dump bei Vercel geschrieben wird, fehlt sonst bei gooddeploy.

Prüfen kannst du danach mit gooddeploy db info (Größe, Verbindungen) und gooddeploy db dump -o kontrolle.dump (Sicherung der Live-Datenbank herunterladen). Automatische Backups gibt es in der Testphase noch nicht: Sichere wichtige Daten selbst mit gooddeploy db dump.

Weg B: bisherige Datenbank behalten

Nutzt du Neon, Supabase oder eine andere externe Postgres-Datenbank, kann sie bleiben. Antworte bei „Postgres anlegen?“ mit n und setze die Adresse selbst, je Umgebung (Eingabe verdeckt):

gooddeploy env add DATABASE_URL --production
gooddeploy env add DATABASE_URL --preview

Brauchen deine Migrationen eine direkte Adresse ohne Pool, setze DATABASE_URL_UNPOOLED genauso. Nimm für Previews eine eigene Datenbank oder einen eigenen Zweig, nicht die Live-Datenbank. Ob die App die Datenbank erreicht, siehst du an der ersten Preview (Seite mit Daten öffnen, sonst gooddeploy logs <id>). Lässt dein Anbieter nur bestimmte IP-Adressen zu, frag goodDEV. Der Vertrag für die Datenbank bleibt beim jeweiligen Anbieter. Ein eigener Befehl, der eine externe Datenbank anbindet und die Verbindung prüft, kommt später; bis dahin geht es mit env add.

5. Erstes Deploy

gooddeploy deploy

gooddeploy lädt den letzten Commit hoch, baut ihn, startet die App und prüft, ob sie antwortet. Previews sind geschützt; deploy erzeugt dir deshalb gleich einen Freigabelink, der 1 Tag gilt:

✓ Preview bereit nach 48 s
  Die Preview ist geschützt. Der Freigabelink ist für dich zum Ansehen.
  Öffnen:        https://kunde-website--k7m2q9xa.…/__gooddeploy/share#… (Freigabelink, 1 Tag gültig)
  Preview:       https://kunde-website--k7m2q9xa.…
  Live schalten: gooddeploy promote k7m2q9xa
  Für Kunden:    gooddeploy share k7m2q9xa --days 7

Öffne den Link und klick die wichtigen Seiten durch: Startseite, Formulare, Login, Seiten mit Daten aus der Datenbank. Zur Kontrolle:

gooddeploy inspect k7m2q9xa       # Status, Adressen, Namen der Variablen, Checks
gooddeploy logs k7m2q9xa          # Laufzeit-Logs der Preview
gooddeploy logs k7m2q9xa --build  # Build-Log

Ohne ID zeigt gooddeploy inspect das Live-Deployment, vor dem ersten promote das neueste, jeweils mit den Namen der Variablen je Umgebung. Bricht der Build ab, nennt gooddeploy Code und Grund; die häufigsten stehen unter Häufige Fehler.

Fehlt eine Variable, setze sie und deploye neu. Eine Laufzeit-Variable wirkt mit --apply sofort, ohne neuen Build:

gooddeploy env add API_URL --preview --apply

6. Kunden abnehmen lassen

Für die Abnahme bekommt dein Kunde einen eigenen Link, ohne Konto und ohne Passwort:

gooddeploy share k7m2q9xa --days 7

Der Link gilt 1 bis 30 Tage (Standard 7). Alle Links des Projekts widerrufst du mit gooddeploy share revoke. Mehr unter Freigabelink.

7. Live schalten

Gefällt der Stand, schalte genau dieses Deployment live, ohne Neubau:

gooddeploy promote k7m2q9xa

gooddeploy zeigt vorher, was live geht, und fragt nach. Danach ist die App unter der Projekt-Adresse live (z. B. https://kunde-website.…, steht in der Ausgabe); deine Domain zeigt bis Schritt 8 weiter auf Vercel. Nach dem Umschalten prüft gooddeploy die neue Version noch eine Weile und schaltet bei Fehlern von selbst zurück. Abwarten kannst du das mit gooddeploy promote k7m2q9xa --wait.

Stimmt etwas nicht, geht es in Sekunden zurück:

gooddeploy rollback

rollback tauscht nur den Code, nie die Daten. Hast du Migrationen eingespielt, muss die ältere Version mit dem neuen Schema zurechtkommen. gooddeploy status zeigt, was live ist und wohin rollback zurückschaltet. Alles dazu: Deploy, Preview, Promote, Rollback.

Hast du die Daten erst nach dem ersten promote eingespielt (Weg A), prüf die Live-Seite danach noch einmal.

8. Eigene Domain

Eigene Domains richtet in der Pilotphase goodDEV für dich ein; selbst per CLI kommt später. So läuft es:

  1. Schreib uns, welche Domains zum Projekt gehören (z. B. kunde.de und www.kunde.de) und welche die Hauptdomain sein soll. Die anderen leiten mit 301 auf sie weiter.
  2. Senke bei deinem Domain-Anbieter einen Tag vorher die TTL der betroffenen Einträge (z. B. auf 300 Sekunden), dann geht die Umstellung schneller und ein Rückweg auch.
  3. goodDEV trägt die Domains ein und nennt dir die DNS-Einträge, die du beim Domain-Anbieter deines Kunden setzt. Erst damit zeigt die Domain auf gooddeploy.
  4. Prüfe die Seite unter der Domain im Browser, mit https://. gooddeploy status zeigt die Domains des Projekts.

Hat dein Kunde die Domain bei Vercel registriert oder nutzt er die DNS-Server von Vercel, kläre vorher, wo die Einträge künftig gepflegt werden. E-Mail-Einträge (MX, SPF, DKIM) der Domain bleiben, wie sie sind; nimm sie bei einem Umzug der DNS-Verwaltung mit.

Die Projekt-Adresse bei gooddeploy bleibt erreichbar, sendet aber noindex, damit Suchmaschinen nur deine Domain führen (siehe Eigene Domains).

9. Vercel abschalten

Schalte das Vercel-Projekt erst ab, wenn die Seite unter der eigenen Domain von gooddeploy kommt und eine Weile ohne Fehler läuft. Bis dahin ist der Weg zurück offen: DNS-Einträge zurück auf Vercel.

Vor dem Abschalten:

  • Die Domain zeigt überall auf gooddeploy (auch für www und weitere Domains), und die alte TTL ist abgelaufen.
  • gooddeploy logs --since 1h zeigt keine unerwarteten Fehler.
  • Daten, die nach dem Dump bei Vercel noch geschrieben wurden, sind übernommen.
  • Vercel-eigene Dienste (Blob, Cron, Analytics) sind ersetzt oder bewusst weggefallen.
  • Webhooks und Rückruf-Adressen bei anderen Diensten (Zahlung, Login, Formulare) zeigen auf die neue Domain bzw. funktionieren damit.
  • Eine aktuelle Sicherung liegt bei dir: gooddeploy db dump -o nach-umzug.dump (Weg A) oder beim bisherigen Anbieter (Weg B).

Danach im Vercel-Projekt die Domain entfernen und das Projekt löschen oder pausieren. Nutzt du bei Vercel eine Datenbank aus dem Marketplace und bist mit Weg A umgezogen, kündige sie beim jeweiligen Anbieter erst nach deiner letzten Sicherung.

Was es noch nicht gibt

gooddeploy ist in der Pilotphase. Für den Umzug wichtig, und laut Plan für den Pilot vorgesehen (kommt später, ohne festen Termin):

  • Vorschau bei jedem Push aus GitHub und live per Merge. Heute deployst du per Befehl, auch aus deiner CI (siehe Skripte und CI).
  • Dashboard im Browser mit Deployments und Logs. Heute läuft alles über die CLI.
  • Cron-Jobs aus vercel.json. Bis dahin ruft z. B. deine CI oder ein anderer Dienst den Pfad im Takt auf.
  • Eigene Domains selbst einrichten (domains add). Heute richtet goodDEV sie ein.
  • Migrationen einmal je Live-Schalten (release-Befehl). Heute über eine eigene Startdatei (siehe Migrationen ausrollen).
  • Sicherung selbst einspielen bzw. Daten direkt aus der alten Datenbank übernehmen, und automatische Backups der Datenbanken. Heute hilft goodDEV.
  • Externe Datenbank per Befehl anbinden (z. B. Neon oder Supabase). Heute mit gooddeploy env add DATABASE_URL.

Nicht geplant sind ein Ersatz für Vercel Blob, Global Config und Web Analytics sowie Edge Functions an weltweiten Standorten.

Checkliste

Zum Abhaken, je Projekt:

  • Zugang von goodDEV, CLI installiert, gooddeploy login und whoami ok
  • Vercel-eigene Dienste (Blob, Cron, Analytics, Global Config) aufgelistet und Ersatz geklärt
  • next build und next start laufen lokal, alles committet, Lockfile dabei
  • output: "standalone" gesetzt, oder ohne standalone mit eigener server.js, wenn Migrationen beim Start laufen sollen
  • .gooddeployignore für große Dateien committet
  • redirects aus der vercel.json in die next.config bzw. die gooddeploy.json übernommen
  • Datenbank entschieden: Postgres bei gooddeploy oder bisherige behalten
  • gooddeploy link <projekt> (mit oder ohne Postgres)
  • Variablen je Umgebung mit vercel env pull --environment=… und gooddeploy env import übernommen, Dateien gelöscht
  • Secret-Werte, mehrzeilige Werte und ggf. DATABASE_URL einzeln gesetzt, gooddeploy env ls geprüft
  • NEXT_PUBLIC_… in Previews und Live gleich
  • Daten übernommen (Dump an goodDEV) oder externe Datenbank verbunden
  • gooddeploy deploy, Preview durchgeklickt, inspect und logs ohne Fehler
  • Kunde hat über gooddeploy share <id> --days 7 abgenommen
  • gooddeploy promote <id>, Live-Adresse geprüft, rollback bekannt
  • TTL gesenkt, Domains an goodDEV gemeldet, DNS-Einträge gesetzt, Seite unter der Domain mit HTTPS geprüft
  • Webhooks und Rückruf-Adressen angepasst, letzte Sicherung gezogen
  • Vercel-Projekt abgeschaltet

Quellen zu Vercel

Angaben zur Vercel-CLI aus der Doku von Vercel, abgerufen am 22.10.2026: vercel env (https://vercel.com/docs/cli/env) und Config- und Secret-Variablen (https://vercel.com/docs/environment-variables/sensitive-environment-variables). Vercel ist eine Marke der Vercel Inc.