Environment Variables — Index¶
Pointer page. The canonical catalogue is
../env-reference.md(every var across all three repos, grouped by category) and the local-vs-prod diff is at../env-reference-diff.md. This page summarises how envs are loaded and where secrets come from.
Loading mechanism by repo¶
| Repo | Mechanism | Templates |
|---|---|---|
ebit-api |
env-cmd -f .env (via npm scripts); validated at startup by libs/shared/src/env-config/env.dto.ts |
.example.env, .local.env, .test.env |
ebit-fe |
Next.js built-in process.env + NEXT_PUBLIC_* client-side injection |
.example.env |
ebit-admin-fe |
Same as ebit-fe |
.example.env |
| Root compose | docker-compose.yml environment: blocks; ${VAR:-default} for host-port overrides |
— |
.env files are gitignored. Never commit real secrets; the templates ship dev-safe placeholders.
For ebit-api, the env validator is strict: @IsString() without @IsOptional() plus skipMissingProperties: false means any missing required variable crashes the boot. The validator is libs/shared/src/env-config/env.dto.ts — read it when adding a new env to know which decorators are needed.
Doppler — secrets management¶
Workspace: ebit-devops (slug 4d59619bf8c6f858715b). Per memory reference_doppler_workspace.
Layout¶
| Project | Secret count | Source baseline |
|---|---|---|
ebit-api |
~121 keys in dev_perf config |
uploaded from .local.env |
ebit-fe |
11 keys in dev_perf config |
uploaded from .example.env |
ebit-admin-fe |
11 keys in dev_perf config |
uploaded from .example.env |
Environments per project: dev / stg / prd (auto-created). Only the dev_perf branch config is populated today; stg / prd are intentionally empty until the perf rig hands over to a pre-prod environment.
Personal token (admin scope)¶
- Persisted:
~/.config/doppler/token(chmod 600). - Loaded in shell via
~/.bashrc:export DOPPLER_TOKEN=$(cat ~/.config/doppler/token 2>/dev/null). - Token rotation: requested by the user post-perf-run; coordinate with team lead.
Service tokens (container runtime)¶
Each project has a scoped service token used by doppler run --token <tok> -- node main.js inside containers (Dockerfiles in ebit-api wrap their CMD with doppler run). Tokens persist on the perf-rig workstation:
terraform/perf/secrets/doppler-token-ebit-apiterraform/perf/secrets/doppler-token-ebit-feterraform/perf/secrets/doppler-token-ebit-admin-fe
secrets/ is gitignored in terraform/perf/.gitignore.
CLI cheatsheet¶
doppler projects # list projects
doppler configs --project ebit-api # list configs in project
doppler secrets --project ebit-api --config dev_perf # view secrets
doppler secrets set KEY=value --project X --config dev_perf
doppler run --token <service-token> -- node main.js # run with secrets injected
Production deployment — where each var comes from¶
| Source | What lives there | Examples |
|---|---|---|
Doppler (stg / prd configs, when populated) |
Application secrets (JWT keys, DB URLs, API keys) | JWT_SECRET, DATABASE_URL, REDISCLOUD_URL, SENDGRID_API_KEY, all SENTRY_DSN_*, all OAuth client secrets |
Terraform output (terraform/perf/outputs.tf) |
Infrastructure-derived URLs and IPs | monitoring_url, grafana_url, jaeger_url, sut_public_ip, loadgen_public_ip |
| Build args (Dockerfile / Next.js build) | NEXT_PUBLIC_* client-side bundles, source-map upload |
NEXT_PUBLIC_API_URL, NEXT_PUBLIC_SENTRY_DSN, SENTRY_AUTH_TOKEN |
Compose ${VAR:-default} |
Host port overrides, dev-only flags | POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD |
.env (local only) |
Dev-safe placeholders | Same key set as .example.env |
For perf-test specifics see ../audits/doppler-perf-audit.md which documents the dev_perf audit, two showstoppers fixed in-place (FASTTRACK_JWT_PRIVATE_KEY / FASTTRACK_JWT_PUBLIC_KEY missing; JWT_SECRET contaminated with multi-line junk), and one pending issue (NODE_ENV=production breaks captcha bypass used by seed scripts).
Top must-change-for-prod vars¶
From ../env-reference-diff.md. Deploying without changing these will cause outages or vulnerabilities.
| Variable | Local default | Production requirement | Risk if unchanged |
|---|---|---|---|
DATABASE_URL |
postgresql://ebit:ebit@ebit-db:5432/ebit |
Managed Postgres, strong creds | Open DB, default password |
REDISCLOUD_URL |
redis://:cache@ebit-redis:6379/0 |
Managed Redis | Public Redis with password cache |
JWT_SECRET |
dev placeholder | Cryptographically random, ≥256-bit | Token forgery |
SESSION_SECRET |
dev placeholder | Cryptographically random | Session hijacking |
JWT_MFA_TEMP_SECRET |
dev placeholder | Cryptographically random | 2FA bypass |
NODE_ENV |
local |
production |
Sentry off, email bypass on, captcha bypass on |
APP_FE_ORIGIN |
http://localhost:3000 |
https://dropbet.com |
CORS blocks real users |
APP_FE_ORIGIN_ADMIN |
http://localhost:3001 |
https://admin.dropbet.com |
Admin CORS broken |
BASE_DOMAIN |
localhost |
dropbet.com |
Cookie scope wrong |
ADMIN_DEFAULT_PASSWORD |
admin |
Strong password or remove seed | Admin account with password admin |
The full table (must-change + must-provision + behaviour-by-NODE_ENV matrix) is in ../env-reference-diff.md.
Behaviour gated on NODE_ENV=local¶
These behaviours are on in local dev and off in production. Forgetting to flip means tests rely on something that doesn't exist in prod.
| Behaviour | When on |
|---|---|
Captcha bypass via x-captcha-token: pass |
NODE_ENV=local (apps/api/src/captcha/google/recaptcha.service.ts:28) |
Email sending bypassed (SendGrid sendEmail() returns immediately) |
NODE_ENV=local |
| Sentry error reporting disabled | NODE_ENV=local regardless of DSN |
| Pretty-printed logs (pino-pretty) | NODE_ENV=local + DEBUG_LOGS_PRETTY=true |
| Socket.IO admin UI | NODE_ENV=local + DEBUG_SOCKET_IO_ADMIN=true |
| In-memory feature flags | FEATURE_FLAGS_USE_LOCAL=true (regardless of NODE_ENV) |
| Demo seed user created | DEBUG_SEED_LOCAL=true (should never be set in prod) |
Adding a new env variable¶
- Add it to the relevant repo's
.example.envwith a dev-safe placeholder. - For
ebit-api: add the field tolibs/shared/src/env-config/env.dto.tswith the rightclass-validatordecorator (@IsString(),@IsOptional(),@IsNumber(), etc.). - For FE: prefix client-side vars with
NEXT_PUBLIC_*so Next.js inlines them. - Add a row to
../env-reference.mdunder the right category (Database / Redis cache / Redis bot / Auth / OAuth / etc.). - If it's required in production: add a row to
../env-reference-diff.md. - Push the secret to Doppler:
- If the var is
[SECRET], mark it in the env-reference table.
See also¶
../env-reference.md— full catalogue (every var, every repo, every category)../env-reference-diff.md— local-vs-prod sharp-edge checklist../audits/doppler-perf-audit.md—dev_perfconfig audit + showstoppers fixedreference_doppler_workspacememory — workspace layout, token persistence, CLI cheatsheet