Skip to main content

Configuration

A Docker deployment of OpenMapX reads one environment file: infra/docker/.env. Copy it from the tracked template and fill in the handful of required values:

cp infra/docker/.env.example infra/docker/.env

Both Docker Compose and the openmapx CLI auto-load this file from the directory containing the generated compose file, so you set a value once and both sides see it. At docker compose up time, Compose substitutes the values into the ${VAR} placeholders in the rendered YAML, and the service manifests forward the resolved values into each container's environment.

A few conventions are worth knowing before the tables:

  • Required values fail loud. The most critical keys are written into the generated stack as ${VAR:?error} — Compose refuses to start if they are unset, so production can't silently ship with a placeholder. They are marked Required below.
  • .env.example is the source of truth. Every key documented here exists in that file, usually with an inline comment and a default. When in doubt, read the template.
  • Most feature credentials live in the admin UI, not here. API keys for individual integrations (tile providers, transit feeds, weather, fuel prices, and so on) are managed at /admin/integrations. Anything you do set in .env always wins over an admin-stored value. See How it works for the service/integration model.
Recreate containers after editing

Changing .env only takes effect when the affected containers are recreated. Re-run docker compose up -d (Compose detects the changed file and recreates what's needed) or restart through the CLI's service commands.

Core / required

The values without which the stack won't start. Generate the secrets — never ship the placeholders.

VariableDescriptionRequired / Default
DOMAINPublic domain. Drives Traefik routing, the auth URLs (BETTER_AUTH_URL, PASSKEY_RP_ID, PASSKEY_ORIGIN), the web app's NEXT_PUBLIC_API_URL, and tile-server URLs. Point both an A and an AAAA record at the host.Default localhost
ACME_EMAILContact email for Traefik's automatic Let's Encrypt TLS certificates.Default admin@example.com
POSTGRES_PASSWORDPassword for the PostgreSQL/PostGIS database (used by postgis, app-api, and data-manager). Compose refuses to start if unset. Generate with openssl rand -hex 32.Required
OPENMAPX_HOST_DIRAbsolute host path of the OpenMapX repo checkout. The app-api container shells out to docker compose from inside the container and bind-mounts this path at the same path on both sides, so generated bind sources like ./data resolve correctly. Find it with pwd from the repo root.Required (no default)
DOCKER_GIDThe host's docker-socket group id. Containers that mount the docker socket run as a non-root user and must join this group, or the data-manager's MOTIS import/promote fails with "permission denied". Host-specific — find it with stat -c %g /var/run/docker.sock.Required. Default 999
Domain and TLS networking

Traefik serves HTTP/3 (QUIC) on UDP/443 and the OpenMapX Docker network is dual-stack. For IPv6 to reach published ports, the Docker daemon needs ip6tables enabled — the default in Docker Engine 27+, otherwise add {"experimental": true, "ip6tables": true} to /etc/docker/daemon.json and restart the daemon.

Secrets

Authentication and internal service secrets. The first two are enforced at runtime by the API; DATA_MANAGER_AUTH_TOKEN is enforced at the Compose layer. Generate each with the command shown.

VariableDescriptionRequired / Default
BETTER_AUTH_SECRETBetter Auth session-signing key. No fallback — the API refuses to start without it. Generate with npx @better-auth/cli@latest secret.Required
OPENMAPX_SECRETS_KEYSymmetric key (32 bytes, hex — 64 chars) used to encrypt integration secrets stored in the vault. If unset, integrations that store secrets in the admin panel won't decrypt after a restart. Generate with openssl rand -hex 32.Required (to use the secret vault)
DATA_MANAGER_AUTH_TOKENShared secret between app-api and the data-manager service; every data-manager mutation endpoint (downloads, hardlinks, dataset reload, conversions) requires it. Compose refuses to start without it in production; development generates a random ephemeral token. Generate with openssl rand -hex 32.Required in production
OPENMAPX_LOCAL_ADMIN_TOKENShared secret for the CLI ↔ API loopback admin short-circuit. When set, loopback requests only gain admin if they carry a matching X-OpenMapX-Local-Admin header (a CSRF guard); the CLI attaches it automatically. In production with no token, the loopback bypass is denied and the CLI needs a web-login session cookie. Generate with openssl rand -hex 32.Optional (recommended). Default unset

Docker & host wiring

How the containers find the host, the repo, and bind-mounted volumes. The required pieces of this group are listed under Core / required (OPENMAPX_HOST_DIR, DOCKER_GID); the rest are optional.

VariableDescriptionRequired / Default
OPENMAPX_CUSTOM_INTEGRATIONS_DIRContainer path where community integrations (installed by the admin panel or CLI) are mounted. Leave at the default unless you also change the app-api bind-mount target.Default /app/custom_integrations
UIDHost UID for bind-mounted volumes (Linux). macOS/Windows usually don't need this — Docker Desktop handles ownership.Optional. Commented 1000
GIDHost GID for bind-mounted volumes (Linux). Same caveat as UID.Optional. Commented 1000
DATA_MANAGER_URLBase URL app-api uses to reach the data-manager. Compose overrides this to the service-network DNS name automatically.Default http://localhost:4000 (pnpm dev); compose sets http://data-manager:4000
OPENMAPX_ENABLED_SERVICESPin a specific service selection (comma- or space-separated) for CI/repeatable deploys. Wins over the services-selection.json written by the admin UI / CLI.Optional. Default: services-selection.json

Authentication & OAuth

Optional social-login providers. Each requires an OAuth app registered with the provider.

VariableDescriptionRequired / Default
OSM_CLIENT_IDOpenStreetMap OAuth client id. Register at the OSM OAuth applications page.Optional. Commented
OSM_CLIENT_SECRETOpenStreetMap OAuth client secret.Optional. Commented
MAPILLARY_CLIENT_IDMapillary OAuth client id (re-uses the same app as MAPILLARY_TOKEN). Register at the Mapillary developer dashboard.Optional. Commented
MAPILLARY_CLIENT_SECRETMapillary OAuth client secret.Optional. Commented

Map style & tiles

Tile-source selection and keys. The NEXT_PUBLIC_* values (except NEXT_PUBLIC_API_URL) are read per-request via the web app's EnvProvider, so runtime changes reach both server and client components without a rebuild.

VariableDescriptionRequired / Default
NEXT_PUBLIC_STYLE_PROVIDERTile source. maptiler uses MapTiler Cloud (needs a key); openmapx uses the self-hosted tile stack (needs the tiles profile).Default maptiler
MAPTILER_KEYMapTiler Cloud API key. Also settable in /admin/settings → Map. Leave commented to manage from the admin UI; uncomment to lock a value (env wins).Optional. Commented
NEXT_PUBLIC_MAP_STYLE_URLBase URL of the self-hosted tileserver-gl; the web app appends /styles/<style>/style.json. With the built-in Traefik route this is ${DOMAIN}/tiles.Optional. Commented
NEXT_PUBLIC_TILES_URLSelf-hosted tile JSON URL.Optional. Commented
NEXT_PUBLIC_TRAFFIC_MIN_ZOOMMinimum zoom at which traffic tiles are requested.Optional. Commented 10
NEXT_PUBLIC_TRAFFIC_TILE_URL_TEMPLATEOverride URL template for the traffic raster layer.Optional. Commented
NEXT_PUBLIC_CYCLOSM_TILE_URL_TEMPLATEOverride URL template for the CyclOSM layer.Optional. Commented
NEXT_PUBLIC_TERRAIN_TILE_URL_TEMPLATEOverride URL template for the terrain layer.Optional. Commented

Street-level imagery

Mapillary tokens for street-level imagery. One stays server-side; the viewer token ships in the browser bundle.

VariableDescriptionRequired / Default
MAPILLARY_TOKENServer-side Mapillary token used by the /api/mapillary/* vector-tile proxy and integrations that fetch Mapillary on the user's behalf. Stays server-side — never expose it in NEXT_PUBLIC_*.Optional. Default unset
MAPILLARY_VIEWER_TOKENClient token for the in-browser Mapillary viewer. Ships in the public JS bundle — use a dedicated read-only OAuth app with a quota you're comfortable exposing. Leave unset to hide the on-map entry point entirely.Optional. Commented
Two different Mapillary tokens

MAPILLARY_TOKEN is secret and must never be copied into MAPILLARY_VIEWER_TOKEN or any NEXT_PUBLIC_* variable — Next.js would bundle it into the JavaScript the browser downloads.

Backend endpoint overrides

Self-hosted backends are normally resolved from the service registry. These overrides force a specific (often public) endpoint instead — useful when a backend runs outside the Compose stack. All optional and commented by default.

VariableDescriptionRequired / Default
OSRM_URLOSRM endpoint for road-snapping (driving / walking / cycling).Optional. Commented http://osrm:5000
VALHALLA_URLValhalla endpoint for isochrones, elevation, road-snap (bus), and the routing/directions provider. The default targets Stadia Maps' hosted Valhalla, which requires VALHALLA_API_KEY. A self-hosted Valhalla needs no key.Optional. Commented https://api.stadiamaps.com
VALHALLA_API_KEYAPI key for the hosted Valhalla above (free non-commercial tier at stadiamaps.com). Leave blank for a self-hosted Valhalla.Optional. Default unset
MOTIS_URLMOTIS endpoint for the transit manager and shared local MOTIS helpers.Optional. Commented http://motis:8081
OVERPASS_URLOverpass API endpoint used by the core Overpass client.Optional. Commented http://overpass:80
NOMINATIM_URLNominatim endpoint for station reverse-geocoding (bike / scooter / car sharing).Optional. Commented http://nominatim:8080
TRANSITOUS_URLTransitous endpoint for rental POIs used by shared-mobility integrations.Optional. Commented https://api.transitous.org

Regional defaults

Default regions and country filters used by the CLI and selected services, so you can keep them here instead of repeating CLI flags. A region passed on the command line overrides the env value for that invocation.

VariableDescriptionRequired / Default
OPENMAPX_REGIONShared default OSM region for selectors like openmapx data download osm, services build, and data convert overpass.Optional. Commented europe/germany
OSRM_REGIONPer-service OSRM build region (wins over OPENMAPX_REGION for that target).Optional. Commented
OTP_REGIONPer-service OTP build region.Optional. Commented
MOTIS_REGIONPer-service MOTIS build region.Optional. Commented planet
PELIAS_REGIONPer-service Pelias build region.Optional. Commented
TILESERVER_REGIONPer-service TileServer GL build region.Optional. Commented
OVERPASS_REGIONPer-service Overpass build region.Optional. Commented
TRANSITOUS_COUNTRIESCountry filter (e.g. de,at,ch) for data download gtfs and MOTIS Transitous config generation.Optional. Commented
INTEGRATION_GEOCODING_PROVIDERComma-separated geocoding fallback chain, tried left to right. Valid names: maptiler, photon, nominatim, pelias, motis, transitous, entur, db-ris.Optional. Default maptiler
PHOTON_REGIONRuntime download region for the self-hosted Photon index.Default planet

Service tuning

Knobs forwarded into the backend containers. Defaults are sensible for most deployments.

VariableDescriptionRequired / Default
NOMINATIM_THREADSImport/query thread count for the self-hosted Nominatim geocoder.Default 8
NOMINATIM_IMPORT_WIKIPEDIAImport Wikipedia importance scores during the Nominatim build.Default true
NOMINATIM_IMPORT_GB_POSTCODESImport GB postcodes.Default false
NOMINATIM_IMPORT_US_POSTCODESImport US postcodes.Default false
OVERPASS_SPACEOverpass database space limit, in bytes.Default 107374182400 (~100 GiB)
OVERPASS_FASTCGI_PROCESSESNumber of Overpass FastCGI worker processes.Default 4

Traffic & extra tile providers

Keys and overrides for the app-api traffic and tile proxies.

VariableDescriptionRequired / Default
TRAFFIC_PROVIDERTraffic data provider.Default tomtom
TOMTOM_TRAFFIC_KEYTomTom Flow tile-proxy key. Sign up at developer.tomtom.com.Optional. Default unset
TOMTOM_TRAFFIC_URLTomTom API base URL.Optional. Commented https://api.tomtom.com
TOMTOM_TRAFFIC_VERSIONTomTom Flow API version.Optional. Commented 4
TOMTOM_TRAFFIC_STYLETomTom Flow tile style.Optional. Commented relative-delay
TOMTOM_TRAFFIC_TILE_SIZETomTom tile size in pixels.Optional. Commented 256
TOMTOM_TRAFFIC_THICKNESSTomTom Flow line thickness.Optional. Commented 2
THUNDERFOREST_API_KEYThunderforest OpenCycleMap key (free Hobby Project key at thunderforest.com).Optional. Default unset
CYCLOSM_TILE_URLOverride URL for the CyclOSM tile proxy.Optional. Commented
WAYMARKED_CYCLING_TILE_URLOverride URL for the Waymarked Trails cycling layer.Optional. Commented
OPENTOPOMAP_TILE_URLOverride URL for the OpenTopoMap layer.Optional. Commented

Email

Used for email verification, 2FA, and email-change flows. The provider is auto-detected by priority: EmailLabs > Lettermint > SMTP. These are also settable in /admin/settings → Email / SMTP; env always wins.

VariableDescriptionRequired / Default
EMAIL_FROMSender address, e.g. OpenMapX <noreply@openmapx.example.com>.Optional. Commented
EMAILLABS_APP_KEYEmailLabs app key (emaillabs.io, 9k emails/mo free).Optional. Commented
EMAILLABS_SECRET_KEYEmailLabs secret key.Optional. Commented
EMAILLABS_SMTP_ACCOUNTEmailLabs SMTP account.Optional. Commented
LETTERMINT_API_TOKENLettermint API token (lettermint.co, 300 emails/mo free).Optional. Commented
SMTP_HOSTSMTP server hostname (any provider).Optional. Commented
SMTP_PORTSMTP port.Optional. Commented 587
SMTP_SECUREUse TLS on connect.Optional. Commented false
SMTP_USERSMTP username.Optional. Commented
SMTP_PASSSMTP password.Optional. Commented

Transitous & cron

Schedules and tuning for the daily Transitous transit-data sync.

VariableDescriptionRequired / Default
TRANSITOUS_SYNC_CRONCron schedule for the daily Transitous sync. Set to disabled to turn it off (e.g. on a staging host where you trigger manually).Optional. Commented 0 3 * * *
TRANSITOUS_FEED_PROXY_RELOAD_CRONCron schedule for the feed-proxy nginx-reload heartbeat — a safety net against a missed reload during sync.Optional. Commented */15 * * * *
Transitous feed-proxy key

The optional age private key used to decrypt AGE-ENCRYPTED: feed values has no env variable. Drop the file at infra/docker/secrets/transitous-feed-proxy.age on the host and re-render compose; the mount is omitted automatically when the file is absent. See infra/docker/secrets/README.md for the generation steps.

Advanced & optional

Lower-level toggles, retention, and legal-page metadata. All optional.

VariableDescriptionRequired / Default
LOG_LEVELFastify log level (trace, debug, info, warn, error, fatal).Optional. Commented info
OPENMAPX_DISABLE_LOCALHOST_AUTHSet to 1 to disable the loopback admin short-circuit entirely, regardless of OPENMAPX_LOCAL_ADMIN_TOKEN. Use on multi-tenant hosts where another local process could reach the API's loopback.Optional. Commented
ISOCHRONE_PROVIDERIsochrone provider. Use otp to route isochrones through OpenTripPlanner instead of Valhalla.Optional. Commented. Default valhalla
AUDIT_LOG_RETENTION_DAYSDays to keep admin audit-log entries before the daily prune.Optional. Commented 90
ADMIN_JOB_RETENTION_DAYSDays to keep finished admin jobs (in-flight jobs are never pruned).Optional. Commented 30
GITHUB_TOKENGitHub API token — raises the Transitous catalog fetch rate limit from 60 to 5000 req/h. Needed only on multi-tenant hosts.Optional. Commented
STORE_CATALOG_URLCommunity-service catalog URL for openmapx repos add.Optional. Commented https://openmapx.org/api/store/catalog.json
LEGAL_NAMEOperator legal name shown on /terms and /privacy.Optional. Commented
LEGAL_STREETOperator street address.Optional. Commented
LEGAL_POSTAL_CODEOperator postal code.Optional. Commented
LEGAL_CITYOperator city.Optional. Commented
LEGAL_COUNTRYOperator country.Optional. Commented
LEGAL_JURISDICTION_CITYCity of legal jurisdiction.Optional. Commented
LEGAL_EMAILLegal contact email.Optional. Commented
LEGAL_PHONELegal contact phone.Optional. Commented
Legal pages

The legal fields are optional but required for complete production /terms and /privacy pages. Leave them blank to omit the corresponding rows.

Per-integration and per-service overrides

Most integration credentials and per-service knobs are not set here — they are managed in the admin UI, and env values always win over admin-stored ones:

  • /admin/integrations — per-integration detail pages.
  • /admin/integrations/bulk — every integration on one page, plus a generated catalogue (Copy config / Copy credentials / Copy all) you can paste into .env.
  • /admin/services/<id> — per-service config, exposed as SERVICE_<ID>_<KEY> (for example SERVICE_VALHALLA_MEMORY_LIMIT=4g).

Nothing in these override blocks is required at deploy time. Paste only the lines you want to pin from the bulk page; the admin UI generates them on demand so the catalogue stays in sync with the live manifests.

Where to go next