Demo

Environment variables

Base backend process env from base/backend/.env (see .env.sample). These are infrastructure settings for the host process — not plugin @InjectEnv keys.

Overview

Copy base/backend/.env.sample to base/backend/.env (or wire the same keys through Docker Compose). Plugin-scoped runtime keys use @InjectEnv / the env table — see PluginEnv. Never commit real secrets.

TopicDetail
Filebase/backend/.env (template: base/backend/.env.sample)
ComposeMany keys are also set under the backend service environment
PluginEnvOperator-editable plugin keys — different layer from this page
SecretsLocal sample values are for development only — rotate for staging / production

Runtime & identity

VariableDescriptionExample
NODE_ENVNode runtime modeproduction
MODEApp mode (template often uses dev)dev
BASE_VERSIONBase platform version — keep aligned with @quan-erp/* and image tags1.0.0
ORGANIZATION_IDOrganization identifier for this deploymentquan-erp
DEBUG_LOGOptional debug scopeplugin-manager

Service URLs

VariableDescriptionExample
FRONTEND_URLPublic frontend originhttp://localhost
BACKEND_URLBackend API basehttp://localhost:8080
DEV_TOOL_URLBase dev toolshttp://localhost:8081
PLUGIN_SERVER_URLPlugin serverhttp://localhost:8082
CORS_ALLOWED_ORIGINSComma-separated browser origins allowed to call the APIhttp://localhost:3000,...

Auth tokens

Rotate all token secrets before any shared or production deploy.

VariableDescriptionExample
ACCESS_TOKEN_SECRETJWT access-token signing secretchange-me
ACCESS_TOKEN_SECRET_EXPIRATION_TIMEAccess token TTL15m
REFRESH_TOKEN_SECRETJWT refresh-token signing secretchange-me
REFRESH_TOKEN_SECRET_EXPIRATION_TIMERefresh token TTL30d

OpenAI-compatible AI

VariableDescriptionExample
OPENAI_BASE_URLAPI base URLhttps://api.deepseek.com
OPENAI_API_KEYProvider API key (leave empty if unused)

Database

Inside Compose, hosts are usually service names (pgbouncer / db), not localhost. DB_PORT is often 6432 when traffic goes through PgBouncer.

VariableDescriptionExample
DATABASE_HOSTPostgres or PgBouncer host (alias used by some entrypoints)pgbouncer
DB_HOSTPostgres or PgBouncer hostpgbouncer
DB_PORTDatabase port (6432 via PgBouncer, 5432 direct)6432
DB_USERNAMEDatabase usernamepostgres
DB_PASSWORDDatabase passwordchange-me
DB_SCHEMASchema namequan-erp
DB_SYNCTypeORM synchronize — local/dev only; use migrations in staging/productiontrue

Redis

VariableDescriptionExample
REDIS_HOSTRedis service nameredis
REDIS_PORTRedis port6379
REDIS_PASSWORDRedis auth passwordchange-me

Cluster

VariableDescriptionExample
CLUSTER_MODEEnable multi-process clusterfalse
CLUSTER_MAX_COUNTMax worker processes when cluster is on2

Encryption & Firebase

Do not paste production private keys into git, docs, or chat — load them from a secret store or local .env only.

VariableDescriptionExample
ENV_ENCRYPTION_KEYKey used to encrypt sensitive env values at restchange-me-…
FIREBASE_CONFIGSingle-line JSON string for the Firebase Admin service account (push / auth){"type":"service_account",…}

Folders & files

VariableDescriptionExample
AVAILABLE_PLUGINS_FOLDERStaged plugin builds/app/available-plugins
INSTALLED_PLUGINS_FOLDERActive installed plugins/app/installed-plugins
APP_DATA_FOLDERPersistent app data root/app/data/data/
UPLOAD_FILE_TEMP_FOLDERTemporary upload staging/app/data/temp
UPLOAD_FILE_FOLDERPersisted uploads/app/data/data/
PLUGINS_ENV_FILEPlugin env JSON file path/app/data/data/plugin.env.json
RUNNER_FLOW_FILEWorkflow definitions directory/app/data/data/workflows/

Admin, limits & subscription

VariableDescriptionExample
ROOT_ADMIN_USERNAMEBootstrap root admin usernameadmin
ROOT_ADMIN_PASSWORDBootstrap root admin password — change outside local templatechange-me
MAX_USER_LIMITMax users for the org5
MAX_ACTIVE_USER_LIMITMax concurrently active users5
MAX_USER_SESSION_LIMIT_PER_USERSessions per user1
MAX_ORGANIZATION_BRANCHMax branches1
MAX_ROLE_LIMITMax roles5
MAX_SUBSCRIPTION_GRACE_PERIOD_DAYSGrace days after subscription end14
DEVELOPER_CONFIG_PASSWORDPassword gate for developer config UI / APIschange-me
SUBSCRIPTION_END_DATESubscription end date2026-01-01

Sample (.env.sample shape)

Illustrative keys matching base/backend/.env.sample. Replace every change-me value. Secrets below are placeholders only.

TSbase/backend/.env
1NODE_ENV=production 2 3MODE=dev 4BASE_VERSION=1.0.0 5ORGANIZATION_ID=quan-erp 6 7FRONTEND_URL=http://localhost 8BACKEND_URL=http://localhost:8080 9DEV_TOOL_URL=http://localhost:8081 10PLUGIN_SERVER_URL=http://localhost:8082 11 12DEBUG_LOG=plugin-manager 13 14ACCESS_TOKEN_SECRET=change-me 15ACCESS_TOKEN_SECRET_EXPIRATION_TIME=15m 16REFRESH_TOKEN_SECRET=change-me 17REFRESH_TOKEN_SECRET_EXPIRATION_TIME=30d 18 19OPENAI_BASE_URL=https://api.deepseek.com 20OPENAI_API_KEY= 21 22# database 23DATABASE_HOST=pgbouncer 24DB_HOST=pgbouncer 25DB_USERNAME=postgres 26DB_PASSWORD=change-me 27DB_PORT=6432 28DB_SCHEMA=quan-erp 29DB_SYNC=true 30 31# redis 32REDIS_HOST=redis 33REDIS_PORT=6379 34REDIS_PASSWORD=change-me 35 36CLUSTER_MODE=false 37CLUSTER_MAX_COUNT=2 38 39ENV_ENCRYPTION_KEY=change-me-32-char-hex-or-secret 40 41CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,http://localhost,https://localhost 42 43AVAILABLE_PLUGINS_FOLDER=/app/available-plugins 44INSTALLED_PLUGINS_FOLDER=/app/installed-plugins 45 46APP_DATA_FOLDER=/app/data/data/ 47UPLOAD_FILE_TEMP_FOLDER=/app/data/temp 48UPLOAD_FILE_FOLDER=/app/data/data/ 49PLUGINS_ENV_FILE=/app/data/data/plugin.env.json 50RUNNER_FLOW_FILE=/app/data/data/workflows/ 51 52FIREBASE_CONFIG={"type":"service_account","project_id":"your-project",...} 53 54ROOT_ADMIN_USERNAME=admin 55ROOT_ADMIN_PASSWORD=change-me 56 57MAX_USER_LIMIT=5 58MAX_ACTIVE_USER_LIMIT=5 59MAX_USER_SESSION_LIMIT_PER_USER=1 60MAX_ORGANIZATION_BRANCH=1 61MAX_ROLE_LIMIT=5 62MAX_SUBSCRIPTION_GRACE_PERIOD_DAYS=14 63DEVELOPER_CONFIG_PASSWORD=change-me 64SUBSCRIPTION_END_DATE=2026-01-01

Critical rules

RuleDetail
Start from sampleUse .env.sample — do not invent a second naming scheme
No secrets in gitNever commit real .env files or Firebase private keys
Version alignmentAlign BASE_VERSION with base images and @quan-erp/* packages
Production hardenTurn off DB_SYNC and rotate secrets before production
Two layersPlugin business config → PluginEnv (@InjectEnv); host infra → this file