From 586ed51a6a58742ccd9250456eefc6191c113a39 Mon Sep 17 00:00:00 2001 From: dimitar Date: Mon, 3 Aug 2026 20:15:56 +0200 Subject: [PATCH] docs: capture CSP/build-variable and admin-login gotchas in Coolify guide --- docs/coolify.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/docs/coolify.md b/docs/coolify.md index a9f1465..3b97f72 100644 --- a/docs/coolify.md +++ b/docs/coolify.md @@ -159,8 +159,15 @@ NODE_ENV=production `SUPER_ADMIN_PASSWORD_HASH`, `S3_*`) stay as normal runtime variables. - The `super` admin row is provisioned automatically on container start by `scripts/start.sh` (`node prisma/seed.cjs` after migrations). If you instead - use a custom Nixpacks start command (Option A below), run the seed manually + use a custom Nixpacks start command (Option B below), run the seed manually after the first deploy: `npx prisma db seed`. +- `ADMIN_SESSION_SECRET` is required at runtime — without it every super-admin + login returns 500 (`ADMIN_SESSION_SECRET env var is not set`). Generate with + `openssl rand -hex 32`. `scripts/start.sh` logs `ADMIN_SESSION_SECRET: set` + at boot so a missing value is obvious. +- Changing any `NEXT_PUBLIC_*` build variable requires a **redeploy**, not just + a restart — those values are baked into the client bundle and the CSP at + `next build`. ## Step 5: Configure Domain & Subdomain Routing @@ -227,6 +234,14 @@ traefik.http.middlewares.spomeniqr-subdomain.headers.customrequestheaders.X-Subd 4. Under **Domains**, add: - `testbed.mk` - `*.testbed.mk` +5. **Custom frontend API domain (recommended):** under **Domains**, set + `clerk.testbed.mk` as the Frontend API custom domain and add the DNS record + Clerk instructs (a CNAME). clerk-js then loads from + `https://clerk.testbed.mk/npm/@clerk/clerk-js@...`. Because this domain can't + be derived from the publishable key at build time, you **must** set + `NEXT_PUBLIC_CLERK_FAPI_HOST=clerk.testbed.mk` (Step 4) as a **build + variable** — otherwise the app's CSP blocks `clerk.browser.js` and the + auth-gated buttons on the home page stop working. ## Step 7: Configure Contabo S3 @@ -273,8 +288,12 @@ traefik.http.middlewares.spomeniqr-subdomain.headers.customrequestheaders.X-Subd - Run `npx prisma generate` - Build the Next.js app - Run `npx prisma migrate deploy` + - Provision the super-admin (`[seed] Super-admin 'super' provisioned.`) - Start the server on port 3000 -3. Once deployed, visit `https://testbed.mk` to verify +3. **First deploy:** make sure every `NEXT_PUBLIC_*` variable (including + `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` and `NEXT_PUBLIC_CLERK_FAPI_HOST`) is + already marked as a build variable — they're baked in during this build. +4. Once deployed, visit `https://testbed.mk` to verify ## Step 9: Verify Subdomain Routing @@ -296,6 +315,13 @@ If subdomains aren't working: # App health curl -s https://testbed.mk | head -5 +# CSP must allowlist the Clerk frontend API host (script-src + connect-src) +curl -sI https://testbed.mk | grep -i content-security-policy + +# Super-admin login (expect {"success":true}) +curl -s -X POST https://testbed.mk/api/admin/login -H "Content-Type: application/json" \ + -d '{"username":"super","password":"YOUR_PASSWORD"}' + # Subdomain routing curl -sI https://test-memorial.testbed.mk | head -5 @@ -328,6 +354,22 @@ Make sure you've applied the bucket policy for public read. See Step 7. If Conta - Ensure production Clerk keys are set (not `pk_test_` / `sk_test_`) - Verify `testbed.mk` and `*.testbed.mk` are added in Clerk dashboard domains - Check that `NEXT_PUBLIC_APP_URL` and `NEXT_PUBLIC_APP_DOMAIN` are set correctly +- **CSP blocking Clerk JS** — if the browser console shows + `Content-Security-Policy: ... blocked a script ... clerk.testbed.mk/npm/@clerk/clerk-js...` + (and auth buttons do nothing): the CSP was built without the Clerk frontend + API host. Set `NEXT_PUBLIC_CLERK_FAPI_HOST` (Step 4) as a **build variable** + and **redeploy** — the CSP is generated at build time. + +### Super-admin login fails + +- **401 "Невалидно корисничко име или лозинка"** — wrong password, or + `SUPER_ADMIN_PASSWORD_HASH` was pasted with `$$` escaping (the dev Compose + format) so the stored hash is wrong. Re-paste the raw `$2b$12$...` hash and + redeploy (the seed upserts the row on boot). +- **500 / "ADMIN_SESSION_SECRET env var is not set"** — `ADMIN_SESSION_SECRET` + is missing. Add it (runtime var) and restart. +- Verify the boot log contains `[seed] Super-admin 'super' provisioned.` — the + seed skips silently when `SUPER_ADMIN_PASSWORD_HASH` is unset. ### Database migration issues @@ -354,6 +396,8 @@ npx prisma db push | `CLERK_SECRET_KEY` | Yes | Clerk secret key (`sk_live_...`) | | `NEXT_PUBLIC_CLERK_SIGN_IN_URL` | Yes | `/sign-in` | | `NEXT_PUBLIC_CLERK_SIGN_UP_URL` | Yes | `/sign-up` | +| `NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL` | Yes | Redirect after sign-in (`/`) | +| `NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL` | Yes | Redirect after sign-up (`/`) | | `S3_ENDPOINT` | Yes | Contabo S3 endpoint URL | | `S3_REGION` | Yes | Contabo S3 region (e.g. `eu-2`) | | `S3_ACCESS_KEY_ID` | Yes | S3 access key | @@ -366,6 +410,10 @@ npx prisma db push | `SUPER_ADMIN_PASSWORD_HASH` | No | Super-admin bcrypt hash; if unset, super login is unavailable | | `NODE_ENV` | Yes | `production` | +\* `NEXT_PUBLIC_CLERK_FAPI_HOST` is only needed when a custom Clerk frontend API +domain is configured in the Clerk dashboard. It must be a **build variable** so +the CSP (generated at `next build`) allowlists `clerk.browser.js`. + ## Useful Coolify Commands - **Redeploy:** Project → Application → Deploy