# FitTrackee: a self-hosted workout tracker for GPX files you own

> FitTrackee is a Flask and Vue application that stores outdoor activity files on your own server. It suits people who export GPX or FIT files from a watch or phone and want the data to stay there.

**SamR1/FitTrackee** — Self-hosted outdoor activity tracker :bicyclist: [mirror of codeberg repository: https://codeberg.org/FitTrackee/FitTrackee]

- Repository: https://github.com/SamR1/FitTrackee
- Website: https://docs.fittrackee.org
- Stars: 1,169 · Forks: 76
- Language: Python
- License: AGPL-3.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/samr1-fittrackee

## The problem FitTrackee solves: workout files with nowhere private to go

Phones and watches record activities well and store them badly. FitoTrack, OpenTracks, OSMAnd and Runner Up all keep workouts locally and export them as files, and Amazfish can pull data off a smartwatch. What none of them provides is a server-side view: a map of every ride, cumulative statistics, a public feed if you want one. The usual answer is to upload the files to a commercial service, which means handing over location traces that show where you live and when you are away.

FitTrackee is the other half of that workflow. It is a web application that ingests activity files and renders them with OpenStreetMap tiles. The README describes it as a simple self-hosted workout/activity tracker, and the target user is someone who already has an export step in their routine. If your watch syncs only through a vendor account and you have never touched a GPX file, FitTrackee does not remove that step; it replaces the destination, not the source.

## How FitTrackee works: Flask API, Vue 3 client, PostGIS storage

The repository is split into two top-level directories, fittrackee and fittrackee_client. The server is Python: Flask 3.1 with flask-sqlalchemy and flask-migrate for schema changes, and GeoAlchemy2 with Shapely on top of PostGIS for the spatial columns. gpxpy handles GPX parsing and fitdecode handles FIT files. The client is Vue 3.5 with TypeScript, built by Vite or an equivalent npm script and served as static files from fittrackee/dist, which the Dockerfile copies into the runtime image.

The database requirement is the part that shapes deployment. PostgreSQL 14 through 18 is supported, and PostGIS 3.4, 3.5 or 3.6 must be installed. That is not a soft dependency: track geometry is stored as spatial data, so a plain PostgreSQL instance will not do. Two optional services appear in the configuration. Redis backs API rate limits through flask-limiter, user data export, archive uploads and email sending. Dramatiq, with dramatiq-abort on Redis, runs those background tasks. The docker-compose.yml comments state that a single-user installation needs only the fittrackee and fittrackee-db containers, and that workers and Redis are for multi-user setups. That is a real architectural fork: a one-person instance is two containers, and a shared instance is four plus an SMTP URL.

## Installing FitTrackee with Docker Compose

The documented path is Docker Compose, with a minimum Compose version of 2.30.0 according to the comments in docker-compose.yml. Start from the environment template in the repository root. The .env.example file lists the variables you are expected to fill in, including APP_SECRET_KEY, DATABASE_URL and UI_URL.

```bash
cp .env.example .env
# edit .env: set APP_SECRET_KEY, DATABASE_URL, UI_URL
```

The database service in docker-compose.yml uses postgis/postgis:18-3.6-alpine and mounts ${HOST_DATABASE_DIR:-./data/db} at /var/lib/postgresql. Uploads and a static map cache are mounted separately, defaulting to ./data/uploads and ./data/staticmap_cache. The application image is pinned in the file as fittrackee/fittrackee:v1.3.5.

```bash
docker compose up -d
```

After the containers report healthy, the web interface is reachable on the port you configured, and you register an account, then upload a workout file exported from your phone or watch. The README notes that a workout can also be added without a file, which is useful for activities recorded on a device that only reports a summary.

Two things to check before the first upgrade. The compose file warns that there is no official PostGIS image for ARM platforms, with a workaround of building the image locally, so a Raspberry Pi deployment takes extra work. It also warns that PGDATA changed starting with PostgreSQL 18, which matters if you point the volume at an existing data directory. For multi-user instances, uncomment the fittrackee-workers and fittrackee-redis services and set EMAIL_URL, because email sending depends on Redis.

## Where FitTrackee is the wrong tool

The README says plainly that the project is under heavy development and that some features may be unstable. That is an honest warning and it should shape expectations. This is not a service with a support contract; it is a codebase with a provisional roadmap, and the release list shows a beta (v1.4.0b1) sitting alongside stable v1.3.5 and v1.3.4 releases. If you want to install something and forget it, the changelog is the document that decides whether an upgrade is safe, not the version number.

The harder limitation is recording. FitTrackee ingests files; it does not ship a mobile app. The README points to third-party Android apps and to Amazfish for Sailfish OS, and it notes that Gadgetbridge has no integration. If your current routine is pressing start in an app that syncs automatically, FitTrackee inserts a manual export and upload step that no amount of server configuration removes. The same applies to anyone whose watch exports only a proprietary format through a vendor cloud: fitdecode covers FIT, but the file still has to reach you.

Infrastructure is the second constraint. PostgreSQL with PostGIS, plus Redis if you enable rate limits, exports, archive uploads or email, is a heavier stack than a single SQLite file. On a small VPS that is fine; on shared hosting with no Docker it is not. And since the GitHub repository is described as a mirror used mainly for running tests and publishing packages and images, with issues and pull requests living on Codeberg, anyone filing a bug should read the README's repository section first.

## FitTrackee against Endurain and Wger

Endurain appears in the related searches as the obvious comparison, and the difference is one of scope rather than quality. FitTrackee is built around files: you bring a GPX or FIT export, the server parses it, stores the track and draws it. Its integrations are other people's export buttons. Endurain is a self-hosted activity tracker in the same broad category, so the choice usually comes down to which import path matches the devices you own and which stack you are willing to operate. Anyone weighing the two should compare the import formats each accepts against the actual exports their phone or watch produces, because that is the step that cannot be worked around.

Wger is a different kind of tool that keeps surfacing in the same searches. It is a workout and fitness manager oriented toward logging strength training and routines, not toward parsing GPS tracks and rendering them on a map. If your training is sets, reps and body measurements, FitTrackee's map-centric model is a poor fit, and Wger's data model is a poor fit for a 60 km ride with elevation. The related searches also mix in SparkyFitness on Unraid, which is a deployment question rather than a feature comparison: FitTrackee's own compose file is the reference for how it is meant to run, and it assumes Docker Compose 2.30.0 or newer.

## Licence, maintenance and what an upgrade costs

FitTrackee is licensed AGPL-3.0-only, as stated in pyproject.toml and the LICENSE file. The practical consequence for most readers is nothing, since running it on your own server for yourself is the intended use. It matters if you modify the code and expose it to other users over a network: the AGPL's network clause is the part that distinguishes it from GPL-3.0, and what that obliges you to publish is a question for a lawyer, not for this article. The project is a mirror on GitHub of a Codeberg repository, so contributions belong upstream on Codeberg.

On maintenance, the last push to the repository was on 2026-09-09, the same day v1.3.5 was released. The repository is not archived. The README's own framing, under heavy development, is the more useful signal than any date.

Upgrade cost concentrates in one place. The docker-compose.yml comments instruct you to back up the database before a FitTrackee upgrade whenever the new version includes database migrations, and flask-migrate is in the dependency list, so migrations are part of the release process. The database image is pinned to a specific PostGIS and PostgreSQL combination, and the file tells you to consult the PostgreSQL and PostGIS documentation before changing that image version. A safe upgrade therefore means reading the changelog for the target version, taking a dump, and only then pulling a new application image.

## Conclusion

Adopt FitTrackee if you already export GPX or FIT files from a watch or phone and want a private web dashboard instead of a cloud account. Skip it if you need an official mobile app, since the README points to third-party apps for recording. Before committing, check that your host can run PostGIS 3.4 to 3.6 and read the migration notes in the changelog for the version you install.

## FAQ

### What is the FitTrackee app?

It is a self-hosted web application that tracks outdoor activities from files, storing workout data on your own server. The README describes it as a simple self-hosted workout/activity tracker, with map data from OpenStreetMap.

### Does FitTrackee include a mobile app for recording workouts?

No. The README points to third-party apps such as FitoTrack, OpenTracks, OSMAnd and Runner Up that store workouts locally and export them to a file, which you then upload. Amazfish offers integration with FitTrackee from v2.9.0, and the README states Gadgetbridge has no integration.

### What database does FitTrackee need?

PostgreSQL 14 through 18 with PostGIS 3.4, 3.5 or 3.6, according to the version badges in the README. The production compose file uses the postgis/postgis:18-3.6-alpine image.

### Do I need Redis to run FitTrackee?

Only for multi-user setups. The docker-compose.yml comments state that a minimal single-user application needs just the fittrackee and fittrackee-db containers, while Redis is required for API rate limits, user data export, archive uploads and email sending.

### Under what licence is FitTrackee released?

AGPL-3.0-only, as declared in pyproject.toml and the LICENSE file. The README also notes the main repository is on Codeberg, with GitHub acting as a mirror.

## Sources

- [License: AGPL-3.0](https://github.com/SamR1/FitTrackee/blob/main/LICENSE)
- [Project website](https://docs.fittrackee.org)
- [README](https://github.com/SamR1/FitTrackee/blob/main/README.md)
- [Releases](https://github.com/SamR1/FitTrackee/releases)
- [SamR1/FitTrackee on GitHub](https://github.com/SamR1/FitTrackee)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/samr1-fittrackee
