Skip to content

Update - #72

Merged
JoseEstevez520 merged 6 commits into
ANFAIA:mainfrom
gestiontickets-online:main
Aug 27, 2026
Merged

Update#72
JoseEstevez520 merged 6 commits into
ANFAIA:mainfrom
gestiontickets-online:main

Conversation

@dibanez

@dibanez dibanez commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

What and why

montón de cosas a configur

Checks

  • uv run ruff check src tests and uv run pytest -m "not integration" (from apps/skillnet-api/)
  • pnpm lint, pnpm test and pnpm build (from apps/skillnet-web/)
  • Touched a migration, the compose files or .env.example? A clean docker compose up -d --build still comes up and /api/v1/health is green.

Notes for the reviewer

dibanez and others added 6 commits August 25, 2026 09:59
Dokploy loads exactly one compose file, so the `-f base -f overlay` pattern the
rest of the repo uses is unavailable, and three things a Dokploy host needs
cannot be expressed from its UI: `web` must publish no host port (Traefik
reaches it over `dokploy-network`, and a published port both bypasses the host
firewall via DNAT and collides with whatever already holds 3000), every routed
service must join that external network, and TLS terminating at Traefik means
COOKIE_SECURE has to flip — the same reason docker-compose.caddy.yml flips it.

`db` and `api` are pulled in with `extends` rather than copied. That env block
is ~60 keys and most of this repo's deployment bugs have been one of them
failing to reach the container; a second hand-maintained copy would drift, and
the symptom would be "what I configured in Dokploy does nothing". `web` is
written out in full instead, because the one thing it must not inherit is
`ports:` and Compose merges sequences rather than replacing them.

Service names are prefixed, since a Dokploy host shows every project's
containers side by side and `api`/`db`/`web` say nothing there. The old names
survive as network aliases: `docker/nginx.conf` is baked into the web image and
proxies to `api:8000`, and the inherited DATABASE_URL points at `db:5432`, so
without the aliases a cosmetic rename would force edits to files the Caddy,
cloudflared and dev deployments also use. `depends_on` needs `!override` for
the same rename — `extends` carries it over pointing at the base file's names,
and re-declaring it merges instead of replacing, leaving a dangling reference
that compose refuses to start.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NQQDUWt5Ga5xTqvjGuSpL
Dokploy parses the compose file and writes it back out before running it — that
is how it injects its own network and labels — and the rewrite drops YAML tags.
`depends_on: !override` therefore reached Compose as a plain `depends_on`, which
MERGES with the one `extends` had copied from docker-compose.yml, so the deploy
failed on `service "skillnet-api" depends on undefined service "db"`. None of
this is visible locally: there the file reaches Compose untouched and the tag
does exactly what it says.

So the file no longer relies on anything that has to survive a round-trip: no
`extends`, no tags. `db` and `api` are spelled out, `DATABASE_URL` points at
`skillnet-postgres` directly (no alias needed for it any more), and only the
`api` alias stays, because docker/nginx.conf is baked into the web image and
proxies to `api:8000`.

The cost is a second copy of `api`'s ~60-key environment block, which is why
the header now says in plain words that it has to be kept in sync — the whole
class of bug this repo keeps hitting is one env key not reaching the container.
The copy was extracted from docker-compose.yml mechanically and diffed against
it: same keys, exactly three deliberate value changes (DATABASE_URL host,
COOKIE_SECURE and CORS_ORIGINS, the last two for the same reason the Caddy
overlay changes them).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NQQDUWt5Ga5xTqvjGuSpL
The compose file carried its own Traefik labels for ${DOMAIN}. They work, but
adding the domain from Dokploy's Domains tab makes Dokploy write a second set
of labels for the same hostname, and two routers claiming the same `Host()`
rule is a coin flip over which one answers. The UI is where a Dokploy operator
looks for this, so the UI wins and the labels go.

What cannot move to the UI stays: `skillnet-web` still joins the external
`dokploy-network`, because the Domains tab adds labels, not networks, and
Traefik cannot reach a container it shares no network with. Point that tab at
service `skillnet-web`, container port 80 — nginx's port inside the container,
not a host port; there is still deliberately none.

DOMAIN was previously required by the router label. It is still needed, now by
CORS_ORIGINS alone, so the `:?` guard moves there rather than disappearing —
otherwise a missing DOMAIN would have silently produced the origin
`https://`. Setting CORS_ORIGINS explicitly skips the guard, since Compose only
evaluates a default when the variable is unset.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NQQDUWt5Ga5xTqvjGuSpL
On a Dokploy host Traefik is the reverse proxy, so the nginx inside the web
image was a second one to keep in sync for nothing. docker/web.dokploy.Dockerfile
builds the same Vite bundle and serves it with `serve` on 3000: history-API
fallback and headers come from docker/serve.json, which reproduces the three
headers docker/security-headers.conf sets plus the immutable/no-store split
between /assets and index.html.

Dropping nginx moves one job it was doing, and it is not optional: the SPA calls
the API on relative paths (`/api/v1/...`, apps/skillnet-web/src/api/client.ts)
and has no configurable base URL, so the Domains tab now needs TWO entries on
the same host — `/` to skillnet-web:3000 and `/api` to skillnet-api:8000 (plus
`/ext` for the external API). Traefik ranks routers by rule length, so the
prefix wins over `/` on its own. That is why skillnet-api joins dokploy-network
here; the paths it exposes publicly are the ones nginx already forwarded, so it
is a shorter route to the same surface, not a wider one. The web healthcheck
drops to `/` because `/health` was nginx proxying to the API.

Two things this build does differently, both about failures that look like
broken code and are not: pnpm is installed from npm instead of `corepack
enable`, whose signature check fails opaquely on hosts with an old keyring, and
NODE_OPTIONS raises V8's heap ceiling so `tsc -b && vite build` on a small VPS
dies with an error rather than a bare "Killed". The existing web.Dockerfile
builds fine here (verified), so the Vite step was never the problem.

Verified by running the image: index.html, a React Router path, a hashed asset
and the headers all come back as intended, serve.json stays out of the served
directory, and the container runs as `node`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NQQDUWt5Ga5xTqvjGuSpL
The header said the Domains tab needs an `/api` entry. It did not say what
missing it looks like — `GET /api/v1/setup/status` returning 200 with
`filename="index.html"`, which reads like a frontend bug — nor that "Strip
Path" has to stay off, since `/api/v1` is where FastAPI mounts its routes
rather than a prefix to peel away. Both produce a login that never fires.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NQQDUWt5Ga5xTqvjGuSpL
@JoseEstevez520
JoseEstevez520 merged commit 0a960d0 into ANFAIA:main Aug 27, 2026
1 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants