Skip to content

Deploying (Oracle + Dokploy)

The current deployment target is Oracle Cloud (for testing; the production vendor is not yet chosen), managed with Dokploy (a self-hosted PaaS on Traefik).

Two ARM instances:

  • forge - runs Dokploy, both dashboards, and the API.
  • forge-worker - PostgreSQL only, reachable on the private network only.

The API sits with the dashboards on forge, not with the database. This is forced by the same-origin constraint: the API has no CORS and the login cookies are SameSite=Strict and path-scoped, so each dashboard and the API it calls must share one origin (see Auth planes & tenancy).

Domain Serves
app.nexisapi.xyz hq dashboard at /, API at /api (path stripped)
admin.nexisapi.xyz platform-admin at /, API at /admin (not stripped)

All three services listen on container port 8080 (the dashboards run nginx as a non-root user; the API’s Dockerfile sets ASPNETCORE_HTTP_PORTS=8080).

Three code changes made the apps deploy cleanly under Dokploy’s Traefik. All are merged:

  1. Configurable cookie paths (API). Traefik cannot rewrite a Set-Cookie path, so the API emits the cookie at its public path via Auth__TenantCookiePath / Auth__AdminCookiePath.
  2. Migrate on startup (API). RunCentralMigrationsOnStartup=true applies the central database migrations when the API boots, instead of a separate shell step.
  3. Dashboard Dockerfiles (web). Each dashboard builds from the monorepo root and is served by non-root nginx on port 8080, with a build-time guard on VITE_API_BASE_URL.

VITE_API_BASE_URL is validated as a full URL and inlined at build time:

  • hq dashboard: https://app.nexisapi.xyz/api (the same origin it is served from, with the /api prefix).
  • platform-admin: https://admin.nexisapi.xyz (origin only - the admin client prepends /admin itself).

After deploying, sign in on admin.nexisapi.xyz and reload the page. Staying signed in proves the same-origin plus cookie-path chain is correct end to end. Getting logged out points at the cookie path or the proxy’s strip-path setting.