Configuration
OpenHamClock is configured through a single .env file on the server. This section explains every category of setting and shows you a fully annotated example.
Two Layers of Configuration
OpenHamClock separates server configuration (the .env file) from
display preferences (the browser Settings panel). Understanding which is which
saves a lot of confusion:
| Layer | Where | Controls | Requires restart? |
|---|---|---|---|
| Server config | .env file on the server |
Callsign, grid, ports, API keys, WSJT-X, security, auto-update | Yes — restart the server after changes |
| Display prefs | ⚙️ Settings panel in the browser | Theme, layout, visible panels, map layers, units, filters | No — take effect immediately |
By default each browser saves its own display preferences independently.
On a self-hosted or Pi install you can set SETTINGS_SYNC=true in .env
to store all display preferences on the server — every browser that connects will share the same layout and filters.
Do not enable this on a multi-user shared instance.
The .env File
On first run the server automatically copies .env.example to .env.
The .env file is never overwritten by updates — your settings are safe
across upgrades.
Edit it with any plain-text editor:
# On Pi / Linux / macOS $ nano ~/openhamclock/.env # On Windows (PowerShell) PS> notepad openhamclock\.env
Restart the server after every change to .env:
# systemd (Pi / Linux) $ sudo systemctl restart openhamclock # Docker $ docker compose restart # Manual npm start — just Ctrl+C and npm start again
Callsign & Grid Locator
These two variables are the only ones that are truly required. Everything else has a sensible default.
# Your amateur radio callsign CALLSIGN=K0CJH # Maidenhead grid locator — 4 or 6 characters LOCATOR=DM79 # Optional: override the coordinates derived from LOCATOR # LATITUDE=39.7392 # LONGITUDE=-104.9903
VK2ABC, OE1XYZ/P).
IO91) give ±60 km accuracy. 6-character grids (e.g. IO91wm)
give ±3 km. The extra precision matters for satellite pass predictions and sunrise/sunset times.
Find your grid here.
Port & Network Settings
# Web UI port (default 3000 in production, 3001 in dev) PORT=3000 # localhost = only this machine # 0.0.0.0 = accessible from any device on your network HOST=localhost
Setting HOST=0.0.0.0 makes OpenHamClock reachable by any device on your LAN —
and potentially beyond, depending on your router/firewall.
If you open it to the internet, also set API_WRITE_KEY to prevent unauthorised access
to write endpoints (rotator control, settings sync).
Security Settings
# Protects POST endpoints (rotator, settings sync, N3FJP QSO logging) # Required for cloud / internet-facing installs. Any random string works. API_WRITE_KEY=change-me-to-something-secret # Additional allowed CORS origins (comma-separated) # Only needed if you access OHC from a custom domain # CORS_ORIGINS=https://yourdomain.com # Trust X-Forwarded-For headers (set true behind nginx/Caddy/Railway) TRUST_PROXY=false
API Keys (Optional)
Most of OpenHamClock's data sources are free and require no key. The following optional keys unlock additional features or lift rate limits:
| Variable | Service | What it unlocks |
|---|---|---|
QRZ_USERNAMEQRZ_PASSWORD |
QRZ.com | Callsign lookup — name, QTH, photo for DX spots. Requires a free QRZ account. |
VITE_AMBIENT_APP_KEYVITE_AMBIENT_API_KEY |
Ambient Weather | Personal weather station data in the Weather panel. |
WSJTX_RELAY_KEY |
Self-generated | Authentication for the WSJT-X relay agent (cloud installs only). Any random string. |
Current conditions and forecasts come from Open-Meteo, which is completely free and requires no registration. The browser fetches this data directly, bypassing the server entirely to avoid rate-limit issues.
DX Cluster Source
# auto | proxy | hamqth | dxspider DX_CLUSTER_SOURCE=auto # How long to keep spots in the panel (minutes) SPOT_RETENTION_MINUTES=30 # If using a self-hosted DX Spider proxy: # DXSPIDER_PROXY_URL=http://your-proxy:3002
WSJT-X UDP Integration
OpenHamClock listens for WSJT-X UDP packets on port 2237 by default — the same port
WSJT-X uses for its "UDP Server" feature. No relay agent is needed if WSJT-X and OpenHamClock
run on the same machine or LAN.
# Enable WSJT-X integration WSJTX_ENABLED=true # UDP port to listen on (must match WSJT-X Settings → Reporting → UDP Server Port) WSJTX_UDP_PORT=2237 # For multicast setups (advanced — leave blank for most installs) # WSJTX_MULTICAST_ADDRESS=224.0.0.1 # For cloud installs only — authentication key for the relay agent # WSJTX_RELAY_KEY=your-relay-secret
For the full WSJT-X setup walkthrough, including the relay agent for cloud installs, see WSJT-X / FT8.
Settings Sync
# Save all display settings on the server instead of in each browser # Enable for single-operator self-hosted / Pi installs SETTINGS_SYNC=false # Optional: custom path for the settings file # SETTINGS_FILE=/path/to/settings.json
With SETTINGS_SYNC=true, your layout, visible panels, map layers, theme, and all filters
are stored in data/settings.json on the server. Any browser that connects picks up the
same configuration automatically — useful when you access your Pi from multiple devices.
Display Defaults
These set the initial values loaded by new browsers. Users can always override them in the Settings panel.
# Theme: dark | light | legacy | retro | custom THEME=dark # Layout: modern | classic | dockable | tablet | compact | emcomm LAYOUT=modern # Units: imperial | metric DISTUNITS=imperial TEMPUNITS=imperial # Clock format: 12 | 24 TIME_FORMAT=24
Auto-Update
# Check for updates automatically (requires git clone install) AUTO_UPDATE_ENABLED=false # How often to check (minutes) AUTO_UPDATE_INTERVAL_MINUTES=60 # Run a check shortly after startup AUTO_UPDATE_ON_START=false # Exit after updating so systemd/pm2 restarts the service AUTO_UPDATE_EXIT_AFTER=true
Annotated .env Example
A typical configuration for a Raspberry Pi shack display with WSJT-X and rig control:
# ── Station ───────────────────────────── CALLSIGN=K0CJH LOCATOR=DM79ol # ── Server ────────────────────────────── PORT=3000 HOST=0.0.0.0 # accessible from tablets on the LAN # ── Display ───────────────────────────── THEME=dark LAYOUT=modern DISTUNITS=imperial TEMPUNITS=imperial TIME_FORMAT=24 # ── Settings sync (single-operator Pi) ── SETTINGS_SYNC=true # ── WSJT-X ────────────────────────────── WSJTX_ENABLED=true WSJTX_UDP_PORT=2237 # ── QRZ callsign lookups ───────────────── QRZ_USERNAME=K0CJH QRZ_PASSWORD=my-qrz-password # ── Auto-update ────────────────────────── AUTO_UPDATE_ENABLED=true AUTO_UPDATE_INTERVAL_MINUTES=60 AUTO_UPDATE_EXIT_AFTER=true
The complete list of every .env variable with defaults and valid values
is in the Reference section.