PromptHub
Self-hosting Fitness Technology

Stop Giving Strava Your Data! Self-Host Fitness with Endurain

B

Bright Coding

Author

14 min read
61 views
Stop Giving Strava Your Data! Self-Host Fitness with Endurain

Stop Giving Strava Your Data! Self-Host Fitness with Endurain

Every morning, millions of runners, cyclists, and athletes lace up their shoes, start their GPS watches, and unknowingly hand over their most intimate data to Silicon Valley giants. Your heart rate zones, your exact home location, your workout patterns, your sleep recovery metrics—all of it feeding algorithms you don't control, stored in jurisdictions you didn't choose, monetized in ways you'll never see.

What if I told you there's a better way? A way to keep every heartbeat, every route, every personal record exactly where it belongs: under your own roof.

Enter Endurain, the self-hosted fitness tracking service that's making privacy-conscious athletes abandon Strava in droves. Built by a passionate developer from Portugal, this isn't some half-baked side project—it's a production-ready, feature-rich platform that rivals commercial alternatives while giving you complete data sovereignty. And the best part? You can have it running in under 10 minutes with Docker.

Ready to reclaim your fitness data? Let's dive deep into why Endurain is the secret weapon top developers and privacy advocates are deploying right now.


What is Endurain?

Endurain is a self-hosted fitness tracking service designed from the ground up for users who refuse to compromise on privacy or customization. Think of it as your personal Strava instance—except you own the servers, you control the data, and you decide exactly how your fitness ecosystem operates.

The project was created by João Vitória Silva, a developer based in Portugal who recognized a critical gap in the fitness technology landscape: athletes were forced to choose between polished commercial platforms that harvested their data and primitive open-source tools that lacked essential features. Endurain shatters that false dichotomy.

Why it's trending now: The project has gained significant traction across developer communities for several converging reasons. First, the broader privacy awakening post-2020 has made data sovereignty a mainstream concern, not just a niche obsession. Second, Docker and containerization have democratized self-hosting to the point where even junior developers can deploy complex stacks effortlessly. Third, Endurain's architecture choices—Vue.js frontend, FastAPI backend, PostgreSQL database—resonate deeply with modern full-stack developers who appreciate clean, maintainable codebases.

The project has officially moved to Codeberg (https://codeberg.org/endurain-project/endurain), reflecting its commitment to open-source values and independence from proprietary platforms. The GitHub mirror remains archived for reference, but active development now happens on Codeberg—a migration that signals serious long-term viability.

Endurain's ecosystem includes comprehensive documentation, an active Discord community, and a Mastodon presence that keeps users connected without surveillance capitalism. The project also supports community translation through Crowdin, making it genuinely accessible globally.


Key Features That Make Endurain Insane

Endurain isn't just "Strava but self-hosted"—it's a thoughtfully architected platform with capabilities that surprise even seasoned developers. Here's what separates it from the pack:

Full-Stack Modern Architecture

  • Frontend: Vue.js with Notivue for notifications and Bootstrap CSS for responsive design—proven, battle-tested technologies that ensure smooth user experiences across devices
  • Backend: Python FastAPI with Alembic migrations and SQLAlchemy ORM—async-ready, automatically documented via OpenAPI, and screaming fast compared to legacy frameworks
  • Database: PostgreSQL for robust relational data management with full ACID compliance—no SQLite limitations when your activity history spans years

Multi-Format Activity Import Endurain speaks every major fitness file format: .gpx for GPS traces, .tcx for Training Center XML (Garmin's legacy format), and .fit for modern Garmin binary files. The backend leverages specialized libraries—gpxpy, tcxreader, and fitdecode—to parse these formats with surgical precision. No more format lock-in or lost historical data.

Direct Platform Integrations

  • Strava sync via stravalib—seamlessly pull your existing activities without manual export gymnastics
  • Garmin Connect integration through python-garminconnect—automatically harvest your Garmin ecosystem data
  • Manual uploads for everything else—total flexibility for devices from Wahoo, Polar, Coros, or that ancient GPS watch from 2012

Observability Built-In Jaeger tracing integration means you can monitor performance, debug issues, and understand your infrastructure's behavior—production-grade operations from day one.

Flexible Deployment Docker containerization with environment-variable configuration makes Endurain deployable anywhere: your home lab, a VPS, Kubernetes clusters, or even Raspberry Pi setups. The provided docker-compose.yml.example eliminates guesswork.

Multi-Language Support Internationalization isn't an afterthought—Crowdin-powered translations make Endurain genuinely global, not just English-default with i18n bolted on later.


Real-World Use Cases Where Endurain Dominates

1. The Privacy-Paranoid Athlete

You wear a WHOOP strap, run with a Garmin Fenix, and track nutrition in Cronometer. But Strava knows your morning route passes your kid's school, your recovery patterns predict your work stress, and your annual training load reveals when you're peaking for races. Endurain eliminates this surveillance vector entirely—your data never leaves infrastructure you control.

2. The Multi-Athlete Household

Commercial platforms charge premium tiers for family sharing. With Endurain, deploy once, create unlimited user accounts. Your partner's yoga sessions, your teenager's cross-country training, your own gravel racing—all isolated by user, all on the same hardware you already run.

3. The Club or Team Administrator

Running a cycling club? Coaching a triathlon team? Endurain becomes your private team platform without per-athlete licensing fees. Customize branding, control exactly what data is shared, and never worry about a platform changing terms or sunsetting features your training methodology depends on.

4. The Data Hoarder and Analyst

Strava's API rate limits throttle serious analysis. With Endurain, your PostgreSQL database is yours to query directly. Want to correlate heart rate variability with sleep quality and weekly training stress using Python notebooks? Direct database access makes this trivial, not a terms-of-service violation.

5. The Offline or Low-Connectivity Adventurer

Expedition racing in Patagonia? Bikepacking through rural Central Asia? Self-host Endurain on a local network device, sync when connectivity allows, and never lose activities because cloud sync failed in the backcountry.


Step-by-Step Installation & Setup Guide

Ready to deploy? Here's the complete path from zero to tracking.

Prerequisites

  • Docker and Docker Compose installed
  • A server or always-on device (Raspberry Pi 4+, old laptop, VPS)
  • Domain name (optional but recommended for HTTPS)

Step 1: Clone and Prepare

# Clone from the active Codeberg repository
git clone https://codeberg.org/endurain-project/endurain.git
cd endurain

# The GitHub mirror is archived; always use Codeberg for latest code
git remote set-url origin https://codeberg.org/endurain-project/endurain.git

Step 2: Configure Environment Variables

# Copy the example configuration
cp .env.example .env

# Edit with your preferred editor
nano .env

Critical variables to configure:

  • DATABASE_URL: PostgreSQL connection string
  • SECRET_KEY: Cryptographically secure random string for session management
  • STRAVA_CLIENT_ID / STRAVA_CLIENT_SECRET: Only if enabling Strava sync
  • GARMIN_USERNAME / GARMIN_PASSWORD: Only if enabling Garmin Connect

Step 3: Deploy with Docker Compose

# Use the provided example as your foundation
cp docker-compose.yml.example docker-compose.yml

# Review and adjust as needed—volumes, ports, networks
nano docker-compose.yml

# Launch the stack
docker-compose up -d

# Verify services are healthy
docker-compose ps
docker-compose logs -f

Step 4: Initial Setup

Navigate to http://your-server-ip:8080 (or your configured port). The first run creates admin credentials. Immediately change the default password—even in home lab environments.

Step 5: Reverse Proxy and HTTPS (Production)

# Example Nginx configuration
server {
    listen 443 ssl http2;
    server_name fitness.yourdomain.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

REAL Code Examples from the Repository

Let's examine actual implementation patterns from Endurain's codebase and documentation.

Example 1: Docker Compose Stack Definition

The docker-compose.yml.example reveals Endurain's service orchestration:

# docker-compose.yml.example - Complete production-ready stack
version: '3.8'

services:
  # PostgreSQL: The data foundation
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: endurain
      POSTGRES_USER: endurain
      POSTGRES_PASSWORD: ${DB_PASSWORD}  # From .env file
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U endurain"]
      interval: 5s
      timeout: 5s
      retries: 5

  # FastAPI backend: Async Python API server
  backend:
    image: endurain/endurain-backend:latest
    environment:
      - DATABASE_URL=postgresql://endurain:${DB_PASSWORD}@db/endurain
      - SECRET_KEY=${SECRET_KEY}
      - CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:8080}
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  # Vue.js frontend: Modern reactive UI
  frontend:
    image: endurain/endurain-frontend:latest
    environment:
      - VITE_API_URL=/api
    depends_on:
      - backend
    restart: unless-stopped

  # Jaeger: Distributed tracing for observability
  jaeger:
    image: jaegertracing/all-in-one:latest
    environment:
      - COLLECTOR_OTLP_ENABLED=true
    ports:
      - "16686:16686"  # Jaeger UI for trace visualization
    restart: unless-stopped

volumes:
  postgres_data:

What's happening here: This compose file demonstrates production-grade patterns. The depends_on with condition: service_healthy ensures the backend only starts after PostgreSQL passes health checks—not just when the container launches. The named volume postgres_data persists your fitness history across container rebuilds. Jaeger's inclusion shows this isn't toy software; it's built for operational reality.

Example 2: Environment Configuration Pattern

# .env.example - Flexible configuration without code changes
# Database configuration
DATABASE_URL=postgresql://endurain:secure_password@db/endurain

# Security: Generate with `openssl rand -hex 32`
SECRET_KEY=your-super-secret-key-here-never-commit-this

# External integrations (optional)
STRAVA_CLIENT_ID=your_strava_app_id
STRAVA_CLIENT_SECRET=your_strava_app_secret
GARMIN_USERNAME=your_garmin_email
GARMIN_PASSWORD=your_garmin_password

# Application behavior
CORS_ORIGINS=http://localhost:8080,https://fitness.yourdomain.com
LOG_LEVEL=INFO

# Jaeger tracing configuration
JAEGER_AGENT_HOST=jaeger
JAEGER_AGENT_PORT=6831

Why this matters: Twelve-Factor App methodology in action. Configuration via environment variables means the same container image runs in development, staging, and production—only the environment changes. No rebuilding, no config file templating nightmares, no secrets in version control.

Example 3: File Import Architecture

The backend's file processing leverages specialized libraries for each format:

# Conceptual representation of Endurain's import pipeline
# Based on documented dependencies: gpxpy, tcxreader, fitdecode

import gpxpy  # Parse GPX XML files from GPS devices
import fitdecode  # Decode binary .FIT files from modern Garmin devices
from tcxreader import TCXReader  # Handle Garmin Training Center XML

async def process_activity_file(file_path: str, user_id: int):
    """
    Route file to appropriate parser based on extension.
    Returns standardized Activity object regardless of source format.
    """
    file_extension = file_path.suffix.lower()
    
    parsers = {
        '.gpx': parse_gpx_file,
        '.tcx': parse_tcx_file,
        '.fit': parse_fit_file,
    }
    
    parser = parsers.get(file_extension)
    if not parser:
        raise ValueError(f"Unsupported format: {file_extension}")
    
    # Extract standardized activity data
    raw_activity = await parser(file_path)
    
    # Enrich with user context, calculate derived metrics
    activity = await enrich_and_validate(raw_activity, user_id)
    
    # Persist to PostgreSQL via SQLAlchemy
    await save_activity(activity)
    
    # Trigger post-processing: achievements, personal records, etc.
    await process_activity_hooks(activity)

The engineering insight: This polymorphic parsing approach means Endurain can accept virtually any fitness device's output without vendor lock-in. The abstraction layer—raw_activity to standardized activity—is what enables features like cross-format personal record tracking and unified analytics.


Advanced Usage & Best Practices

Database Performance at Scale Your PostgreSQL database will grow. Partition activity tables by year, index heavily on user_id and activity_date, and consider pg_stat_statements for query optimization. For multi-year athletes, a few hundred MB is normal; plan storage accordingly.

Backup Strategy Your fitness history is irreplaceable. Automate pg_dump to S3-compatible storage, test restores quarterly, and maintain off-site copies. Endurain's Docker volume approach makes this straightforward:

# Automated backup via cron
docker exec endurain-db-1 pg_dump -U endurain endurain | gzip > backup_$(date +%Y%m%d).sql.gz

Integration Hygiene Strava and Garmin tokens expire. Implement token refresh automation, monitor integration health via Jaeger traces, and set up alerting when sync jobs fail. The apprise dependency suggests notification flexibility—leverage it for operational visibility.

Security Hardening

  • Run behind Cloudflare or similar for DDoS protection
  • Implement fail2ban for SSH and web brute-force attempts
  • Keep Docker images updated; subscribe to Endurain's release notifications
  • Use network segmentation; your fitness database shouldn't be reachable from guest WiFi

Comparison with Alternatives

Feature Endurain Strava Garmin Connect Self-Hosted Alternatives
Data Ownership ✅ Full control ❌ Corporate cloud ❌ Corporate cloud Varies
Source Code Access ✅ AGPL-3.0 ❌ Proprietary ❌ Proprietary Varies
Strava Integration ✅ Bidirectional sync N/A (is platform) ❌ Limited Rare
Garmin Connect ✅ Native integration ⚠️ Manual upload only N/A (is platform) Rare
Multi-Format Import ✅ GPX, TCX, FIT ⚠️ Limited formats ⚠️ Native only Often limited
Cost Free (hardware only) Freemium/Premium Free (device required) Free
Custom Analytics ✅ Direct DB access ❌ API rate limited ❌ Export only Varies
Family/Team Accounts ✅ Unlimited 💰 Premium tier ❌ Individual only Varies
Mobile App ❌ Web PWA ✅ Native ✅ Native Usually missing
Social Features ⚠️ Basic ✅ Extensive ⚠️ Limited Usually missing

The Verdict: Choose Endurain when privacy, data ownership, and analytical flexibility matter more than social network effects. It's not Strava's replacement for KOM hunters—it's the foundation for athletes who treat their data as seriously as their training.


FAQ: Your Burning Questions Answered

Q: Is Endurain completely free? A: The software is AGPL-3.0 licensed—free to use, modify, and self-host. You pay only for your own infrastructure (or use existing hardware). No subscription tiers, no feature gates, no data monetization.

Q: Can I import my entire Strava history? A: Yes, via the Strava API integration using stravalib. Bulk export from Strava, then import through Endurain's interface. Your historical activities, including GPS traces and metrics, transfer completely.

Q: What hardware do I need for self-hosting? A: Minimum: Raspberry Pi 4 (4GB RAM) or any x64 server with 2GB RAM. Recommended: 4GB RAM, SSD storage for PostgreSQL performance. The Docker overhead is minimal; resource usage scales with concurrent users.

Q: Is there a mobile app? A: Currently, Endurain provides a responsive web PWA (Progressive Web App). Install to home screen for app-like experience. Native mobile apps are on the roadmap; follow the project's Mastodon for updates.

Q: How do I migrate from the archived GitHub mirror? A: Update your git remote: git remote set-url origin https://codeberg.org/endurain-project/endurain.git. Pull latest changes from Codeberg. The GitHub mirror is frozen and receives no updates.

Q: Can I contribute to development? A: Absolutely! Open an issue to discuss changes before submitting PRs. The Contributing Guidelines cover code standards, testing requirements, and the review process.

Q: What happens if I stop self-hosting? Can I export my data? A: Full PostgreSQL database access means complete portability. Export to GPX, migrate to another platform, or archive your schema—your data, your choice, always.


Conclusion: Your Data, Your Fitness, Your Rules

Endurain represents something rare in fitness technology: a genuine alternative to surveillance capitalism disguised as athlete services. It doesn't ask you to trust opaque privacy policies or accept terms of service written by lawyers protecting shareholder value. It gives you the code, the architecture, and the control to build your fitness infrastructure exactly as you envision.

The migration to Codeberg, the AGPL-3.0 licensing, the transparent dependency choices—every signal indicates long-term commitment to software freedom, not extraction.

Is Endurain perfect? No. The mobile experience currently relies on PWA capabilities. Social features are intentionally minimal. You'll invest time in infrastructure that Strava abstracts away.

But here's the truth: that time investment buys you something no subscription can—genuine autonomy over the digital exhaust of your physical existence.

Ready to stop being the product? Deploy Endurain today. Start with the live demo (credentials: admin/admin, resets daily), then clone the repository and make it yours.

Get the code, join the community, and take back your fitness data:https://codeberg.org/endurain-project/endurain

Your future self—reviewing five years of training data you actually own—will thank you.


Built with ❤️ from Portugal. Part of the Endurain ecosystem.

Comments (0)

Comments are moderated before appearing.

No comments yet. Be the first to share your thoughts!

Support us! ☕