Configuration
Shell API reads all env vars on startup and validates them with Zod (shell/api/src/config/env.config.ts). Invalid or missing required vars will throw at boot.
All variables use the APP_ENV_ prefix. Shell UI uses only one variable.
Server
| Variable | Default | Description |
|---|---|---|
APP_ENV_HOST | 0.0.0.0 | Bind address |
APP_ENV_PORT | 3000 | HTTP port |
APP_ENV_SERVER_BASE_PATH | /api | Route prefix for all endpoints |
APP_ENV_NODE_ENV | development | development | production | test |
Database
| Variable | Default | Description |
|---|---|---|
APP_ENV_DATABASE_URL | — required | PostgreSQL connection string |
APP_ENV_DATABASE_URL=postgresql://shell:shell@localhost:5433/shell_dbRedis / Storage
| Variable | Default | Description |
|---|---|---|
APP_ENV_REDIS_URL | redis://localhost:6379 | Redis URL. Used for PKCE state store and token blacklist. |
APP_ENV_MINIO_ENDPOINT | http://localhost:9000 | MinIO / S3-compatible endpoint |
APP_ENV_MINIO_ACCESS_KEY | — optional | MinIO access key |
APP_ENV_MINIO_SECRET_KEY | — optional | MinIO secret key |
Redis password format
In Kubernetes, Redis requires authentication. Use the format redis://:password@host:port (note the colon before the password).
# K8s
APP_ENV_REDIS_URL=redis://:mypassword@redis:6379
# Local (no auth)
APP_ENV_REDIS_URL=redis://localhost:6380JWT
| Variable | Default | Description |
|---|---|---|
APP_ENV_JWT_SECRET | — required | HS256 signing secret, minimum 32 characters |
APP_ENV_JWT_ISSUER | — optional | iss claim value |
APP_ENV_JWT_AUDIENCE | — optional | aud claim value |
Generate a strong secret
openssl rand -hex 32Never reuse secrets across environments or services.
Keycloak
Two URLs are required in Kubernetes
The browser and the server must use different Keycloak URLs in a K8s cluster.
| Variable | Used for | K8s example |
|---|---|---|
APP_ENV_KEYCLOAK_URL | Browser → PKCE authorize redirect | https://auth.dev.venizia.ai |
APP_ENV_KEYCLOAK_INTERNAL_URL | Server → token exchange, JWKS | http://keycloak:8080 |
In local dev, set both to the same value (http://localhost:8080). If APP_ENV_KEYCLOAK_INTERNAL_URL is not set, it falls back to APP_ENV_KEYCLOAK_URL.
| Variable | Default | Description |
|---|---|---|
APP_ENV_KEYCLOAK_URL | http://localhost:8080 | Public URL — sent to the browser for the PKCE authorize redirect |
APP_ENV_KEYCLOAK_INTERNAL_URL | (falls back to KEYCLOAK_URL) | Internal URL — used server-side for token exchange and JWKS |
APP_ENV_KEYCLOAK_REALM | veni-ai | Keycloak realm name |
APP_ENV_KEYCLOAK_CLIENT_ID | veni-ai-platform | Keycloak client ID |
APP_ENV_KEYCLOAK_CLIENT_SECRET | — optional | Required for confidential clients only |
APP_ENV_KEYCLOAK_REDIRECT_URI | http://localhost:3000/api/auth/callback | OAuth callback URL (must match Keycloak client config) |
Google OAuth optional
| Variable | Description |
|---|---|
APP_ENV_GOOGLE_CLIENT_ID | Google OAuth client ID |
APP_ENV_GOOGLE_CLIENT_SECRET | Google OAuth client secret |
When set, Google is auto-registered as an identity provider on startup (upsert — safe to change).
Application URLs
| Variable | Default | Description |
|---|---|---|
APP_ENV_API_URL | http://localhost:3000 | Public API URL (used in OAuth redirects and emails) |
APP_ENV_FRONTEND_URL | http://localhost:5173 | Frontend URL (used as default CORS origin) |
gRPC Services
Shell API acts as a gRPC gateway. Each downstream service needs a URL.
| Variable | Default | Service |
|---|---|---|
APP_ENV_SURE_GRPC_URL | http://localhost:3008/api | Sure service |
APP_ENV_HRM_GRPC_URL | http://localhost:3001/api | HRM service |
APP_ENV_REPORT_GRPC_URL | http://localhost:3002/api | Report service |
APP_ENV_GRPC_URLS | — optional | JSON map for additional services |
# Add arbitrary services
APP_ENV_GRPC_URLS={"myapp":"http://myapp-api:3000/api"}URLs must include the service's base path (e.g. /api).
Stripe optional
| Variable | Description |
|---|---|
APP_ENV_STRIPE_SECRET_KEY | Stripe secret key (sk_...) |
APP_ENV_STRIPE_WEBHOOK_SECRET | Stripe webhook signing secret (whsec_...) |
APP_ENV_STRIPE_PUBLISHABLE_KEY | Stripe publishable key (pk_...) — returned to frontend via /api/config |
CORS
| Variable | Default | Description |
|---|---|---|
APP_ENV_CORS_ORIGINS | (see below) | Comma-separated list of allowed origins |
If not set, defaults to: APP_ENV_FRONTEND_URL, http://localhost:5173, http://localhost:3000.
APP_ENV_CORS_ORIGINS=https://app.venizia.ai,https://hrm.venizia.aiShell UI
Shell UI has a single env variable:
| Variable | Required | Description |
|---|---|---|
VITE_API_URL | required | Full API base URL including /api path |
# shell/ui/.env.local
VITE_API_URL=http://localhost:3000/apiComplete .env example
Expand full example
# ── Server ────────────────────────────────────────────────────
APP_ENV_HOST=0.0.0.0
APP_ENV_PORT=3000
APP_ENV_SERVER_BASE_PATH=/api
APP_ENV_NODE_ENV=development
# ── Database ──────────────────────────────────────────────────
APP_ENV_DATABASE_URL=postgresql://shell:shell@localhost:5433/shell_db
# ── Redis ─────────────────────────────────────────────────────
APP_ENV_REDIS_URL=redis://localhost:6380
# ── JWT ───────────────────────────────────────────────────────
APP_ENV_JWT_SECRET=your-min-32-char-secret-change-in-production
# ── Keycloak ──────────────────────────────────────────────────
APP_ENV_KEYCLOAK_URL=http://localhost:8080
APP_ENV_KEYCLOAK_INTERNAL_URL=http://localhost:8080
APP_ENV_KEYCLOAK_REALM=veni-ai
APP_ENV_KEYCLOAK_CLIENT_ID=veni-ai-platform
APP_ENV_KEYCLOAK_CLIENT_SECRET=
APP_ENV_KEYCLOAK_REDIRECT_URI=http://localhost:3000/api/auth/callback
# ── Google OAuth (optional) ───────────────────────────────────
# APP_ENV_GOOGLE_CLIENT_ID=
# APP_ENV_GOOGLE_CLIENT_SECRET=
# ── URLs ──────────────────────────────────────────────────────
APP_ENV_API_URL=http://localhost:3000
APP_ENV_FRONTEND_URL=http://localhost:5173
# ── gRPC services ─────────────────────────────────────────────
APP_ENV_SURE_GRPC_URL=http://localhost:3008/api
APP_ENV_HRM_GRPC_URL=http://localhost:3001/api
APP_ENV_REPORT_GRPC_URL=http://localhost:3002/api
# ── Stripe (optional) ─────────────────────────────────────────
# APP_ENV_STRIPE_SECRET_KEY=sk_test_...
# APP_ENV_STRIPE_WEBHOOK_SECRET=whsec_...
# APP_ENV_STRIPE_PUBLISHABLE_KEY=pk_test_...
# ── CORS ──────────────────────────────────────────────────────
# APP_ENV_CORS_ORIGINS=http://localhost:5173