Skip to main content
ShadowBroker reads configuration from environment variables at startup. The backend loads them from a .env file or from the process environment (Docker Compose environment: section). The frontend reads a single variable at runtime — no rebuild needed.

Backend variables

Create a .env file in the backend/ directory by copying the example:
cp backend/.env.example backend/.env
Then fill in your values.

Optional — data sources

All backend variables are optional. The backend starts cleanly without any of them, but missing keys degrade specific data layers. A startup warning is logged for each missing key.
Although no variables are technically required for the backend to start, AIS_API_KEY is essential for the ships layer. Without it the maritime layer will be empty.
VariableDescriptionEffect if missing
AIS_API_KEYWebSocket API key for AISStream.io real-time vessel tracking.Ships layer is empty.
OPENSKY_CLIENT_IDOAuth2 client ID for OpenSky Network. Provides flight gap-fill in Africa, Asia, and Latin America.Flight coverage reduced outside ADS-B Exchange range.
OPENSKY_CLIENT_SECRETOAuth2 client secret paired with OPENSKY_CLIENT_ID. Both must be set together.Same as above.
LTA_ACCOUNT_KEYAccount key for Singapore’s Land Transport Authority API. Enables the Singapore CCTV traffic camera layer.Singapore CCTV layer is empty.

Optional — security and networking

VariableDescriptionDefault
ADMIN_KEYSecret key that protects the /api/settings/api-keys, /api/settings/news-feeds, and /api/system/update endpoints. Pass it in the X-Admin-Key request header. If unset, those endpoints are open to anyone who can reach the backend — acceptable for local dev, not for production.Unset (endpoints unprotected)
CORS_ORIGINSComma-separated list of allowed CORS origins. By default the backend auto-detects localhost and the machine’s LAN IPs. Override this when your frontend is on a different host or port.Auto-detected localhost + LAN IPs

Frontend variables

The frontend reads one variable at runtime — it does not need to be baked in at build time (it is not a NEXT_PUBLIC_* build-time variable). Set it in the root .env file used by Docker Compose, or in the container’s environment directly.
VariableDescriptionDefault
BACKEND_URLFull URL of the backend that the Next.js server uses to proxy /api/* requests (e.g., http://backend:8000 in Docker, http://192.168.1.50:8000 for a remote host). The browser only ever talks to the frontend on port 3000 — port 8000 does not need to be exposed externally.http://backend:8000 (Docker internal) / http://localhost:8000 (local dev)

Setting variables

In a .env file

For local development, add variables to the appropriate .env file:
backend/.env
AIS_API_KEY=your-key-here
OPENSKY_CLIENT_ID=your-client-id
OPENSKY_CLIENT_SECRET=your-client-secret
ADMIN_KEY=your-secret-admin-key
# CORS_ORIGINS=http://192.168.1.50:3000
# LTA_ACCOUNT_KEY=your-lta-key

In Docker Compose

Pass variables via the environment: section in your compose.yml:
compose.yml
services:
  backend:
    environment:
      AIS_API_KEY: your-key-here
      OPENSKY_CLIENT_ID: your-client-id
      OPENSKY_CLIENT_SECRET: your-client-secret
      ADMIN_KEY: your-secret-admin-key
Or use an env file with Docker Compose:
compose.yml
services:
  backend:
    env_file:
      - backend/.env

At runtime (frontend)

Because BACKEND_URL is a runtime variable (not baked in at build time), you can update it without rebuilding the frontend image:
BACKEND_URL=http://192.168.1.50:8000 docker compose up -d
Or set it in the root .env file next to docker-compose.yml:
.env
BACKEND_URL=http://myserver.com:9096

Docker Swarm secrets

All backend variables support a _FILE variant for use with Docker Swarm secrets. When <VAR>_FILE is set, the backend reads the file at that path and loads its contents into <VAR> before any service code runs. The following variables support the _FILE suffix:
  • AIS_API_KEY_FILE
  • OPENSKY_CLIENT_ID_FILE
  • OPENSKY_CLIENT_SECRET_FILE
  • LTA_ACCOUNT_KEY_FILE
  • CORS_ORIGINS_FILE
  • ADMIN_KEY_FILE
Example Swarm service definition:
compose.yml
services:
  backend:
    environment:
      AIS_API_KEY_FILE: /run/secrets/ais_api_key
      ADMIN_KEY_FILE: /run/secrets/admin_key
    secrets:
      - ais_api_key
      - admin_key

secrets:
  ais_api_key:
    external: true
  admin_key:
    external: true
Create secrets with the Docker CLI:
echo "your-key-here" | docker secret create ais_api_key -
echo "your-admin-key" | docker secret create admin_key -
The _FILE loading runs before any service module is imported, so secrets are available to all Python code that reads os.environ at import time.

Startup validation

At startup, the backend calls validate_env() and logs the status of every variable. There are no hard-required variables — the app always starts — but two severity levels are used:
  • Critical warningADMIN_KEY is missing: logged at CRITICAL level. The backend starts, but sensitive endpoints (/api/settings/*, /api/system/update) are unprotected and open to any request.
  • Optional warningAIS_API_KEY, OPENSKY_CLIENT_ID, OPENSKY_CLIENT_SECRET, or LTA_ACCOUNT_KEY is missing: logged at WARNING level. The affected data layer will be empty or reduced.
Check the backend logs on first boot to confirm all variables are loaded correctly:
docker compose logs backend | grep -E "(CRITICAL|WARNING|✅)"

Build docs developers (and LLMs) love