Files
dotcom-arcade/docs/09-deployment/environment-variables.md
T

14 KiB

Environment Variables

Configuration reference for all Flashpoint Web services.

Backend Variables

Location: backend/.env (local development)

Server:

Variable Default Description
NODE_ENV development Environment: development, production, test

Note: Port (3100) and bind address (0.0.0.0) are hardcoded in the backend. In Docker, use API_PORT to map a different host port to the container.

Paths:

Variable Default Description
FLASHPOINT_PATH D:/Flashpoint (dev), /data/flashpoint (prod) Root Flashpoint directory. All other paths auto-derived. Edition (Infinity/Ultimate) auto-detected from version.txt.
FLASHPOINT_GAMES_PATH <FLASHPOINT_PATH>/Data/Games Override game ZIP directory (rarely needed).
APP_VERSION set by the Docker build Release version the server reports on Settings → Update. Baked into the official image from the release tag; set it by hand for a non-Docker deployment, or update checks stay off.

Authentication & Security:

Variable Default Description
JWT_SECRET auto-generated (dev) Secret for JWT signing (required in production)
JWT_EXPIRES_IN 1h Access token expiration (15m, 1h, 7d, etc.)
BCRYPT_SALT_ROUNDS 10 Password hash cost (higher = more secure but slower)
DOMAIN http://localhost:5173 Allowed CORS origin(s), comma-separated (see below)
COOKIE_SECURE auto Secure flag on auth cookies: auto, true, false
UV_THREADPOOL_SIZE 16 Concurrent file I/O threads (Node's own default is 4)
DB_WORKER_COUNT 4 Read-only SQLite query workers (1-16)

Generate secure JWT secret:

openssl rand -hex 64

COOKIE_SECURE — auth cookies over HTTP and HTTPS:

Browsers discard a cookie marked Secure when it arrives over plain HTTP, which logs users straight back out. auto therefore decides per request: cookies are marked Secure only on connections that actually used TLS, so one deployment can serve a LAN over HTTP and the internet over HTTPS at the same time.

Detection reads X-Forwarded-Proto, which is trusted only from a proxy. Set COOKIE_SECURE=true if your TLS-terminating proxy does not send that header, and false only if you deliberately want the flag off everywhere.

DOMAIN — allowed origins:

DOMAIN accepts one origin or a comma-separated list, so a single deployment can be reached over several addresses:

DOMAIN=http://192.168.0.118,https://flashpoint.example.com

The first entry is the primary origin, used where a single value is required. Requests from any listed origin are accepted, as are requests from hostnames in the domains table.

Two notes that save debugging time:

  • Same-origin requests are always allowed, so SERVE_FRONTEND=true deployments work at any address without listing it here. You only need DOMAIN when the UI is served from a different origin than the API, or behind a reverse proxy that rewrites the Host header.
  • Default ports are normalized away: http://host:80 and http://host are treated as the same origin, as are https://host:443 and https://host. Non-default ports must be written out, for example http://host:8080.

Rate Limiting:

Variable Default Description
RATE_LIMIT_WINDOW_MS 60000 Time window (ms)
RATE_LIMIT_MAX_REQUESTS 100 Max requests per window

Logging:

Variable Default Description
LOG_LEVEL info Level: error, warn, info, debug
LOG_FILE /app/logs/backend.log (prod) Log file path (unset in dev = stdout only)

Database Performance:

Variable Default Description
ENABLE_LOCAL_DB_COPY false Copy flashpoint.sqlite locally (for network storage SMB/NFS)
SQLITE_CACHE_SIZE -64000 SQLite page cache size (negative = KB, -64000 = 64MB)
SQLITE_MMAP_SIZE 268435456 Memory-mapped I/O size in bytes (256MB)
ENABLE_CACHE_PREWARM true Pre-load common queries on startup

Game Content Serving:

Variable Default Description
ENABLE_CGI false Enable PHP CGI execution for legacy game content
HOME_RECENT_HOURS 24 Hours to look back for "recently added" games

Frontend Serving:

The backend serves the built React UI in the single-image deployment, so the app and API share one origin.

Variable Default Description
SERVE_FRONTEND true in production, else false Serve the built frontend and SPA fallback from the backend
FRONTEND_DIST_PATH <backend>/../frontend/dist Location of the built frontend (rarely needed)
RUFFLE_DATA_PATH /app/data/ruffle in production Where Ruffle is installed. Must sit on a mounted volume, or an in-app update is lost when the container is recreated

Streaming:

Games that can't run in a browser, such as Java applets, can be streamed from a server-side container by a separate session manager (flashpoint-ultimate-server). The backend asks it which games are streamable and starts sessions for players. Browsers reach each stream at /stream/<id>/ on this site, so the reverse proxy in front of flashpoint-web must route /stream/ to the session manager, including WebSocket upgrades. Saves for streamed games are kept in each browser's IndexedDB.

Variable Default Description
STREAMING_API_URL - Session manager's internal API, e.g. http://flashpoint-session-manager:8080
STREAMING_API_TOKEN - Token the session manager expects. Streaming is off unless both are set

Trusted Header Login:

When a reverse proxy such as Authentik (forward auth) authenticates users in front of flashpoint-web, it can pass the signed-in username in a header so users don't log in twice. The backend believes the header only on connections from TRUSTED_PROXIES, checked against the connection's own address, not X-Forwarded-For. The proxy must always set the header, overwriting anything a client sends, and flashpoint-web must not be reachable from untrusted networks except through it.

Users are matched by username, so an existing account of that name is signed in; otherwise an account is created (the first one as admin, as with registration). New accounts get a random password. While signed in through the proxy, users can set a password from Settings without knowing the current one, then log in with it when reaching flashpoint-web without the proxy, such as on a LAN.

Variable Default Description
TRUSTED_HEADER_USERNAME - Header holding the username, e.g. X-authentik-username
TRUSTED_HEADER_EMAIL - Optional header holding the email used for new accounts
TRUSTED_PROXIES - Comma-separated proxy addresses or CIDR ranges allowed to set the header

With nginx and Authentik's forward auth, pass the header from the auth subrequest in each protected location:

auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-email $authentik_email;

OpenTelemetry:

Variable Default Description
OTEL_ENABLED false Enable distributed tracing and metrics
OTEL_EXPORTER_OTLP_ENDPOINT http://localhost:4318 OTLP collector endpoint
OTEL_API_KEY - API key for authentication
OTEL_SERVICE_NAME flashpoint-web Service name in traces/metrics
OTEL_TRACES_ENABLED true Enable trace export (when OTEL enabled)
OTEL_METRICS_ENABLED true Enable metrics export (when OTEL enabled)
OTEL_METRICS_EXPORT_INTERVAL 60000 Metrics export interval (ms)
OTEL_LOG_LEVEL info OTEL SDK log level

Frontend Variables

The frontend has no environment variables of its own. API calls use relative paths (/api), so they resolve against whatever origin serves the app.

  • Development: Vite dev server on port 5173 proxies /api to http://localhost:3100
  • Production: The backend serves the built UI and the API from the same origin

Docker Environment Variables

Location: .env in project root (used by docker-compose)

Required:

Variable Description
FLASHPOINT_HOST_PATH Host path to Flashpoint installation (bind-mounted as ro)
JWT_SECRET Secret for JWT signing (generate with openssl rand -hex 64)

Port Mapping:

Variable Default Description
WEB_PORT 80 Host port mapped to the container (serves UI + API)

Container Settings:

Variable Default Description
PUID 1000 Container user ID (match host user: id -u)
PGID 1000 Container group ID (match host user: id -g)
TZ UTC Container timezone
IMAGE_TAG latest Docker image tag (production compose only)
DATA_PATH ./data Host path for persistent data (production compose)
LOGS_PATH ./logs Host path for log files

All backend variables listed above are also passable via docker-compose. See docker-compose.yml for the full list with defaults.

Docker Compose Setup

Create .env file:

cat > .env << EOF
FLASHPOINT_HOST_PATH=/path/to/flashpoint
JWT_SECRET=$(openssl rand -hex 64)
DOMAIN=https://flashpoint.example.com
WEB_PORT=80
LOG_LEVEL=warn
EOF

Start services:

docker compose up -d

Environment Templates

Development (backend/.env):

NODE_ENV=development
FLASHPOINT_PATH=D:/Flashpoint
JWT_SECRET=development-secret-change-in-production
DOMAIN=http://localhost:5173
RATE_LIMIT_MAX_REQUESTS=1000
LOG_LEVEL=debug

Production (.env for Docker):

FLASHPOINT_HOST_PATH=/data/flashpoint
JWT_SECRET=CHANGE-THIS-TO-A-RANDOM-64-CHARACTER-STRING
DOMAIN=https://flashpoint.example.com
WEB_PORT=80
LOG_LEVEL=warn

Validation and Defaults

Required Variables:

Backend (local dev):

  • FLASHPOINT_PATH (only this is required; others auto-derive)

Docker Production:

  • FLASHPOINT_HOST_PATH (must point to Flashpoint installation)
  • JWT_SECRET (must be changed from default)

Verify configuration:

cd backend
node -e "require('dotenv').config(); console.log(process.env.FLASHPOINT_PATH)"

Security Best Practices

  1. Never commit .env files to version control
  2. Use strong JWT secrets (64+ characters) in production
  3. Restrict CORS origins to your domain only (no wildcards)
  4. Use HTTPS in production (update DOMAIN to https://)
  5. Limit exposed ports (don't expose all services)
  6. Rotate secrets periodically
  7. Use environment-specific files (.env.production, .env.development)
  8. Store secrets in secure management system (AWS Secrets Manager, HashiCorp Vault)
  9. Use read-only mounts for Flashpoint data in Docker

Next Steps