0pt.app svarar i dag HTTP 402 DEPLOYMENT_DISABLED — Vercels betalningsspärr — och är den enda egendomen som både är önskad och genuint trasig utan någon självhostad ersättare igång. Repot hade en Dockerfile, men appen gick inte att köra meningsfullt utanför Vercel: next.config.mjs satte inte output: "standalone" och satte images.unoptimized.
Referensimplementation är sax3l/siax-io, som redan kör självhostat på flottan. Dess Dockerfile återanvänds i form i stället för att uppfinna ett nytt mönster.
⚠️DEN HÄR PR:EN ÄR AVSIKTLIGT INTE MERGAD — läs "Blockerare" längst ner innan du mergar.
Vad som faktiskt blockerade självhostning
Uppdraget bad mig anta att det var två inställningar. Det var fem:
#
Blockerare
Åtgärd
1
Ingen output: "standalone"
Satt. Runtime kör node server.js.
2
images.unoptimized: true
Borttaget — se sharp-avsnittet, det räckte inte att ta bort raden.
3
next build spårar inte sharp in i standalone-utdatan
Eget symlänkfritt npm-steg i Dockerfile.
4
--ignore-workspace i Dockerfile byggde med ett annat kommando än CI
Borttaget; motiveringen var inaktuell sedan P1-21.
5
NODE_ENV=production vid byggtid (Coolify injicerar det) fick pnpm att hoppa över devDependencies som next build kräver
--prod=false.
Sharp: varför det inte var en enradsändring
Att ta bort images.unoptimized utan mer hade gett en container som svarar fel på varje /_next/image-begäran. Nexts bildoptimerare laddar sharp med en runtime-require, inte ett statiskt import.
VERIFIERAT: ett bygge med enbart output: "standalone" gav ett .next/standalone/node_modules som innehöll baranext/, react/, react-dom/.
VERIFIERAT (kontrolltest, inte antagande): den uppenbara lösningen outputFileTracingIncludes med "./node_modules/@img/**/*" får Turbopack att panika på pnpms katalogsymlänkar — reading file ".../@img/sharp-libvips-linux-x64" — Is a directory (os error 21) — och bygget faller med exit 1.
Därför ett eget FROM node:22-alpine AS sharp-steg: npm lägger ett platt, symlänkfritt träd som runtime-steget kan kopiera rakt av. Versionen läses ur pnpm-lock.yaml (0.35.4) så den aldrig glider, och steget faller hårt om utläsningen ger tomt i stället för att tyst skeppa en image vars bildoptimering är trasig.
Vercel-beroenden — fullständig genomgång
Beroende
Status
Ersätts av
vercel.json
Finns inte (VERIFIED: find)
— inga rewrites/redirects/crons/function-config att flytta
Sätt DATABASE_URL. De två Vercel-namnen är ofarliga fallbacks, de behöver inte tas bort.
Edge runtime
Nollexport const runtime = "edge" (VERIFIED)
Middleware kör självhostat — bevisat med 401 nedan
Bildoptimering
Var kringgången med unoptimized
Självhostad next/image + sharp, bevisad nedan
Objektlagring
R2_* = Cloudflare R2, inte Vercel
Oförändrat. Kan flyttas till ST0RE separat.
Ingenting av detta krävde en ersättningstjänst. Migrationen är i praktiken kostnadsfri på beroendesidan.
Miljövariabler för Coolify (endast namn, aldrig värden)
Måste sättas för en fungerande deploy:
DATABASE_URL — Postgres. Utan den svarar /api/ready 503 (avsiktligt).
AUTH_SECRET — sessionssignering, lång slumpsträng.
INTERNAL_TOKEN — service-till-service, skickas som X-Internal-Token.
NEXT_PUBLIC_APP_URL — publik bas-URL, används för absoluta länkar/callbacks.
CL0UD_URL, N0D_URL, AUD0_URL — under NODE_ENV=production är en osatt URL ett hårt bootfel (DEPENDENCY_UNAVAILABLE); produktion faller aldrig tyst tillbaka på mockar.
Sätts av Dockerfilen — sätt dem INTE i Coolify:NODE_ENV, PORT, HOSTNAME, NEXT_TELEMETRY_DISABLED.
Valfria (funktionen är avstängd/501 tills de sätts):
Sätt ALDRIG i produktion:AUTH_ENFORCE=false (appen vägrar boota — fail-closed), DEV_LOGIN_KEY, OPT_LOCAL_BLOB_DIR.
Probe-inställning i Coolify: peka health/liveness på /api/health (200 så länge processen lever). Peka inte en readiness-probe dit — använd /api/ready, som faller stängt (503) tills Postgres är nåbar. Att blanda ihop dem får Coolify att döda en container som fungerar precis som avsett.
Bevis — det byggdes och kördes faktiskt
Uppdraget var uttryckligt: "En Dockerfile som aldrig byggts är inte en leverans." Alla siffror nedan är körda kommandon.
Bygge utan en enda Vercel-variabel (env -i, helt tom miljö):
pnpm install --frozen-lockfile -> exit 0
NODE_ENV=production next build -> exit 0
docker build --no-cache -> exit 0
"sharp pinnad fran pnpm-lock.yaml: 0.35.4"
"sharp laddar OK i byggsteget"
Containern kördes och svarade:
docker run -d -p 13012:3000 -> klar efter 1s
GET /api/health -> HTTP 200 {"ok":true,"service":"0pt-web",...}
GET /api/ready -> HTTP 503 (utan DATABASE_URL — faller stängt, korrekt)
GET / -> HTTP 200 86 001 bytes
GET /api/0pt/sources utan Bearer -> HTTP 401 OPT_UNAUTHENTICATED
docker inspect .State.Health.Status -> "healthy"
Bildoptimeringen fungerar — det som unoptimized dolde:
Identiskt på ren main: 17 problem (12 fel, 5 varningar). Pre-existerande.
prettier
exit 1
Identiskt på ren main: 429 filer. Är inget CI-steg.
Ingen grind, assertion eller lintregel har försvagats, hoppats över eller lossats. Inga skyddade sökvägar rörda (.gitea/workflows/** och .gitignore är orörda).
Blockerare: en merge här ÄR en produktionsdeploy
.gitea/workflows/cd.yml kör vid varje push till main:
curl -X POST https://cloud.siax.io/api/v1/deploy?uuid=${COOLIFY_APP_ID}
VERIFIERAT via Gitea-API:vars/COOLIFY_APP_ID innehåller en riktig 24-teckens UUID (inte längre platshållaren TODO-no-coolify-app-provisioned-yet) och secret COOLIFY_TOKEN finns sedan 2026-08-31. Båda vaktvillkoren passerar.
Att merga den här PR:en avfyrar alltså en skarp ombyggnad och omdeploy mot cloud.siax.io. Mitt uppdrag förbjuder uttryckligen att deploya eller trigga Coolify, så jag har inte mergat. Det beslutet är ditt, Simon.
Sidofynd, utanför scope här: CHANGELOG.md på main påstår att säkerhetsheaders (CSP/HSTS/X-Frame-Options) är gjorda, men origin/main innehåller noll sådan kod — implementationen ligger på den omergade grenen ci/security-headers-and-scanning (8d2ff73). Bakom Traefik utan Vercel framför får appen alltså inga sådana headers förrän den grenen mergas.
## Varför
`0pt.app` svarar i dag **HTTP 402 DEPLOYMENT_DISABLED** — Vercels betalningsspärr — och är den enda egendomen som både är önskad och genuint trasig utan någon självhostad ersättare igång. Repot hade en Dockerfile, men appen gick inte att köra meningsfullt utanför Vercel: `next.config.mjs` satte inte `output: "standalone"` och satte `images.unoptimized`.
Referensimplementation är **`sax3l/siax-io`**, som redan kör självhostat på flottan. Dess Dockerfile återanvänds i form i stället för att uppfinna ett nytt mönster.
> ⚠️ **DEN HÄR PR:EN ÄR AVSIKTLIGT INTE MERGAD — läs "Blockerare" längst ner innan du mergar.**
## Vad som faktiskt blockerade självhostning
Uppdraget bad mig anta att det var två inställningar. Det var fem:
| # | Blockerare | Åtgärd |
|---|---|---|
| 1 | Ingen `output: "standalone"` | Satt. Runtime kör `node server.js`. |
| 2 | `images.unoptimized: true` | Borttaget — se sharp-avsnittet, det räckte **inte** att ta bort raden. |
| 3 | `next build` spårar **inte** sharp in i standalone-utdatan | Eget symlänkfritt npm-steg i Dockerfile. |
| 4 | `--ignore-workspace` i Dockerfile byggde med ett **annat** kommando än CI | Borttaget; motiveringen var inaktuell sedan P1-21. |
| 5 | `NODE_ENV=production` vid byggtid (Coolify injicerar det) fick pnpm att hoppa över devDependencies som `next build` kräver | `--prod=false`. |
## Sharp: varför det inte var en enradsändring
Att ta bort `images.unoptimized` utan mer hade gett en container som svarar **fel på varje `/_next/image`-begäran**. Nexts bildoptimerare laddar `sharp` med en runtime-`require`, inte ett statiskt import.
- **VERIFIERAT:** ett bygge med enbart `output: "standalone"` gav ett `.next/standalone/node_modules` som innehöll **bara** `next/`, `react/`, `react-dom/`.
- **VERIFIERAT (kontrolltest, inte antagande):** den uppenbara lösningen `outputFileTracingIncludes` med `"./node_modules/@img/**/*"` får **Turbopack att panika** på pnpms katalogsymlänkar — `reading file ".../@img/sharp-libvips-linux-x64" — Is a directory (os error 21)` — och bygget faller med **exit 1**.
Därför ett eget `FROM node:22-alpine AS sharp`-steg: npm lägger ett platt, symlänkfritt träd som runtime-steget kan kopiera rakt av. Versionen läses ur `pnpm-lock.yaml` (0.35.4) så den aldrig glider, och steget **faller hårt** om utläsningen ger tomt i stället för att tyst skeppa en image vars bildoptimering är trasig.
## Vercel-beroenden — fullständig genomgång
| Beroende | Status | Ersätts av |
|---|---|---|
| `vercel.json` | **Finns inte** (VERIFIED: `find`) | — inga rewrites/redirects/crons/function-config att flytta |
| `@vercel/*`-paket | **Noll** i `package.json` (VERIFIED) | `@vercel/analytics` togs redan bort tidigare |
| `VERCEL_*`-env-läsningar | **Noll** i all spårad kod (VERIFIED: `git grep`) | — |
| Vercel KV / Blob | Används inte | — |
| Vercel Postgres | **Mjukt beroende**: `lib/db.ts` läser `DATABASE_URL` → `POSTGRES_URL` → `POSTGRES_PRISMA_URL` | Sätt `DATABASE_URL`. De två Vercel-namnen är ofarliga fallbacks, de behöver inte tas bort. |
| Edge runtime | **Noll** `export const runtime = "edge"` (VERIFIED) | Middleware kör självhostat — bevisat med 401 nedan |
| Bildoptimering | Var kringgången med `unoptimized` | Självhostad `next/image` + sharp, bevisad nedan |
| Objektlagring | `R2_*` = Cloudflare R2, **inte** Vercel | Oförändrat. Kan flyttas till ST0RE separat. |
Ingenting av detta krävde en ersättningstjänst. Migrationen är i praktiken kostnadsfri på beroendesidan.
## Miljövariabler för Coolify (endast namn, aldrig värden)
**Måste sättas för en fungerande deploy:**
- `DATABASE_URL` — Postgres. Utan den svarar `/api/ready` 503 (avsiktligt).
- `AUTH_SECRET` — sessionssignering, lång slumpsträng.
- `INTERNAL_TOKEN` — service-till-service, skickas som `X-Internal-Token`.
- `NEXT_PUBLIC_APP_URL` — publik bas-URL, används för absoluta länkar/callbacks.
- `CL0UD_URL`, `N0D_URL`, `AUD0_URL` — under `NODE_ENV=production` är en **osatt** URL ett hårt bootfel (`DEPENDENCY_UNAVAILABLE`); produktion faller aldrig tyst tillbaka på mockar.
**Sätts av Dockerfilen — sätt dem INTE i Coolify:** `NODE_ENV`, `PORT`, `HOSTNAME`, `NEXT_TELEMETRY_DISABLED`.
**Valfria (funktionen är avstängd/501 tills de sätts):**
- Auth/IdP: `ZITADEL_ISSUER` (default `https://id-customers.siax.io`), `ZITADEL_TENANT_CLAIM`, `AUTH_URL`
- Tjänstetokens: `CL0UD_SERVICE_TOKEN`, `N0D_SERVICE_TOKEN`, `AUD0_SERVICE_TOKEN`, `ST0RE_SERVICE_TOKEN`
- Plattform: `ST0RE_URL`, `INF0_URL`, `ENGINE_URL`, `REDIS_URL`
- Betalning: `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`
- Data-OS: `OPENSEARCH_URL`, `CLICKHOUSE_URL`, `CLICKHOUSE_AUTH`, `OPENMETADATA_URL`, `OPENMETADATA_TOKEN`, `FEAST_SERVER_URL`
- Lagring/OCR/övrigt: `R2_ENDPOINT`, `R2_BUCKET`, `R2_ACCESS_KEY_ID`, `R2_ACCOUNT_ID`, `R2_SECRET_ACCESS_KEY`, `DOC_INTELLIGENCE_ENDPOINT`, `DOC_INTELLIGENCE_KEY`, `DOC_INTELLIGENCE_API_VERSION`, `GRANT_ENC_KEY`, `ODOO_BASE_URL`, `RESEND_API_KEY`
**Sätt ALDRIG i produktion:** `AUTH_ENFORCE=false` (appen vägrar boota — fail-closed), `DEV_LOGIN_KEY`, `OPT_LOCAL_BLOB_DIR`.
**Probe-inställning i Coolify:** peka health/liveness på `/api/health` (200 så länge processen lever). Peka **inte** en readiness-probe dit — använd `/api/ready`, som faller stängt (503) tills Postgres är nåbar. Att blanda ihop dem får Coolify att döda en container som fungerar precis som avsett.
## Bevis — det byggdes och kördes faktiskt
Uppdraget var uttryckligt: *"En Dockerfile som aldrig byggts är inte en leverans."* Alla siffror nedan är körda kommandon.
**Bygge utan en enda Vercel-variabel** (`env -i`, helt tom miljö):
```
pnpm install --frozen-lockfile -> exit 0
NODE_ENV=production next build -> exit 0
docker build --no-cache -> exit 0
"sharp pinnad fran pnpm-lock.yaml: 0.35.4"
"sharp laddar OK i byggsteget"
```
**Containern kördes och svarade:**
```
docker run -d -p 13012:3000 -> klar efter 1s
GET /api/health -> HTTP 200 {"ok":true,"service":"0pt-web",...}
GET /api/ready -> HTTP 503 (utan DATABASE_URL — faller stängt, korrekt)
GET / -> HTTP 200 86 001 bytes
GET /api/0pt/sources utan Bearer -> HTTP 401 OPT_UNAUTHENTICATED
docker inspect .State.Health.Status -> "healthy"
```
**Bildoptimeringen fungerar — det som `unoptimized` dolde:**
```
GET /_next/image?url=/images/mono-3.png&w=1920&q=75
Accept: avif -> HTTP 200 image/avif 51 161 bytes
Accept: webp -> HTTP 200 image/webp 86 390 bytes
Källa: 1 488 706 bytes PNG => 29x mindre
file(1): "ISO Media, AVIF Image" / "RIFF ... Web/P image, VP8, 1920x1280"
node -e require('sharp') i imagen -> "sharp runtime OK, libvips 8.18.6"
```
**Imagens form:**
```
uid=1000(node) icke-root · npm/npx strippat (bara corepack kvar)
node v22.23.2 (matchar CI) · musl-binärer @img/sharp-linuxmusl-x64
X-Powered-By frånvarande
Storlek: 1,33 GB (före) -> 423 MB (efter)
```
## Grindar
| Grind | Utfall | Not |
|---|---|---|
| `typecheck` (blockerande) | **exit 0** | |
| `test` (blockerande) | **exit 0** | 930 passerade, 174 hoppade |
| `build` (blockerande) | **exit 0** | |
| `lint` (rådgivande, `continue-on-error`) | exit 1 | **Identiskt på ren main**: 17 problem (12 fel, 5 varningar). Pre-existerande. |
| prettier | exit 1 | **Identiskt på ren main**: 429 filer. Är inget CI-steg. |
Ingen grind, assertion eller lintregel har försvagats, hoppats över eller lossats. Inga skyddade sökvägar rörda (`.gitea/workflows/**` och `.gitignore` är orörda).
## Blockerare: en merge här ÄR en produktionsdeploy
`.gitea/workflows/cd.yml` kör vid varje push till `main`:
```
curl -X POST https://cloud.siax.io/api/v1/deploy?uuid=${COOLIFY_APP_ID}
```
**VERIFIERAT via Gitea-API:** `vars/COOLIFY_APP_ID` innehåller en riktig 24-teckens UUID (inte längre platshållaren `TODO-no-coolify-app-provisioned-yet`) och secret `COOLIFY_TOKEN` finns sedan 2026-08-31. **Båda vaktvillkoren passerar.**
Att merga den här PR:en avfyrar alltså en skarp ombyggnad och omdeploy mot `cloud.siax.io`. Mitt uppdrag förbjuder uttryckligen att deploya eller trigga Coolify, så jag har **inte** mergat. **Det beslutet är ditt, Simon.**
Sidofynd, utanför scope här: `CHANGELOG.md` på `main` påstår att säkerhetsheaders (CSP/HSTS/X-Frame-Options) är gjorda, men `origin/main` innehåller **noll** sådan kod — implementationen ligger på den omergade grenen `ci/security-headers-and-scanning` (`8d2ff73`). Bakom Traefik utan Vercel framför får appen alltså inga sådana headers förrän den grenen mergas.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
0pt.app svarar i dag HTTP 402 DEPLOYMENT_DISABLED (Vercels betalningsspärr) och
har ingen självhostad ersättare igång. Det här gör appen faktiskt byggbar och
körbar på Coolify. Referens: sax3l/siax-io, som redan kör självhostat på flottan
— dess Dockerfile återanvänds i form i stället för att uppfinna ett eget mönster.
next.config.mjs:
* output: "standalone" — runtime-imagen kör `node server.js` i stället för att
släpa med pnpm, corepack och hela node_modules-trädet.
* images.unoptimized: true BORTTAGET. Det var v0-generatorns standardvärde, inte
ett val: next.config.mjs var orörd sedan "Initial commit from v0". Självhostat
är rätt lösning att låta Next optimera själv.
* poweredByHeader: false.
Dockerfile (fyra steg, samma form som siax-io):
* node:24-alpine -> node:22-alpine. Båda CI-workflowsen bygger på node 22;
att bygga och köra på samma major som grinden testar tar bort en version-skew.
* libc6-compat (sharp), icke-root `node`, HEALTHCHECK mot /api/health,
npm/npx strippat ur runtime-imagen (SIO-019-mönstret).
* --ignore-workspace borttaget: motiveringen i kommentaren var inaktuell sedan
P1-21 (pnpm-workspace.yaml har ett giltigt packages:-fält och
packages/schemas är en riktig medlem). Containerinstallationen blir därmed
bit för bit samma kommando som CI kör.
* --prod=false: Coolify injicerar NODE_ENV=production vid byggtid, och pnpm
hoppar då över devDependencies som next build kräver.
Sharp levereras i ett eget npm-steg, och det är inte godtyckligt:
next build spårar INTE sharp in i .next/standalone (verifierat: standalone-
utdatans node_modules innehöll bara next/, react/, react-dom/). Den uppenbara
lösningen outputFileTracingIncludes fungerar bevisligen inte — globben
"./node_modules/@img/**/*" får Turbopack att panika på pnpms katalogsymlänkar
("Is a directory (os error 21)") och bygget faller med exit 1. Reproducerat, inte
antaget. npm-steget lägger ett platt, symlänkfritt träd som runtime-steget kan
kopiera rakt av, pinnat till versionen i pnpm-lock.yaml, och faller hårt om
versionen inte går att läsa ut i stället för att tyst skeppa trasig optimering.
BEVISAT, inte påstått (fullständiga exitkoder i PR-beskrivningen):
* pnpm install --frozen-lockfile -> 0; next build med HELT TOM env -> 0
* docker build --no-cache -> 0; container startar, /api/health -> HTTP 200
* /api/ready utan DATABASE_URL -> HTTP 503 (faller stängt, som avsett)
* /api/0pt/* utan Bearer -> HTTP 401 (middleware kör självhostat)
* /_next/image -> HTTP 200 image/avif, 1 488 706 B PNG -> 51 161 B (29x)
* sharp laddar i runtime-imagen (libvips 8.18.6, musl-binärer)
* icke-root uid=1000, HEALTHCHECK "healthy", image 1,33 GB -> 423 MB
* typecheck 0, test 0 (930 passerade). lint/prettier faller identiskt på ren
main => pre-existerande, inte infört här. Ingen grind har rörts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CODEOWNERS rules
requested review from sax3l 2026-09-07 16:51:39 +00:00
admin
merged commit into main2026-09-08 20:48:45 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Varför
0pt.appsvarar i dag HTTP 402 DEPLOYMENT_DISABLED — Vercels betalningsspärr — och är den enda egendomen som både är önskad och genuint trasig utan någon självhostad ersättare igång. Repot hade en Dockerfile, men appen gick inte att köra meningsfullt utanför Vercel:next.config.mjssatte inteoutput: "standalone"och satteimages.unoptimized.Referensimplementation är
sax3l/siax-io, som redan kör självhostat på flottan. Dess Dockerfile återanvänds i form i stället för att uppfinna ett nytt mönster.Vad som faktiskt blockerade självhostning
Uppdraget bad mig anta att det var två inställningar. Det var fem:
output: "standalone"node server.js.images.unoptimized: truenext buildspårar inte sharp in i standalone-utdatan--ignore-workspacei Dockerfile byggde med ett annat kommando än CINODE_ENV=productionvid byggtid (Coolify injicerar det) fick pnpm att hoppa över devDependencies somnext buildkräver--prod=false.Sharp: varför det inte var en enradsändring
Att ta bort
images.unoptimizedutan mer hade gett en container som svarar fel på varje/_next/image-begäran. Nexts bildoptimerare laddarsharpmed en runtime-require, inte ett statiskt import.output: "standalone"gav ett.next/standalone/node_modulessom innehöll baranext/,react/,react-dom/.outputFileTracingIncludesmed"./node_modules/@img/**/*"får Turbopack att panika på pnpms katalogsymlänkar —reading file ".../@img/sharp-libvips-linux-x64" — Is a directory (os error 21)— och bygget faller med exit 1.Därför ett eget
FROM node:22-alpine AS sharp-steg: npm lägger ett platt, symlänkfritt träd som runtime-steget kan kopiera rakt av. Versionen läses urpnpm-lock.yaml(0.35.4) så den aldrig glider, och steget faller hårt om utläsningen ger tomt i stället för att tyst skeppa en image vars bildoptimering är trasig.Vercel-beroenden — fullständig genomgång
vercel.jsonfind)@vercel/*-paketpackage.json(VERIFIED)@vercel/analyticstogs redan bort tidigareVERCEL_*-env-läsningargit grep)lib/db.tsläserDATABASE_URL→POSTGRES_URL→POSTGRES_PRISMA_URLDATABASE_URL. De två Vercel-namnen är ofarliga fallbacks, de behöver inte tas bort.export const runtime = "edge"(VERIFIED)unoptimizednext/image+ sharp, bevisad nedanR2_*= Cloudflare R2, inte VercelIngenting av detta krävde en ersättningstjänst. Migrationen är i praktiken kostnadsfri på beroendesidan.
Miljövariabler för Coolify (endast namn, aldrig värden)
Måste sättas för en fungerande deploy:
DATABASE_URL— Postgres. Utan den svarar/api/ready503 (avsiktligt).AUTH_SECRET— sessionssignering, lång slumpsträng.INTERNAL_TOKEN— service-till-service, skickas somX-Internal-Token.NEXT_PUBLIC_APP_URL— publik bas-URL, används för absoluta länkar/callbacks.CL0UD_URL,N0D_URL,AUD0_URL— underNODE_ENV=productionär en osatt URL ett hårt bootfel (DEPENDENCY_UNAVAILABLE); produktion faller aldrig tyst tillbaka på mockar.Sätts av Dockerfilen — sätt dem INTE i Coolify:
NODE_ENV,PORT,HOSTNAME,NEXT_TELEMETRY_DISABLED.Valfria (funktionen är avstängd/501 tills de sätts):
ZITADEL_ISSUER(defaulthttps://id-customers.siax.io),ZITADEL_TENANT_CLAIM,AUTH_URLCL0UD_SERVICE_TOKEN,N0D_SERVICE_TOKEN,AUD0_SERVICE_TOKEN,ST0RE_SERVICE_TOKENST0RE_URL,INF0_URL,ENGINE_URL,REDIS_URLSTRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET,NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYOPENSEARCH_URL,CLICKHOUSE_URL,CLICKHOUSE_AUTH,OPENMETADATA_URL,OPENMETADATA_TOKEN,FEAST_SERVER_URLR2_ENDPOINT,R2_BUCKET,R2_ACCESS_KEY_ID,R2_ACCOUNT_ID,R2_SECRET_ACCESS_KEY,DOC_INTELLIGENCE_ENDPOINT,DOC_INTELLIGENCE_KEY,DOC_INTELLIGENCE_API_VERSION,GRANT_ENC_KEY,ODOO_BASE_URL,RESEND_API_KEYSätt ALDRIG i produktion:
AUTH_ENFORCE=false(appen vägrar boota — fail-closed),DEV_LOGIN_KEY,OPT_LOCAL_BLOB_DIR.Probe-inställning i Coolify: peka health/liveness på
/api/health(200 så länge processen lever). Peka inte en readiness-probe dit — använd/api/ready, som faller stängt (503) tills Postgres är nåbar. Att blanda ihop dem får Coolify att döda en container som fungerar precis som avsett.Bevis — det byggdes och kördes faktiskt
Uppdraget var uttryckligt: "En Dockerfile som aldrig byggts är inte en leverans." Alla siffror nedan är körda kommandon.
Bygge utan en enda Vercel-variabel (
env -i, helt tom miljö):Containern kördes och svarade:
Bildoptimeringen fungerar — det som
unoptimizeddolde:Imagens form:
Grindar
typecheck(blockerande)test(blockerande)build(blockerande)lint(rådgivande,continue-on-error)Ingen grind, assertion eller lintregel har försvagats, hoppats över eller lossats. Inga skyddade sökvägar rörda (
.gitea/workflows/**och.gitignoreär orörda).Blockerare: en merge här ÄR en produktionsdeploy
.gitea/workflows/cd.ymlkör vid varje push tillmain:VERIFIERAT via Gitea-API:
vars/COOLIFY_APP_IDinnehåller en riktig 24-teckens UUID (inte längre platshållarenTODO-no-coolify-app-provisioned-yet) och secretCOOLIFY_TOKENfinns sedan 2026-08-31. Båda vaktvillkoren passerar.Att merga den här PR:en avfyrar alltså en skarp ombyggnad och omdeploy mot
cloud.siax.io. Mitt uppdrag förbjuder uttryckligen att deploya eller trigga Coolify, så jag har inte mergat. Det beslutet är ditt, Simon.Sidofynd, utanför scope här:
CHANGELOG.mdpåmainpåstår att säkerhetsheaders (CSP/HSTS/X-Frame-Options) är gjorda, menorigin/maininnehåller noll sådan kod — implementationen ligger på den omergade grenenci/security-headers-and-scanning(8d2ff73). Bakom Traefik utan Vercel framför får appen alltså inga sådana headers förrän den grenen mergas.🤖 Generated with Claude Code
0pt.app svarar i dag HTTP 402 DEPLOYMENT_DISABLED (Vercels betalningsspärr) och har ingen självhostad ersättare igång. Det här gör appen faktiskt byggbar och körbar på Coolify. Referens: sax3l/siax-io, som redan kör självhostat på flottan — dess Dockerfile återanvänds i form i stället för att uppfinna ett eget mönster. next.config.mjs: * output: "standalone" — runtime-imagen kör `node server.js` i stället för att släpa med pnpm, corepack och hela node_modules-trädet. * images.unoptimized: true BORTTAGET. Det var v0-generatorns standardvärde, inte ett val: next.config.mjs var orörd sedan "Initial commit from v0". Självhostat är rätt lösning att låta Next optimera själv. * poweredByHeader: false. Dockerfile (fyra steg, samma form som siax-io): * node:24-alpine -> node:22-alpine. Båda CI-workflowsen bygger på node 22; att bygga och köra på samma major som grinden testar tar bort en version-skew. * libc6-compat (sharp), icke-root `node`, HEALTHCHECK mot /api/health, npm/npx strippat ur runtime-imagen (SIO-019-mönstret). * --ignore-workspace borttaget: motiveringen i kommentaren var inaktuell sedan P1-21 (pnpm-workspace.yaml har ett giltigt packages:-fält och packages/schemas är en riktig medlem). Containerinstallationen blir därmed bit för bit samma kommando som CI kör. * --prod=false: Coolify injicerar NODE_ENV=production vid byggtid, och pnpm hoppar då över devDependencies som next build kräver. Sharp levereras i ett eget npm-steg, och det är inte godtyckligt: next build spårar INTE sharp in i .next/standalone (verifierat: standalone- utdatans node_modules innehöll bara next/, react/, react-dom/). Den uppenbara lösningen outputFileTracingIncludes fungerar bevisligen inte — globben "./node_modules/@img/**/*" får Turbopack att panika på pnpms katalogsymlänkar ("Is a directory (os error 21)") och bygget faller med exit 1. Reproducerat, inte antaget. npm-steget lägger ett platt, symlänkfritt träd som runtime-steget kan kopiera rakt av, pinnat till versionen i pnpm-lock.yaml, och faller hårt om versionen inte går att läsa ut i stället för att tyst skeppa trasig optimering. BEVISAT, inte påstått (fullständiga exitkoder i PR-beskrivningen): * pnpm install --frozen-lockfile -> 0; next build med HELT TOM env -> 0 * docker build --no-cache -> 0; container startar, /api/health -> HTTP 200 * /api/ready utan DATABASE_URL -> HTTP 503 (faller stängt, som avsett) * /api/0pt/* utan Bearer -> HTTP 401 (middleware kör självhostat) * /_next/image -> HTTP 200 image/avif, 1 488 706 B PNG -> 51 161 B (29x) * sharp laddar i runtime-imagen (libvips 8.18.6, musl-binärer) * icke-root uid=1000, HEALTHCHECK "healthy", image 1,33 GB -> 423 MB * typecheck 0, test 0 (930 passerade). lint/prettier faller identiskt på ren main => pre-existerande, inte infört här. Ingen grind har rörts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>