Configuration Reference

April 8, 2026 · View on GitHub

All runtime configuration is managed through a single .env file at the project root. Copy .env.example to .env and fill in your values before running docker compose up -d.


Quick Start

cp .env.example .env
# Edit .env with your values, then:
docker compose up -d --build

Area of Responsibility (AOR)

These three variables define your monitoring area and are consumed by the ADS-B, AIS, and RF Pulse pollers.

VariableDefaultDescription
CENTER_LAT45.5152AOR center latitude (decimal degrees, -90 to +90)
CENTER_LON-122.6784AOR center longitude (decimal degrees, -180 to +180)
COVERAGE_RADIUS_NM150AOR radius in nautical miles (10–300)

Tip: The AOR can also be updated at runtime without restarting containers via the Settings HUD or POST /api/config/location.

Default location: Portland, OR, USA (45.5152, -122.6784)


Map Rendering

VariableDefaultDescription
VITE_MAPBOX_TOKEN(empty)Mapbox GL JS access token. Required for 3D terrain and satellite imagery. Get one at mapbox.com. If empty, falls back to MapLibre + CARTO Dark Matter (no token needed).
VITE_ENABLE_MAPBOXtrueSet to false to force MapLibre even when a Mapbox token is present.

Aviation (ADS-B)

VariableDefaultDescription
HOLDING_PATTERN_THRESHOLD360Degrees of total turn within the window to trigger a holding pattern flag.
HOLDING_WINDOW_S300Rolling observation window in seconds (default 300s = 5 min).
HEADING_CHANGE_THRESHOLD2Minimum heading change in degrees to process (noise filter).
MIN_CIRCLE_DURATION90Minimum duration in seconds an aircraft must be circling to be flagged.
MIN_DIRECTIONAL_CONSISTENCY0.7Minimum dominant turn-direction ratio required before a hold is flagged.
MIN_VELOCITY_KNOTS0Minimum velocity in knots to consider for pattern detection.

Maritime (AIS)

The maritime poller supports an active-passive source model. By default it connects to AISStream.io first. If AISHUB_USERNAME is set, AISHub becomes an automatic fallback after repeated connection failures. You can also set AIS_PRIMARY_SOURCE=aishub to try AISHub first and keep AISStream as fallback.

VariableDefaultRequiredDescription
AISSTREAM_API_KEY(empty)Yes unless AIS_PRIMARY_SOURCE=aishub and AISHub is your intended primaryAISStream.io WebSocket API key. Get a free key at aisstream.io. Required for AISStream primary or fallback operation.
AISHUB_USERNAME(empty)NoEnables the optional AISHub WebSocket fallback. Leave empty to keep AISStream-only behavior.
AIS_PRIMARY_SOURCEaisstreamNoWhich source to try first: aisstream or aishub. If set to aishub, AISHUB_USERNAME must also be set.

AI / LLM Cognition

Sovereign Watch uses LiteLLM as a unified AI gateway. It supports a triple-model architecture: local (secure-core), Gemini (public-flash), and Claude (deep-reasoner).

Important: For detailed information on the three-layer configuration system, see the AI & LLM Configuration Guide.

VariableDefaultRequiredDescription
LITELLM_MODELsecure-coreNoDefault model ID for the UI Analyst (secure-core, public-flash, or deep-reasoner).
ANTHROPIC_API_KEY(empty)For ClaudeAnthropic API key for cloud models.
ANTHROPIC_MODELanthropic/claude-3-5-sonnet...NoLiteLLM model string for Claude.
GEMINI_API_KEY(empty)For GeminiGoogle AI Studio API key for Gemini models.
GEMINI_MODELgemini/gemini-1.5-flashNoLiteLLM model string for Gemini.
OPEN_API_BASEhttp://localhost:11434NoEndpoint for local model (default: Ollama).
OPEN_API_MODELopenai/llama3NoLocal model identifier used by LiteLLM.

The local model (secure-core) follows a "fail-closed" routing policy—it will never fall back to cloud providers to ensure data sovereignty. Use Gemini or Claude for higher reasoning capabilities when internet access is available.


RF Infrastructure

RadioReference

VariableDefaultRequiredDescription
RADIOREF_APP_KEY(empty)For RadioRefRadioReference application key. Ingestion is disabled if not set (along with username/password).
RADIOREF_USERNAME(empty)For RadioRefRadioReference account username.
RADIOREF_PASSWORD(empty)For RadioRefRadioReference account password.

RF Pulse Intervals

VariableDefaultDescription
RF_ARD_INTERVAL_H24Amateur Radio Directory fetch interval (hours)
RF_NOAA_INTERVAL_H168NOAA Weather Radio fetch interval (hours) — weekly

JS8Call / HF Radio Terminal

VariableDefaultDescription
KIWI_HOSTkiwisdr.example.comPrimary KiwiSDR node for JS8Call decoding. Find nodes at kiwisdr.com.
KIWI_PORT8073KiwiSDR node port (default 8073).
KIWI_FREQ14074Receive frequency in kHz. 14074 = 20m JS8Call calling frequency.
KIWI_MODEusbReceive mode. Use usb for JS8Call.
MY_GRIDCN85Your grid square locator. Used for distance/bearing and JS8 station plotting.

Note on WebSDR: The WebSDR Discovery feature is global and does not require pre-configuration in .env. It utilizes an integrated crawler to discover available nodes in real-time.


Database

VariableDefaultDescription
POSTGRES_PASSWORDpasswordTimescaleDB postgres user password. Change this for production deployments.
POSTGRES_DBsovereign_watchDatabase name (hardcoded in service configs; change with care).

Backend API

VariableDefaultDescription
ALLOWED_ORIGINShttp://localhost,http://127.0.0.1CORS allowed origins (comma-separated). Must include the exact frontend origin you use to open the UI, including protocol and port.

Examples:

  • Local Docker UI: ALLOWED_ORIGINS=http://localhost,http://127.0.0.1
  • Remote IP over plain HTTP: ALLOWED_ORIGINS=http://192.168.1.50
  • Remote domain over HTTPS: ALLOWED_ORIGINS=https://watch.example.com
  • Multiple allowed origins: ALLOWED_ORIGINS=http://localhost,http://192.168.1.50,https://watch.example.com

If this value is wrong, browsers can reject backend requests and WebSocket handshakes even when the containers themselves are healthy.


Internal Service Variables

These are set automatically by docker-compose.yml and do not need to be changed in .env:

VariableValueUsed By
KAFKA_BROKERSsovereign-redpanda:9092All pollers, Backend API
REDIS_HOSTsovereign-redisAIS, ADS-B, RF Pulse, Backend API
REDIS_PORT6379AIS, ADS-B, RF Pulse, Backend API
REDIS_URLredis://sovereign-redis:6379/0Infra Poller
DB_DSNpostgresql://postgres:...Backend API

GEODENT (GDELT OSINT)

VariableDefaultDescription
POLL_INTERVAL900GDELT fetch interval in seconds (15 minutes).

Feature Flags

The following features are automatically enabled or disabled based on credential presence:

FeatureEnabled When
RadioReference ingestionRADIOREF_APP_KEY + RADIOREF_USERNAME + RADIOREF_PASSWORD are all set
Mapbox 3D terrainVITE_MAPBOX_TOKEN is set and VITE_ENABLE_MAPBOX=true
Claude AI analysisANTHROPIC_API_KEY is set
Gemini AI analysisGEMINI_API_KEY is set

Use GET /api/config/features to check which features are currently enabled at runtime.


Example .env File

# ── Area of Responsibility ─────────────────────────────────────
CENTER_LAT=38.8977
CENTER_LON=-77.0365
COVERAGE_RADIUS_NM=100

# ── Map ────────────────────────────────────────────────────────
VITE_MAPBOX_TOKEN=pk.eyJ1IjoiZXhhbXBsZSIsImEiOiJjbH...
VITE_ENABLE_MAPBOX=true

# ── Maritime ───────────────────────────────────────────────────
AISSTREAM_API_KEY=your-aisstream-key-here
AISHUB_USERNAME=your-aishub-username
AIS_PRIMARY_SOURCE=aisstream

# ── AI Cognition ───────────────────────────────────────────────
LITELLM_MODEL=secure-core
ANTHROPIC_API_KEY=sk-ant-api03-...
GEMINI_API_KEY=AIzaSy...
# See Documentation/AI_Configuration.md for more detailed AI options

# ── RF Infrastructure ──────────────────────────────────────────
REPEATERBOOK_API_TOKEN=your-rb-token
RF_RB_RADIUS_MI=150

# RadioReference (optional)
# RADIOREF_APP_KEY=your-rr-app-key
# RADIOREF_USERNAME=your-rr-username
# RADIOREF_PASSWORD=your-rr-password

# ── JS8Call / HF Radio ─────────────────────────────────────────
KIWI_HOST=my-kiwisdr-node.example.com
KIWI_PORT=8073
KIWI_FREQ=14074
KIWI_MODE=usb
MY_GRID=FM18

# ── Database ───────────────────────────────────────────────────
POSTGRES_PASSWORD=change-me-in-production

Forcing Data Refreshes

High-latency infrastructure (FCC Towers, Submarine Cables, RadioReference) uses Redis caching to prevent redundant daily downloads. By default, these sync on a 7-day interval.

Use -1 to Bypass Start-Hour Gating

On a first-time setup, some services wait until a specific UTC hour (e.g., 3:00 AM) to avoid contention. You can force these to run immediately on boot by setting their start hour to -1 in your .env:

FeatureVariableForce-Sync Value
FCC TowersPOLL_FCC_START_HOUR-1
Satellite TLEsSPACE_TLE_FETCH_HOUR-1
RadioReferenceRF_RR_FETCH_HOUR-1

Space Pulse Intervals (Optional)

VariableDefaultDescription
SATNOGS_DB_INTERVAL_H24SatNOGS Transmitter DB fetch (hours)
SATNOGS_NETWORK_INTERVAL_H1SatNOGS Network Observations fetch (hours)
AURORA_INTERVAL_S300NOAA Aurora Forecast fetch (seconds, 5m)
KP_INTERVAL_S900NOAA Kp-Index fetch (seconds, 15m)

Manual Force-Sync via Redis

If a service has already run and you want to force it to run again before the 7-day cooldown expires, you must clear its timestamp from Redis using the following commands:

# Force FCC Towers refetch
docker exec -it sovereign-redis redis-cli DEL infra:last_fcc_fetch

# Force RadioReference refetch
docker exec -it sovereign-redis redis-cli DEL rf_pulse:last_radioref_fetch

# Force Submarine Cables refetch
docker exec -it sovereign-redis redis-cli DEL infra:last_cables_fetch

# Force Satellite TLE refetch
docker exec -it sovereign-redis redis-cli DEL space:last_tle_fetch

After clearing the key, restart the corresponding container to trigger the sync.