Skip to content

Latest commit

 

History

History
131 lines (102 loc) · 6.25 KB

File metadata and controls

131 lines (102 loc) · 6.25 KB

Dev container

Self-contained local environment for the gbl-uzh demo-game by default. No Infisical, no external Auth0 — clone, route through devrouter, and run. The devcontainer owns the whole stack (toolchain, Postgres, the local OIDC mock, install + build + seed, the dev server); devrouter fronts it on a shared :443 / :5432 so many projects coexist with zero host-port collisions (nothing is published on the host).

Note

This README documents the devrouter configuration (multi-project routing, host tooling required). First time here, or just building a game? Use the starter configuration instead (starter/ in this directory): only Docker + VS Code (with the Dev Containers extension) needed, ports published on localhost, Claude Code preinstalled. Walkthrough: docs/getting-started.md.

Prerequisites

devrouter ≥ 0.0.31 (proxy + TCP routing and managed workspace cleanup). One-time host setup — must run before the container starts, because the stack joins devrouter's external devnet network and that network must already exist:

dev up && dev tls install   # Traefik + the shared `devnet` + mkcert CA (needs 80/443/5432 free)

The compose file mounts the mkcert root CA from ${DEVROUTER_MKCERT_CAROOT:-$HOME/Library/Application Support/mkcert} (the macOS default). On Linux set DEVROUTER_MKCERT_CAROOT=~/.local/share/mkcert, on Windows %LOCALAPPDATA%\mkcert, before starting the container.

Run with DevPod

brew install devpod            # or: https://devpod.sh/docs/getting-started/install
devpod provider add docker

devpod up . --ide none         # builds image, starts DB/OIDC, installs, builds deps, seeds, runs dev

# register the routes (one per app; prints the https URLs)
for a in app oidc db; do dev app run "$a" --yes; done

Open https://demo-game.localhost. The dev server auto-starts in the background (tail -f /tmp/dev.log for output).

Select a game target

WORKSPACE names the routed host and container aliases. GBL_GAME_TARGET separately selects the package used consistently for Prisma copy/generate/push, seed, and the dev server. It defaults to demo; the supported values are:

Target Package
demo @gbl-uzh/demo-game
central-bank @gbl-uzh/central-bank
rate-wars @gbl-uzh/rate-wars

Pass an explicit target when creating the DevPod workspace, for example:

devpod up . --ide none --workspace-env GBL_GAME_TARGET=central-bank

The target does not derive from a branch or workspace name, and it does not change the routed hostname. Use a distinct WORKSPACE when you need an isolated route and database volume. Unknown targets fail before any Prisma command runs.

How routing works

The app, OIDC mock, and Postgres join the external devnet network with workspace-aware aliases (${WORKSPACE:-demo-game}-app, ${WORKSPACE:-demo-game}-oidc, ${WORKSPACE:-demo-game}-db). devrouter's Traefik (also on devnet) routes to them by name over the network — no published host ports. Linked worktrees namespace both the app and OIDC issuer hosts automatically.

What Host Upstream (devnet)
App https://demo-game.localhost ${WORKSPACE}-app:3000
OIDC mock https://oidc.demo-game.localhost/default ${WORKSPACE}-oidc:8090
Postgres db.demo-game.localhost:5432 ${WORKSPACE}-db:5432

Connect to the DB with direct-SSL so the TLS ClientHello carries the SNI:

psql "host=db.demo-game.localhost port=5432 user=prisma password=prisma \
      dbname=prisma sslmode=require sslnegotiation=direct"

Admin login

Auth0 is replaced by a local OIDC mock (mock-oauth2-server), routed through devrouter at https://oidc.demo-game.localhost/default. Login is one-click — no password. You are authenticated as the fixed dev admin gbl-dev@df.uzh.ch (stable sub across restarts). The browser (authorize) and the app server (discovery/token/jwks) use the same issuer host, so the token iss is consistent; the app resolves that host to the host gateway (extra_hosts) and trusts the mkcert CA via NODE_EXTRA_CA_CERTS (see docker-compose.yml).

All in-repo games use the platform's shared resolveAdminOidcConfig() resolver. Starter, devrouter, and CI use mock OIDC through GBL_AUTH_MODE=mock and GBL_MOCK_OIDC_*. These container variables override .env.local, so container modes support mock login only; native host mode runs every game against the same mock through its committed .env.development. A native host real-tenant run requires explicit GBL_AUTH_MODE=auth0 with real AUTH0_* values in ignored .env.local. Production defaults to real AUTH0_* and forbids mock mode.

What's inside

Service Image Purpose
app local Dockerfile runs the demo-game next dev
postgres postgres:15 DB, fixed creds prisma/prisma, seeds shadow DB
oidc mock-oauth2-server:2.1.11 local Auth0 replacement (sidecar)

Environment lives in devcontainer.env (committed, dev-only values). Lifecycle: post-create.sh (install + build platform/ui + prisma generate/push/seed) then post-start.sh (launch dev server). node_modules and each game's generated .next cache are named volumes (not the host's), so native binaries match the Linux container and switching between native and container modes cannot reuse an incompatible build cache.

The OIDC mock's config is shared by the container modes and native demo-game run: docker/oidc-config.json, mounted via JSON_CONFIG_PATH. Sanity-check any running container mode from inside the app container with bash .devcontainer/smoke.sh http://localhost:3000 <issuer-url>; probe the devrouter app URL separately from the host. Native host mode runs the same script from the repository root.