- Docker and Docker Compose
- Node.js 18+ (for local development)
# Copy environment file
cp .env.dev .env
# Start services
docker compose up -dAccess:
- Frontend: http://localhost:3000
- Backend: http://localhost:3001
- Zitadel Console: http://localhost:8080/ui/console
-
Login to Zitadel Console at
http://localhost:8080/ui/console- Username:
zitadel-admin@zitadel.localhost - Password:
Admin123!
- Username:
-
Create OIDC Client:
- Projects → Select default project
- Applications → Web → New
- Name: bunker-frontend
- Redirect URIs:
http://localhost:3000/auth/callback - Post Logout URIs:
http://localhost:3000/ - Authentication Method: PKCE (none)
- Grant Types: Authorization Code
-
Update
.envwith Client ID and Secret:ZITADEL_CLIENT_ID=<your-client-id> ZITADEL_CLIENT_SECRET=<your-client-secret> ZITADEL_PROJECT_ID=<your-project-id>
-
Restart backend:
docker compose restart backend
-
Copy and customize
.env:cp .env.dev .env # Edit with production values -
Add Traefik labels to docker-compose.yml:
services: frontend: labels: - "traefik.enable=true" - "traefik.http.routers.frontend.rule=Host(`your-domain.com`)" - "traefik.http.services.frontend.loadbalancer.server.port=3000" backend: labels: - "traefik.enable=true" - "traefik.http.routers.backend.rule=Host(`your-domain.com`) && (PathPrefix(`/socket.io/`) || PathPrefix(`/api/`))" - "traefik.http.services.backend.loadbalancer.server.port=3001" zitadel: labels: - "traefik.enable=true" - "traefik.http.routers.zitadel.rule=Host(`your-domain.com`) && PathPrefix(`/auth/`)" - "traefik.http.services.zitadel.loadbalancer.server.port=8080"
-
Start services:
docker compose up -d -
Configure Zitadel with production redirect URIs
# Backend
cd backend
npm install
npm run dev
# Frontend
cd frontend
npm install
npm run devAll configuration via environment variables. See .env.example for all options.
Key variables:
NODE_ENV: development or productionBACKEND_DOMAIN: Backend URLFRONTEND_DOMAIN: Frontend URLZITADEL_DOMAIN: Zitadel URLZITADEL_CLIENT_ID: OAuth client IDZITADEL_CLIENT_SECRET: OAuth client secretDATABASE_URL: PostgreSQL connection string
Zitadel not accessible: docker compose ps zitadel and check logs
OAuth redirect errors: Verify redirect URI matches Zitadel configuration
Database connection errors: Check DATABASE_URL in .env
Services not using env vars: Restart with docker compose down && docker compose up -d
To enable guest account promotion:
- Create service account in Zitadel Console
- Create service key (JSON format)
- Grant PROJECT_OWNER role
- Update
.envwith service account credentials - Change frontend to use
/api/auth/shadow-userendpoint - Restart services