Found the statistics-for-strava repository on GitHub with frequent updates and comprehensive documentation. Decided to deploy it myself.

Deployment

  • First, register a new app on Strava’s API page. Fill in the Authorization Callback Domain with your deployment domain (mine is strava.kyxie.me). After successful creation, you’ll receive Client ID, Client Secret, Access Token, and Refresh Token.

  • Create docker-compose.yml and modify according to your setup. I integrated it with cloudflared and deployed it publicly on port 8000 of the host machine:

    services:
      app:
        image: robiningelbrecht/strava-statistics:latest
        container_name: strava
        restart: unless-stopped
        volumes:
          - ./config:/var/www/config/app
          - ./build:/var/www/build
          - ./storage/database:/var/www/storage/database
          - ./storage/files:/var/www/storage/files
        env_file: ./.env
        ports:
          - 8000:8080
        networks:
          - cloudflared
    
    networks:
      cloudflared:
        external: true
    
  • Create .env file. You can leave STRAVA_REFRESH_TOKEN empty for now, as it’s needed after the container starts:

    # The client id of your Strava app.
    STRAVA_CLIENT_ID=YOUR_CLIENT_ID
    # The client secret of your Strava app.
    STRAVA_CLIENT_SECRET=YOUR_CLIENT_SECRET
    # You will need to obtain this token the first time you launch the app. 
    # Leave this unchanged for now until the app tells you otherwise.
    # Do not use the refresh token displayed on your Strava API settings page, it will not work.
    STRAVA_REFRESH_TOKEN=YOUR_REFRESH_TOKEN_OBTAINED_AFTER_AUTH_FLOW
    # Valid timezones can found under TZ Identifier column here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
    TZ=America/Toronto
    
    # The UID and GID to create/own files managed by statistics-for-strava
    PUID=1000
    PGID=1000
    
  • Add the domain in your reverse proxy. statistics-for-strava listens on port 8080. I named the container strava:

    Subdomain: strava
    Domain: your_domain
    Type: HTTP
    URL: strava:8080
    
  • After startup, a config folder is created. Create config.yaml file inside (must be yaml, not yml):

    general:
      # The URL on which the app will be hosted. This URL will be used in the manifest file. 
      # This will allow you to install the web app as a native app on your device.
      appUrl: 'http://localhost:8080/'
      # Optional subtitle to display in the navbar.
      # Useful for distinguishing between multiple instances of the app.
      # Leave empty to disable.
      appSubTitle: null
      # Optional, a link to your profile picture. Will be used to display in the nav bar and link to your Strava profile.
      # Any image can be used; a square format is recommended.
      # Leave empty to disable this feature.
      profilePictureUrl: null
      # Optional, full URL with ntfy topic included. This topic will be used to notify you when a new HTML build has run.
      # Leave empty to disable notifications.
      ntfyUrl: null
      athlete:
        # Your birthday. Needed to calculate heart rate zones.
        birthday: 'YYYY-MM-DD'
        # The formula used to calculate your max heart rate. The default is Fox (220 - age).
        # Allowed values: arena, astrand, fox, gellish, nes, tanaka (https://pmc.ncbi.nlm.nih.gov/articles/PMC7523886/table/t2-ijes-13-7-1242/)
        # Or you can set a fixed number for any given date range.  
        maxHeartRateFormula: 'fox'
        # If you're not sure about your zones, leave this unchanged — the defaults are sensible.
        heartRateZones:
          # Relative or absolute. 
          # Relative will treat the zone numbers as percentages based on your max heart rate, while absolute will treat them as actual heartbeats per minute.
          # This mode will apply to all heart rate zones you define.