# Copy to .env and edit. Every value here is the default unless stated otherwise. # The first-run walkthrough lives in the README; start there. # # Reminder: docker compose reads this file when a container is CREATED. After changing anything, # run `docker compose up -d --force-recreate` — a plain `restart` keeps the old values. ### Polar client ############################################################## # Required. Create a client at https://admin.polaraccesslink.com. POLAR_CLIENT_ID= # Required. Also accepts a _FILE variant pointing at a Docker secret, e.g. # POLAR_CLIENT_SECRET_FILE=/run/secrets/polar_client_secret POLAR_CLIENT_SECRET= # Where this connector is reachable in a browser. Used to build the OAuth redirect URI, which must # match a redirect URL registered for your client. Leave empty if your client has exactly one # registered URL — Polar then uses it automatically. PUBLIC_URL=http://localhost:8080 # The redirect URI to send, verbatim, overriding the PUBLIC_URL + /callback default. Needed when the # URL registered for your client is not /callback: Polar's admin page accepts a path, but # its authorization endpoint may then reject that URL and honour only the bare origin — the symptom is # "Oops, something went wrong somewhere along the way." instead of a consent page. This connector # answers the callback at / as well, so REDIRECT_URI=http://:8080 completes the flow. Whatever # you set is sent unchanged, trailing slash included, because Polar compares it byte for byte. #REDIRECT_URI= ### Where things live ######################################################## # Dreeve's watch folder, inside the container. Map it to the real one in docker-compose.yml. #WATCH_DIR=/watch # The ledger: which exercises have already been fetched. Losing it means downloading again. #STATE_DIR=/state # The access token and webhook signing key. Keep this volume and you never authorize twice. #POLAR_TOKENS=/tokens ### What to fetch ############################################################ # How far back to reach on the first run. Polar only keeps 30 days, so -30d is "everything there is". # Resolved once and then remembered, so a restart does not skip exercises recorded while down. # Set this to 'now' if you have already exported your history from Polar Flow by hand. #SINCE=-30d # Only these sports, comma separated, e.g. running,cycling. Matched against Polar's sport or its # detailed sport name. Empty means everything. #SPORTS= # Some exercises have no FIT file. Dreeve imports TCX and GPX too, so those are fetched instead. # Set to 'none' to record them as having no file. #FALLBACK_FORMAT=tcx # What to do when the file is already in the watch folder: skip or overwrite. #ON_CONFLICT=skip # How many times an exercise may fail before it is left alone. #MAX_ATTEMPTS=5 ### Pace ###################################################################### # Seconds between cycles. Polar's published budget is 520 requests per 15 minutes for one user, and a # cycle costs one list call plus one download per new exercise — so this uses about 2% of it. #POLL_INTERVAL=900 # Randomises the interval by ±this percentage, so every deployment of this image does not hit Polar # on the same second. #POLL_JITTER_PCT=10 # Spreads a first run over several cycles instead of asking for everything at once. The remainder # shows up in /status as a backlog. #MAX_DOWNLOADS_PER_CYCLE=25 # Pause between downloads. Polar is far more forgiving of a slow client than a busy one. #DOWNLOAD_DELAY_SECONDS=1 # After a 429 the interval backs off exponentially, up to this many seconds (6 hours). #MAX_BACKOFF_SECONDS=21600 ### Webhook (optional) ######################################################## # A publicly reachable HTTPS URL ending in /webhook. Set it and new exercises arrive within seconds # instead of at the next poll. Polling stays on either way, so this only affects latency. # Requires WEBHOOK_ADDR to be set alongside it: Polar posts to that listener, not to HTTP_ADDR. #WEBHOOK_URL= # The public listener, serving /webhook and nothing else. This is the only port you publish to the # internet. 0.0.0.0:8081 is the conventional value. #WEBHOOK_ADDR=off ### Weight (optional) ######################################################### # Record your Polar weight in Dreeve whenever it changes. Off unless set to true. #WEIGHT_SYNC=false # Dreeve's address as this container reaches it. Required when WEIGHT_SYNC is on. #DREEVE_URL=http://dreeve:8080 # A Dreeve API key (drv_..., Settings -> Security in Dreeve's admin panel); the MCP key (drvm_...) # does not work here. Required when WEIGHT_SYNC is on. Also accepts DREEVE_API_KEY_FILE. #DREEVE_API_KEY= # kg or lb: the unit system Dreeve is set to under Appearance. Dreeve reads the number in that unit # and its API does not say which one it is, so a mismatch stores 80 kg as 80 lb. #DREEVE_WEIGHT_UNIT=kg ### Operations ################################################################ # The local listener: /healthz, /status, /authorize, /callback and /. Keep it on your LAN — never # port-forward it. Set to 'off' to disable, in which case authorization moves to # `docker compose run --rm polar-connector login` and the healthcheck falls back to the heartbeat # file in STATE_DIR. #HTTP_ADDR=0.0.0.0:8080 # 0 runs forever. Anything else runs that many cycles and exits, which is useful for testing. #MAX_CYCLES=0 # List what would be downloaded, download nothing and leave the ledger untouched. #DRY_RUN=false #LOG_LEVEL=info #LOG_FORMAT=text # Ownership of the files this connector writes. Set both to the uid/gid Dreeve runs as, or leave # them unset to run as root. #PUID=1000 #PGID=1000 #UMASK=022 TZ=Europe/Brussels