{"id":47241409,"url":"https://github.com/lhotakj/kinetiqo","last_synced_at":"2026-04-01T23:55:37.372Z","repository":{"id":342887500,"uuid":"1147962003","full_name":"lhotakj/kinetiqo","owner":"lhotakj","description":"Kinetiqo is a self-hosted data warehouse for your Strava activities. It synchronizes your data into a high-performance SQL database (PostgreSQL, MySQL/MariaDB, or Firebird), providing full ownership and control over your fitness history.","archived":false,"fork":false,"pushed_at":"2026-03-07T21:00:03.000Z","size":8761,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-08T01:52:40.346Z","etag":null,"topics":["analytics","cycling","docker","heatmap-visualization","strava","strava-api","website"],"latest_commit_sha":null,"homepage":"https://kinetiqo.lhotak.net/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lhotakj.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-02T12:15:44.000Z","updated_at":"2026-03-07T23:54:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lhotakj/kinetiqo","commit_stats":null,"previous_names":["lhotakj/kinetiqo"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/lhotakj/kinetiqo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lhotakj%2Fkinetiqo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lhotakj%2Fkinetiqo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lhotakj%2Fkinetiqo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lhotakj%2Fkinetiqo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lhotakj","download_url":"https://codeload.github.com/lhotakj/kinetiqo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lhotakj%2Fkinetiqo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30486800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-14T01:54:10.014Z","status":"online","status_checked_at":"2026-03-14T02:00:06.612Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","cycling","docker","heatmap-visualization","strava","strava-api","website"],"created_at":"2026-03-14T02:53:07.934Z","updated_at":"2026-04-01T23:55:37.355Z","avatar_url":"https://github.com/lhotakj.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kinetiqo\n\nKinetiqo is a self-hosted data warehouse for your Strava activities. It synchronizes your data into a high-performance SQL database (**PostgreSQL**, **MySQL/MariaDB**, or **Firebird**), providing full ownership and control over your fitness history.\n\nVisualize your progress with the **built-in Web UI** or integrate with your preferred business intelligence tools. For advanced analytics, Kinetiqo includes pre-configured **Grafana dashboards**, transforming your workout data into actionable insights.\n\n\u003e Full project documentation is available at [kinetiqo.lhotak.net](https://kinetiqo.lhotak.net) \n\n## Table of Contents\n\n- [Features](#features)\n- [Getting Started](#getting-started)\n  - [Dependencies](#dependencies)\n  - [Local Setup](#local-setup)\n  - [Configuration](#configuration)\n- [Command-Line Interface (CLI)](#command-line-interface-cli)\n  - [CLI Commands](#cli-commands)\n  - [Manual Sync](#manual-sync)\n  - [Web Interface](#web-interface)\n- [Building Docker Images](#building-docker-images)\n  - [Architecture: Two-Phase Build](#architecture-two-phase-build)\n  - [Local Build](#local-build)\n  - [CI/CD Workflows](#cicd-workflows)\n- [Deployment](#deployment)\n  - [Docker Run](#docker-run)\n  - [Docker Compose](#docker-compose)\n- [License](#license)\n\n## Features\n\n- 📊 **Advanced Visualization**: A streamlined web interface for daily monitoring and comprehensive Grafana dashboards for in-depth analysis.\n- ⚡ **Power Skills Analysis**: Visualize your best power efforts across different time intervals (5s to 1h) with a Strava-like spider chart.\n- 🗺️ **Interactive Maps**: View your activities on an interactive map with customizable styles, filtering, and performance optimizations for large datasets.\n- 🌓 **Dark Mode Support**: Fully supported dark theme with automatic system preference detection and manual toggle.\n- 📝 **Audit Logging**: Records all synchronization operations and data modifications, providing a complete audit trail within the Web UI.\n- 🔄 **Intelligent Synchronization**:\n  - **Full Synchronization**: Conducts a comprehensive audit of your Strava history, retrieving all activities and reconciling any deletions.\n  - **Incremental Synchronization**: Efficiently retrieves only the most recent activities, optimized for frequent updates.\n- 🐳 **Container-Native**: Architected for Docker environments, facilitating seamless integration into existing infrastructure.\n- ⏱️ **Automated Scheduling**: Includes a built-in cron scheduler to ensure data currency without manual intervention.\n- 💾 **Database Compatibility**:\n  - **PostgreSQL** (version 12+)\n  - **MySQL 8 / MariaDB 10+**\n  - **Firebird** (versions 3.0, 4.0, 5.0)\n- 🚀 **Performance Optimization**: Utilizes intelligent caching strategies to minimize API consumption and accelerate data retrieval.\n- 🔒 **Security**: Implements standard OAuth 2.0 protocols to safeguard user credentials.\n\n---\n\n## Getting Started\n\n### Dependencies\n\n- Python 3.13+\n- A running instance of PostgreSQL, MySQL/MariaDB, or Firebird.\n- Python package dependencies as listed in `requirements.txt`.\n- For Firebird, the client library is compiled from source inside the Docker base image (see [Building Docker Images](#building-docker-images)). For local (non-Docker) development on Ubuntu, install `libfbclient2`.\n\n### Local Setup\n\n1.  **Clone the Repository:**\n    ```bash\n    git clone https://github.com/lhotakj/kinetiqo.git\n    cd kinetiqo\n    ```\n    \n2.  **Install Firebird Client (Optional):**\n    Required only if using Firebird as the database backend. Install on Ubuntu:\n    ```bash\n    sudo apt update\n    sudo apt install -y libfbclient2\n    ```\n\n3.  **Initialize Virtual Environment:**\n    ```bash\n    python -m venv .venv\n    source .venv/bin/activate  # On Windows, use `.venv\\Scripts\\activate`\n    pip install -r requirements.txt\n    ```\n\n4.  **Environment Management with `direnv` (Optional):**\n    The `development` directory contains a script to configure `direnv` for automated environment management.\n    ```bash\n    cd development\n    ./setup-direnv.sh\n    ```\n    Upon configuration, `direnv` will automatically load the environment variables when entering the project directory.\n\n5.  **Configure Environment Variables:**\n    Create a `.env` file in the project root to define your configuration. This file is excluded from version control.\n    \n    **Example `.env` file:**\n    ```env\n    STRAVA_CLIENT_ID=12345\n    STRAVA_CLIENT_SECRET=your_secret_here\n    STRAVA_REFRESH_TOKEN=your_refresh_token_here\n    DATABASE_TYPE=postgresql  # or mysql or firebird\n    # PostgreSQL\n    POSTGRESQL_HOST=localhost\n    POSTGRESQL_PORT=5432\n    POSTGRESQL_USER=postgres\n    POSTGRESQL_PASSWORD=password\n    POSTGRESQL_DATABASE=kinetiqo\n    POSTGRESQL_SSL_MODE=disable\n    # MySQL\n    MYSQL_HOST=localhost\n    MYSQL_PORT=3306\n    MYSQL_USER=root\n    MYSQL_PASSWORD=password\n    MYSQL_DATABASE=kinetiqo\n    MYSQL_SSL_MODE=disable\n    # Firebird\n    FIREBIRD_HOST=localhost\n    FIREBIRD_PORT=3050\n    FIREBIRD_USER=firebird\n    FIREBIRD_PASSWORD=firebird\n    FIREBIRD_DATABASE=/db/data/kinetiqo.fdb\n    ```\n    - Set `DATABASE_TYPE` to `postgresql`, `mysql`, or `firebird` as needed.\n    - Only the relevant database section is required for your selected type.\n\n6.  **Secure Secret Storage with GPG (Optional):**\n    For enhanced security, environment files can be encrypted using GPG. The included `.envrc` script supports automatic decryption.\n    \n    1. **Import GPG Key:**\n       ```shell\n       gpg --import ~/.ssh/id_rsa\n       gpg --list-secret-keys\n       ```\n\n    2. **Encrypt Environment File:**\n       The following command encrypts `.env.development`.\n       ```shell\n       mkdir -p secrets\n       gpg -r \u003cyour-key-id\u003e -o secrets/development.gpg -e .env.development\n       ```\n       Ensure the unencrypted source file (`.env.development`) is included in `.gitignore`.\n\n### Configuration\n\nConfiguration is managed exclusively via environment variables.\n\n#### 1. Strava API Credentials\nRegister an application in the [Strava API Settings](https://www.strava.com/settings/api) to obtain the necessary credentials.\n\n| Variable | Description | Required |\n|----------|-------------|----------|\n| `STRAVA_CLIENT_ID` | Strava Application Client ID. | ✅ |\n| `STRAVA_CLIENT_SECRET` | Strava Application Client Secret. | ✅ |\n| `STRAVA_REFRESH_TOKEN` | Valid Refresh Token with `activity:read_all` scope. | ✅ |\n\n#### 2. Database Configuration\nDefine `DATABASE_TYPE` as either `postgresql` (default), `mysql`, or `firebird`.\n\n**PostgreSQL (Default):**\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `POSTGRESQL_HOST` | Database server hostname. | Required |\n| `POSTGRESQL_PORT` | Database server port. | `5432` |\n| `POSTGRESQL_USER` | Database username. | Required |\n| `POSTGRESQL_PASSWORD` | Database password. | Required |\n| `POSTGRESQL_DATABASE` | Database name. | Required |\n| `POSTGRESQL_SSL_MODE` | SSL connection mode (`disable`, `require`, etc.). | `disable` |\n\n**MySQL / MariaDB:**\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `MYSQL_HOST` | Database server hostname. | Required |\n| `MYSQL_PORT` | Database server port. | `3306` |\n| `MYSQL_USER` | Database username. | Required |\n| `MYSQL_PASSWORD` | Database password. | Required |\n| `MYSQL_DATABASE` | Database name. | Required |\n| `MYSQL_SSL_MODE` | SSL connection mode. | `disable` |\n\n\u003e **Note:** For MySQL, ensure the user has `CREATE` and `ALL PRIVILEGES` on the target database to allow for schema management.\n\n**Firebird:**\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `FIREBIRD_HOST` | Database server hostname. | Required |\n| `FIREBIRD_PORT` | Database server port. | `3050` |\n| `FIREBIRD_USER` | Database username. | Required |\n| `FIREBIRD_PASSWORD` | Database password. | Required |\n| `FIREBIRD_DATABASE` | Database file path or alias. | Required |\n\n\u003e **Note:** Kinetiqo will automatically create the Firebird database and schema if they don't exist. \n\u003e \n\u003e **Version Compatibility:** Tested and fully compatible with Firebird 3.0, 4.0, and 5.0. Uses only standard SQL features available in all these versions (SEQUENCE, TRIGGER, UPDATE OR INSERT, FIRST/SKIP pagination).\n\u003e \n\u003e **Permissions Required:**\n\u003e - The user must have rights to **create databases** on the Firebird server (typically `SYSDBA` or a user with equivalent privileges)\n\u003e - Once the database exists, the user needs rights to **create tables, sequences, triggers, and indexes**\n\u003e - For embedded Firebird, ensure the application has **write access** to the database file directory\n\n#### 3. Scheduling (Cron)\nThe Docker image includes a built-in cron scheduler powered by `dcron`. When the container starts, the entrypoint script registers cron jobs for any sync schedules you define via environment variables. If neither variable is set, no automatic synchronization occurs.\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `FULL_SYNC` | Schedule for full synchronization. | `0 3 * * *` (Daily at 3 AM) |\n| `FAST_SYNC` | Schedule for incremental synchronization. | `*/15 * * * *` (Every 15 minutes) |\n\nBoth variables accept standard **5-field cron expressions** (`minute hour day-of-month month day-of-week`):\n\n| Field | Allowed Values |\n|-------|---------------|\n| Minute | `0–59` |\n| Hour | `0–23` |\n| Day of month | `1–31` |\n| Month | `1–12` |\n| Day of week | `0–7` (0 and 7 = Sunday) |\n\n**How the two sync modes differ:**\n\n- **`FAST_SYNC`** runs an incremental sync (`--fast-sync`). It only fetches activities newer than the most recent one already in the database. This is lightweight and ideal for frequent scheduling (e.g., every 15 minutes) to keep data nearly real-time.\n- **`FULL_SYNC`** runs a comprehensive audit (`--full-sync`). It retrieves your entire Strava activity history, inserts any missing activities, and removes any that were deleted on Strava. This is heavier and best scheduled infrequently (e.g., once daily during off-hours).\n\n**Recommended setup:** Use both together — `FAST_SYNC` for frequent, low-cost updates and `FULL_SYNC` as a daily reconciliation pass.\n\n**Common cron examples:**\n\n| Expression | Meaning |\n|-----------|---------|\n| `*/15 * * * *` | Every 15 minutes |\n| `0 * * * *` | Every hour, on the hour |\n| `0 3 * * *` | Daily at 3:00 AM |\n| `0 3 * * 0` | Weekly on Sunday at 3:00 AM |\n| `0 */6 * * *` | Every 6 hours |\n\n#### 4. Web Interface Configuration\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `WEB_LOGIN` | Username for web access. | `admin` |\n| `WEB_PASSWORD` | Password for web access. | `admin123` |\n\n#### 5. Display Configuration\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `DATE_FORMAT` | Date format string (Python `strftime` syntax). | `%b %d, %Y` |\n\n\u003e **Note:** Synchronization errors are recorded in the `logs` database table and are accessible via the Web UI or `docker logs`.\n\n## Command-Line Interface (CLI)\n\nThe CLI tool is located in the `src` directory.\n\n### CLI Commands\n\n-   `--database` / `-d`: Selects the database backend (`mysql`, `postgresql`, or `firebird`), overriding environment variables.\n-   `sync`: Initiates data synchronization.\n    -   `--full-sync` / `-f`: Executes a full synchronization audit.\n    -   `--fast-sync` / `-q`: Executes an incremental synchronization.\n    -   `--period` / `-p`: Restricts full synchronization to a specific timeframe (e.g., '7d', '2w', '1m', '1y').\n    -   `--enable-strava-cache`: Activates API response caching.\n    -   `--cache-ttl`: Defines cache time-to-live in minutes (default: 60).\n    -   `--clear-cache`: Purges the cache prior to synchronization.\n-   `web`: Launches the web server.\n    -   `--port`: Specifies the listening port (default: 4444).\n    -   `--host`: Specifies the bind address (default: 0.0.0.0).\n-   `flightcheck`: Validates database connectivity and schema integrity.\n-   `version`: Outputs the current version information.\n\n### Manual Sync\n\nExecute the `sync` command from the `src` directory:\n\n```bash\n# Execute full synchronization\npython kinetiqo.py sync --full-sync\n\n# Execute full synchronization limited to the last 30 days\npython kinetiqo.py sync --full-sync --period 30d\n\n# Execute incremental synchronization\npython kinetiqo.py sync --fast-sync\n```\n\n### Web Interface\n\nLaunch the web server using the `web` command:\n\n```bash\n# Start server on default port (4444)\npython kinetiqo.py web\n\n# Start server on custom port with specific database backend\npython kinetiqo.py --database mysql web --port 8000\n```\n\n## Building Docker Images\n\n### Architecture: Two-Phase Build\n\nThe Docker build is split into **two independent phases** to keep day-to-day builds fast. Compiling the Firebird 5.x client library from source takes ~40 minutes on CI, so it is isolated into a dedicated **base image** that rarely needs rebuilding.\n\n```\nPhase 1 (rare)                          Phase 2 (every release)\n┌──────────────────────────┐            ┌──────────────────────────┐\n│  Dockerfile.firebird-base│            │  Dockerfile              │\n│                          │            │                          │\n│  python:3.13-alpine      │            │  python:3.13-alpine      │ ← pip install only\n│    + compile Firebird    │            │    (builder stage)       │\n│    + runtime libs        │            │                          │\n│           ↓              │            │  lhotakj/firebird-python │ ← FROM base image\n│  lhotakj/firebird-python │ ──────────│    + pip packages        │\n│         :3.13            │  used as   │    + app source          │\n└──────────────────────────┘  base      │           ↓              │\n                                        │  lhotakj/kinetiqo:x.y.z │\n                                        └──────────────────────────┘\n```\n\n| Phase | Image | Dockerfile | Rebuild when… |\n|---|---|---|---|\n| 1 — Base | `lhotakj/firebird-python:3.13` | `build/Dockerfile.firebird-base` | Python or Firebird version changes |\n| 2 — App | `lhotakj/kinetiqo:x.y.z` | `build/Dockerfile` | Application code or dependencies change |\n\n### Local Build\n\nBoth phases can be run entirely locally without pushing anything to Docker Hub.\n\n```bash\n# Phase 1 — build the base image (~40 min, one-time)\ncd build\n./build-base.sh\n\n# Phase 2 — build the application image (~2 min)\n./build.sh\n```\n\n`build-base.sh` compiles the Firebird client and loads `lhotakj/firebird-python:3.13` into your local Docker daemon. `build.sh` then uses that local image as its `FROM` target (with `--pull=false` to prevent Docker from reaching out to Docker Hub).\n\nYou only need to re-run `build-base.sh` when you change the Python or Firebird version. For day-to-day code changes, `./build.sh` alone is sufficient.\n\nBoth scripts accept the `--push` flag to publish to Docker Hub instead:\n\n| Script | Without `--push` | With `--push` |\n|---|---|---|\n| `build-base.sh` | Builds for `linux/amd64`, loads locally | Builds for `linux/amd64` + `linux/arm64`, pushes to DockerHub |\n| `build.sh` | Builds for `linux/amd64`, loads locally | Builds for `linux/amd64` + `linux/arm64`, pushes to DockerHub |\n\n`build-base.sh` also accepts `--python \u003cversion\u003e` and `--firebird \u003cversion\u003e` to override the defaults (`3.13` and `5.0.3`).\n\n### CI/CD Workflows\n\nTwo GitHub Actions workflows mirror the two-phase build:\n\n| Workflow | File | Trigger | Purpose |\n|---|---|---|---|\n| **Build Firebird Python Base Image** | `.github/workflows/build-base-image.yaml` | Manual (`workflow_dispatch`) | Compiles Firebird, pushes `lhotakj/firebird-python` to DockerHub |\n| **Build and publish Docker image** | `.github/workflows/build.yaml` | Manual or push to `main` with `/publish` or `/release` in commit message | Builds the app image, optionally pushes to DockerHub and creates a GitHub Release |\n\n#### Build Firebird Python Base Image\n\nTriggered **manually only** from the GitHub Actions UI. Inputs:\n\n| Input | Default | Description |\n|---|---|---|\n| `python_version` | `3.13` | Python version for the base Alpine image |\n| `firebird_version` | `5.0.3` | Firebird version to compile from source |\n| `platforms` | `linux/amd64,linux/arm64` | Target architectures |\n\nPushes two tags to DockerHub:\n- `lhotakj/firebird-python:3.13`\n- `lhotakj/firebird-python:3.13-firebird5.0.3`\n\n#### Build and publish Docker image\n\nTriggered **manually** (with `publish` and `create_release` boolean inputs) or automatically on push to `main` when the commit message contains `/publish` and/or `/release`.\n\n| Commit commands | Effect |\n|---|---|\n| `/publish` | Build and push the Docker image to DockerHub |\n| `/release` | Create a GitHub Release with an auto-generated changelog |\n\n## Deployment\n\n### Docker Run\n\nExample command to deploy Kinetiqo as a standalone container (supports PostgreSQL, MySQL/MariaDB, and Firebird):\n\n```bash\ndocker run -d \\\n  --name kinetiqo \\\n  -p 8080:4444 \\\n  -e STRAVA_CLIENT_ID=\"your_id\" \\\n  -e STRAVA_CLIENT_SECRET=\"your_secret\" \\\n  -e STRAVA_REFRESH_TOKEN=\"your_token\" \\\n  -e DATABASE_TYPE=\"postgresql\" \\\n  -e POSTGRESQL_HOST=\"host.docker.internal\" \\\n  -e POSTGRESQL_PORT=5432 \\\n  -e POSTGRESQL_USER=\"postgres\" \\\n  -e POSTGRESQL_PASSWORD=\"password\" \\\n  -e POSTGRESQL_DATABASE=\"kinetiqo\" \\\n  -e FAST_SYNC=\"*/15 * * * *\" \\\n  -e FULL_SYNC=\"0 3 * * *\" \\\n  -e WEB_LOGIN=\"admin\" \\\n  -e WEB_PASSWORD=\"securepassword13\" \\\n  lhotakj/kinetiqo:latest\n```\n\n- Set `DATABASE_TYPE` and only the relevant database variables for your chosen backend (`postgresql`, `mysql`, or `firebird`).\n- The web UI will be available at http://localhost:8080\n\n**Cron schedule in this example:**\n\n| Variable | Value | Effect |\n|----------|-------|--------|\n| `FAST_SYNC` | `*/15 * * * *` | Runs an incremental sync every 15 minutes — quickly picks up any new activities recorded on Strava. |\n| `FULL_SYNC` | `0 3 * * *` | Runs a full audit every day at 3:00 AM — reconciles all activities and detects deletions on Strava. |\n\nBoth schedules are optional. If omitted, no automatic sync occurs and you would need to trigger syncs manually via the Web UI or CLI.\n\n### Docker Compose\n\nFor a production-grade deployment, use Docker Compose. The following configuration includes PostgreSQL and Grafana. You can adapt for MySQL or Firebird as needed.\n\n**`docker-compose.yml`:**\n\n```yaml\nservices:\n  kinetiqo:\n    image: lhotakj/kinetiqo:latest\n    container_name: kinetiqo\n    restart: always\n    ports:\n      - \"80:4444\"\n    environment:\n      - STRAVA_CLIENT_ID=${STRAVA_CLIENT_ID}\n      - STRAVA_CLIENT_SECRET=${STRAVA_CLIENT_SECRET}\n      - STRAVA_REFRESH_TOKEN=${STRAVA_REFRESH_TOKEN}\n      - DATABASE_TYPE=postgresql  # or mysql or firebird\n      - POSTGRESQL_HOST=postgresql\n      - POSTGRESQL_PORT=5432\n      - POSTGRESQL_USER=postgres\n      - POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD}\n      - POSTGRESQL_DATABASE=kinetiqo\n      - FAST_SYNC=\"*/15 * * * *\"\n      - FULL_SYNC=\"0 3 * * *\"\n      - WEB_LOGIN=admin\n      - WEB_PASSWORD=securepassword13\n    depends_on:\n      - postgresql\n  postgresql:\n    image: postgres:latest\n    container_name: postgresql\n    restart: always\n    environment:\n      - POSTGRES_USER=postgres\n      - POSTGRES_PASSWORD=${POSTGRESQL_PASSWORD}\n      - POSTGRES_DB=kinetiqo\n    volumes:\n      - postgresql_data:/var/lib/postgresql/data\n  grafana:\n    image: grafana/grafana:latest\n    container_name: grafana\n    restart: always\n    ports:\n      - \"3000:3000\"\n    environment:\n      - GF_SECURITY_ADMIN_PASSWORD=admin\n    depends_on:\n      - postgresql\nvolumes:\n  postgresql_data:\n```\n\nFor MySQL or Firebird, replace the `postgresql` service and environment variables accordingly.\n\nCreate a `.env` file in the same directory:\n\n```env\nSTRAVA_CLIENT_ID=your_strava_client_id\nSTRAVA_CLIENT_SECRET=your_strava_client_secret\nSTRAVA_REFRESH_TOKEN=your_strava_refresh_token\nPOSTGRESQL_PASSWORD=your_secure_password\n```\n\nDeploy the stack:\n\n```bash\ndocker-compose up -d\n```\n\n- For more details and advanced configuration, see the project documentation at [kinetiqo.lhotak.net](https://kinetiqo.lhotak.net).\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flhotakj%2Fkinetiqo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flhotakj%2Fkinetiqo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flhotakj%2Fkinetiqo/lists"}