AETHERLABS

Deployment

Run and deploy the Aether Labs SSO stack — API, Postgres, and the three frontends.

Deployment

Aether Labs SSO is a small stack: one API, an external Postgres, and three static frontends (accounts-web, myaccount-web, admin-web), each served by nginx with SPA fallback.

Services and ports

ServiceContainer portDev host portProduction domain
api30004000https://sso.aetherlabs.agency
accounts-web803001https://accounts.aetherlabs.agency
myaccount-web803002https://myaccount.aetherlabs.agency
admin-web803003https://admin.sso.aetherlabs.agency

API host vs login host

The API is sso.aetherlabs.agency. accounts.aetherlabs.agency is the login UI. Point VITE_API_URL at the API host, not the login host.

Run locally with Docker

cp .env.example .env     # optional for dev; override secrets/ports here
docker compose up --build
# API     → http://localhost:4000  (health: /health)
# Login   → http://localhost:3001
# Profile → http://localhost:3002
# Admin   → http://localhost:3003

On first boot the API creates the auth schema, syncs its tables, and seeds the default roles. There is no bundled database — point DATABASE_URL at a Postgres you control.

Run the API directly

cd api
cp env.example .env       # fill in real values; never commit real env files
pnpm install
pnpm run dev              # boots on :4000 (needs a reachable Postgres with an auth schema)

Environment variables

VariablePurpose
DATABASE_URLPostgres connection string. No bundled DB.
JWT_ACCESS_SECRETSigns access tokens. Must match any consumer that verifies locally.
JWT_REFRESH_SECRETSigns refresh tokens.
JWT_ISSUERAdvertised by the OAuth discovery document (aetherlabs-sso).
COOKIE_DOMAINlocalhost in dev, .aetherlabs.agency in production.
ALLOWED_ORIGINSComma-separated CORS allowlist of frontend origins.
LOGIN_REDIRECTSOptional key=url overrides for the post-login destination allowlist.
BCRYPT_ROUNDSPassword hashing cost (default 12).
LOG_LEVELLogging verbosity.

Frontend variables are baked in at build time by Vite:

VariableUsed byPurpose
VITE_API_URLall threeThe API base URL.
VITE_ACCOUNTS_URLmyaccount-web, admin-webLogin UI to redirect to when signed out.
VITE_MYACCOUNT_URLaccounts-webWhere to send the user after login.

Rebuild required

Changing any VITE_* value requires rebuilding that frontend image (docker compose build). Editing the env alone has no effect.

Production notes

NODE_ENV=production
COOKIE_DOMAIN=.aetherlabs.agency
ALLOWED_ORIGINS=https://accounts.aetherlabs.agency,https://myaccount.aetherlabs.agency,https://admin.sso.aetherlabs.agency
  • In production the cookies are secure and sameSite=none, so HTTPS is mandatory. The reverse proxy (Traefik on Dokploy) terminates TLS.
  • Secrets must be strong and identical across every consumer that verifies tokens locally: openssl rand -hex 32.
  • With docker-compose.yml alone there are no published host ports — services are reached only through the proxy. The dev host ports come from docker-compose.override.yml.

Bootstrap the production admin

Register a user, then grant super_admin inside the running API container:

node dist/scripts/bootstrapAdmin.js --email you@example.com

Deploying to Dokploy

For a step-by-step walkthrough — Traefik domains, TLS, volume persistence, and the build-time env caveat — see the repository's docs/dokploy-deployment-guide.md.

Keep secrets out of docs

Never commit real .env files or paste live JWT_ACCESS_SECRET, database URLs, or passwords into documentation. Reference variable names only.

See also

On this page