From ecbda3f3a5d9cf76e5be3218e9c7f66fe8c6bc9a Mon Sep 17 00:00:00 2001 From: Maximilian Stubhan Date: Thu, 6 Aug 2026 15:17:24 +0200 Subject: [PATCH] Make the build fit Vercel without breaking the container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two settings were wrong for a platform build. output: "standalone" tells Next.js to emit a self-contained server, which is what the Dockerfile copies in — and what Vercel neither needs nor expects, since it builds and packages the app itself. It is now conditional on the VERCEL variable, which every build there sets, so each path gets what it wants. Verified both ways: with VERCEL=1 no standalone directory appears, without it one does. /api/import declared maxDuration = 120. The free tier caps at 60 and refuses anything higher, so the deployment would have failed on a value chosen for a self-hosted server. Lowered, with the reason and the Pro ceiling written next to it. DEPLOYMENT.md now covers both paths, and says plainly that the repository cannot be connected: git.elycon.solutions is self-hosted, and Vercel's git integration only speaks GitHub, GitLab and Bitbucket. Deploying from the workstation with the CLI works with any repository and is the shorter road; mirroring to GitHub is written down as the alternative, with its cost — two remotes to keep in step. Co-Authored-By: Claude Opus 5 --- DEPLOYMENT.md | 71 ++++++++++++++++++++++++++++++++++++++--- app/api/import/route.ts | 6 +++- next.config.ts | 8 +++-- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index efb76d2..6109f59 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -1,8 +1,71 @@ -# Deployment mit Docker +# Deployment -Dieser Guide beschreibt, wie die App (bisher auf Vercel deployed, siehe -`vercel.json`) stattdessen als Docker-Container auf einem beliebigen Server -läuft. +Zwei Wege, beide unterstützt. Das Abbild ist umgebungsneutral — es gibt keine +Werte mehr, die beim Bauen eingebacken werden —, ein Wechsel ist also +jederzeit möglich. + +| | passt, wenn | +|---|---| +| [Vercel](#vercel) | ihr nichts betreiben wollt; schnellster Weg | +| [Docker](#deployment-mit-docker) | es in eure eigene Infrastruktur soll | + +**In beiden Fällen gleich:** die Umgebungsvariablen aus [Abschnitt 1](#1-env-anlegen), +die Umleitungs-URI in der Entra-Registrierung, und dass eine neue Person nach +ihrer ersten Anmeldung eine `profiles`-Zeile braucht (siehe +[docs/entra-sso.md](docs/entra-sso.md)). + +## Vercel + +Das Repository liegt auf `git.elycon.solutions` — einem selbst betriebenen +Git. **Vercels Git-Anbindung kann nur GitHub, GitLab und Bitbucket**, dieses +Repository lässt sich dort also nicht verknüpfen. Zwei Möglichkeiten: + +### a) Von der Arbeitsstation ausrollen (ohne GitHub) + +```bash +npx vercel login +npx vercel link +npx vercel --prod +``` + +Funktioniert mit jedem Repository. Der Preis: kein automatisches Ausrollen +bei einem Push — jede Veröffentlichung ist ein bewusster Befehl. Für zwei +Personen ist das eher Vorteil als Nachteil. + +### b) Zusätzlich nach GitHub spiegeln + +```bash +git remote add github git@github.com:/alpenwerk-hr.git +git push github feat/sap-om-org-model +``` + +Danach das GitHub-Repository in Vercel verbinden. Ab dann rollt jeder Push +aus. Zwei Fernziele bedeuten aber auch: beide müssen gepflegt werden. + +### Danach + +1. **Umgebungsvariablen** im Vercel-Projekt setzen (Settings → Environment + Variables), dieselben wie in [Abschnitt 1](#1-env-anlegen). `AUTH_URL` ist + nicht nötig, Vercel setzt den Host selbst. +2. **Umleitungs-URI** in der Entra-Registrierung ergänzen: + `https://.vercel.app/api/auth/callback/microsoft-entra-id` +3. Der nächtliche Lauf ist über `vercel.json` bereits eingerichtet. + +Zwei Eigenheiten der Plattform, die im Code berücksichtigt sind: +`output: "standalone"` entfällt dort automatisch (Vercel baut selbst), und +`/api/import` ist auf 60 Sekunden begrenzt — die Obergrenze des kostenlosen +Tarifs. Im Pro-Tarif liessen sich 300 setzen, falls eine Importdatei mit +vielen tausend Zeilen ansteht. + +Der Verbindungspool passt zu serverlosen Aufrufen, **weil** `DATABASE_URL` +auf den Transaktions-Modus zeigt (Port 6543). Mit dem Sitzungs-Modus wären +die 15 Verbindungen des Tarifs nach wenigen gleichzeitigen Aufrufen +verbraucht. + +## Deployment mit Docker + +Dieser Guide beschreibt, wie die App stattdessen als Docker-Container auf +einem beliebigen Server läuft. ## Was wird containerisiert – und was nicht diff --git a/app/api/import/route.ts b/app/api/import/route.ts index 51e198e..ee88a57 100644 --- a/app/api/import/route.ts +++ b/app/api/import/route.ts @@ -25,7 +25,11 @@ class Rueckabwicklung extends Error { } } -export const maxDuration = 120; +// 60 Sekunden, weil das die Obergrenze im kostenlosen Vercel-Tarif ist — +// ein höherer Wert lässt sich dort nicht ausrollen. Auf einem eigenen Server +// gilt die Angabe ohnehin nicht, und im Pro-Tarif liesse sie sich auf 300 +// heben, falls eine Datei mit vielen tausend Zeilen ansteht. +export const maxDuration = 60; type Antwort = { ok: boolean; diff --git a/next.config.ts b/next.config.ts index 2c459e4..26231ff 100644 --- a/next.config.ts +++ b/next.config.ts @@ -44,8 +44,12 @@ function contentSecurityPolicy(): string { const nextConfig: NextConfig = { // Emits a self-contained .next/standalone server (only the deps actually - // used at runtime, no full node_modules) - what the Dockerfile copies in. - output: "standalone", + // used at runtime, no full node_modules) — what the Dockerfile copies in. + // + // Auf Vercel ist das falsch: dort baut die Plattform selbst und erwartet + // die übliche Ausgabe. `VERCEL` setzt sie in jeder Baustrecke, die Angabe + // entfällt dort also von selbst — und der Docker-Weg bleibt unberührt. + output: process.env.VERCEL ? undefined : "standalone", // Baseline security headers (clickjacking, MIME-sniffing, referrer leakage, // browser feature access) plus the report-only CSP described above. async headers() {