Skip to content

Configuration

Settings live in deploy/.env (from .env.example); tokens live in secret files. Unset or empty means the default.

coachd

SettingDefaultMeaning
COACHD_TIMEZONErequiredYour timezone, for example Europe/Bratislava. Days, weeks and workout dates follow it.
COACHD_GARMIN_KEY_EXPIRESrequiredExpiry date of the Garmin key in secrets/garmin_api_key (YYYY-MM-DD); coachd warns before it. A key renewed on the page applies if it expires later.
COACHD_DEMOfalsetrue runs on made-up Garmin data, with no Garmin key: Try it with demo data. Leave the Garmin key settings unset with it. A demo data directory and a real one never mix: each mode refuses the other’s.
COACHD_IMAGEcoachd:localThe image to run, for example ghcr.io/stefiix92/coachd:<version>@sha256:<digest>. Empty builds and runs coachd:local. See Get the image.
COACHD_VERSIONdevThe version string baked into the image by docker compose build.

Public lane

SettingDefaultMeaning
COACHD_PUBLIC_AUTHsee meaningaccess or builtin. Empty means access when all three COACHD_ACCESS_* are set; otherwise there is no page and no public /mcp: the public listener serves only the watch API if COACHD_DEVICE_API=on, else it is disabled.
COACHD_PUBLIC_URLnonePublic origin of the runner page: https://<host>[:port], no path. Required in Access and built-in mode. It is the WebAuthn origin (passkeys are bound to this host), and in built-in mode every OAuth URL coachd emits is built from it. http is accepted only for http://localhost[:port], for development.
COACHD_ACCESS_TEAM_DOMAINnoneAccess mode: <team>.cloudflareaccess.com.
COACHD_ACCESS_AUDnoneAccess mode: the Access application’s AUD tag.
COACHD_ACCESS_ALLOWED_EMAILnoneAccess mode: your email. Set all three COACHD_ACCESS_* together or leave all empty; leave them empty in built-in mode.
COACHD_OAUTH_DCRoffBuilt-in mode: on allows dynamic client registration for apps that cannot identify themselves with a client metadata document URL. Claude and ChatGPT do not need it.

Optional features

SettingDefaultMeaning
COACHD_NTFY_URLoffFull ntfy topic URL, for example https://ntfy.sh/<secret-topic>. Needs the public lane and COACHD_PUBLIC_URL. See ntfy.
COACHD_WEBHOOK_URLoffWhere to POST the post-run webhook. Treat it as a secret.
COACHD_DEVICE_APIoffon serves /device/v1/* on the public listener for the watch app. Anything other than on, off or empty is an error.

Tuning

SettingDefaultMeaning
COACHD_POLL_INTERVAL1hScheduled sync interval (Go duration, > 0).
COACHD_BACKFILL_DAYS730Days of history to backfill on first start (positive integer).
COACHD_BACKFILL_DELAY1sPause between paced Garmin requests (Go duration, >= 0): backfill requests, FIT downloads, long-outage catch-up chunks and deletion-reconcile probes.
COACHD_SYNC_MIN_INTERVAL10mMinimum interval between agent request_sync calls (Go duration, > 0).

Grafana

SettingMeaning
COMPOSE_FILEThe single on/off switch for the overrides: compose.yaml:compose.cloud.yaml (Grafana Cloud), compose.yaml:compose.local.yaml (local Grafana) or compose.yaml:compose.cloud.yaml:compose.local.yaml. When turning one off again, run docker compose up -d --remove-orphans.
GRAFANA_CLOUD_OTLP_ENDPOINT, GRAFANA_CLOUD_OTLP_USERGrafana Cloud OTLP endpoint and user, for traces. Read only with the cloud override.
GRAFANA_CLOUD_PYROSCOPE_URL, GRAFANA_CLOUD_PYROSCOPE_USERGrafana Cloud Pyroscope URL and user, for profiles. Read only with the cloud override.
GRAFANA_PDC_CLUSTER, GRAFANA_PDC_HOSTED_GRAFANA_IDPrivate Data Source Connect cluster and hosted Grafana ID. Read only with the cloud override.
GRAFANA_ROOT_URLThe local Grafana’s URL on the Tailscale node, for example https://raspberrypi-coachd.<tailnet>.ts.net/grafana/. Required with the local override.

Set by compose

compose.yaml also sets settings you don’t change: the secret file paths (COACHD_GARMIN_API_KEY_FILE, COACHD_NTFY_TOKEN_FILE, and COACHD_WEBHOOK_TOKEN_FILE from a compose override), the data directory (COACHD_DATA_DIR, /data), the listeners (COACHD_PUBLIC_ADDR :8080, COACHD_PRIVATE_ADDR :8081, COACHD_OPS_ADDR :9090 for /livez, /readyz and pprof) and the telemetry endpoint (Alloy).

Last updated on