FitTrackee: A Self-Hosted Workout Tracker Built on Flask, Vue 3 and PostGIS
Self-hosted outdoor activity tracker :bicyclist: [mirror of codeberg repository: https://codeberg.org/FitTrackee/FitTrackee]
At a glance
- What is it?
- FitTrackee stores GPX-based outdoor workouts on your own server, with a Flask API, a Vue 3 interface and PostgreSQL plus PostGIS for geographic data. It is a file-import tool, not a live-recording app, and its own README calls it under heavy development.
- Who is it for?
- Adopt FitTrackee if you already export GPX files from FitoTrack, OpenTracks, OSMAnd, Runner Up or Amazfish (integration from v2.9.0) and you want the data on a server you control, with no live-tracking requirement. Do not adopt it if you need real-time recording on the phone, if you cannot run PostgreSQL 14 to 18 with PostGIS 3.4 to 3.6, or if AGPL-3.0 obligations are incompatible with how you plan to distribute your own changes.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap FitTrackee fills: workout files that never leave your server
Most activity trackers are cloud services. You record a ride, the file lands on someone else's infrastructure, and the only way to see it years later is through that vendor's web interface. FitTrackee reverses the storage decision. The README describes it as a web application allowing tracking of outdoor activities from files, with data on your own server. That sentence is the whole product thesis.
The target user is the person who already records with a local-first app. The README lists Android options such as FitoTrack (GPLv3), OpenTracks (Apache License), OSMAnd (GPLv3) and Runner Up (GPLv3), all of which store workouts locally and export them to a file. Smartwatch owners are pointed at Amazfish on Sailfish OS, which the README says integrates with FitTrackee from v2.9.0, and at Gadgetbridge, which the README explicitly notes has no integration. So the typical workflow is: record on the device, export GPX, upload to your own instance. The README also states that a workout can be added without a file, which covers manual entry for sessions where no track exists.
This is not a Strava replacement in the social sense. There is no claim in the supplied material about segments, leaderboards, kudos or a public feed. The value proposition is custody of the data plus a web interface for reading it, with map data from OpenStreetMap.
Architecture: Flask API, Vue 3 front end, PostGIS for the tracks
The stack is visible from the badges and topics in the repository. The backend is Python on Flask 3.1, formatted with ruff and type-checked with mypy. The front end is Vue 3.5 with TypeScript, formatted with prettier. Charting is Chart.js and maps are rendered with Leaflet, both listed as topics. The database is PostgreSQL, with the README badge listing support for versions 14, 15, 16, 17 and 18, plus PostGIS 3.4, 3.5 or 3.6. GPX handling is done with the gpxpy library, which appears in the topic list alongside the gpx topic itself.
The PostGIS requirement is the part that shapes deployment. Geographic track data is stored as spatial data, not as a blob of XML, which is what allows the map view and any distance or elevation aggregation to be computed in the database rather than in Python. That is a reasonable design, but it means you cannot substitute SQLite for a quick local trial. You need a PostgreSQL instance with the PostGIS extension available, and the version matrix is narrow enough that an old distribution package may not qualify.
The README notes that the GitHub repository is a mirror, with the main repository on Codeberg, and that GitHub is used to run tests and to build and publish Python packages and Docker images through GitHub Actions. Issues and pull requests live on Codeberg. For anyone filing a bug, that detail matters: the mirror does not accept them.
The README also carries a warning in its own words: under heavy development (some features may be unstable). It links a provisional roadmap and the issue tracker. Treat that as a statement about API and schema stability rather than a marketing hedge. A project that ships a v1.4.0b1 beta alongside v1.3.5 stable is signalling that the next minor line is still settling.
Getting an instance running from the documented install paths
The README points installation at docs.fittrackee.org/en/installation/index.html rather than inlining the steps, so the exact compose file contents are not in the supplied material. What can be confirmed is that two distribution channels exist: a PyPI package (the badge references pypi.org/project/fittrackee) and a Docker image (the badge references hub.docker.com/r/fittrackee/fittrackee). The presence of both means you can either install the Python package into your own environment or pull the published image.
Either route implies the same external dependency: a PostgreSQL server with PostGIS enabled. The README version badges give the supported range as PostgreSQL 14 through 18 and PostGIS 3.4 through 3.6. Provisioning that database, and making sure the PostGIS extension is created in the target database, is the first thing to verify before the application will start.
A command line interface is documented separately at docs.fittrackee.org/en/cli.html. The README does not enumerate its subcommands, so the CLI surface cannot be described here beyond its existence and its documentation location. There is also a dedicated troubleshooting section at docs.fittrackee.org/en/troubleshooting/index.html, which is worth reading before opening an issue, and a third-party tools page at docs.fittrackee.org/en/third_party_tools.html that presumably covers importers and companion utilities. Configuration keys are not reproduced in the README, so any statement about specific environment variables would be guesswork. The honest position is: the configuration reference lives in the installation docs, and that is where you should read it.
Where FitTrackee is the wrong tool
The README's own framing rules out the most common expectation people bring to an activity tracker. FitTrackee works from files. It is not described anywhere in the supplied material as recording GPS in the browser or on the phone. If you want to press start, put the phone in your pocket and have the track appear live, you need a recording app, and FitTrackee is the place the file goes afterwards. The README's list of Android apps is exactly that: apps that store workouts locally and export them.
Gadgetbridge users should read the parenthetical carefully. The README lists Gadgetbridge with the note no integration. Amazfish gets integration from v2.9.0; Gadgetbridge does not. If your watch syncs through Gadgetbridge, you are exporting and uploading by hand or via some other tool.
The stability warning is the second limitation. Under heavy development, with a beta release in the recent list, means a self-hoster should expect schema migrations between versions and should not assume a plugin or script written against one release will survive the next. The README links the changelog at docs.fittrackee.org/en/changelog.html, and reading it before every upgrade is the practical mitigation.
Finally, the deployment footprint is not trivial. PostgreSQL plus PostGIS is a heavier dependency than a single-file database, and it is not optional given the geographic data model. On a small VPS that is fine; on a shared host without PostGIS, it is a blocker.
Alternatives and the real difference in approach
The obvious comparison is a hosted service, and the difference is not features but custody. With a cloud tracker, the recording app and the storage are the same product, and the export path is an afterthought. With FitTrackee, the recording app and the storage are deliberately separate, and the file is the interface between them. That separation is why the README can list four unrelated Android apps as sources; none of them needs to know FitTrackee exists.
Within self-hosting, the meaningful split is between file-import trackers and live-recording servers. FitTrackee sits firmly on the import side. If your requirement is a server that receives a continuous position stream from a phone, FitTrackee's documented model does not cover it, and choosing it would mean building the recording half yourself.
There is also a data-model difference worth naming. Because FitTrackee stores tracks in PostGIS, the geographic queries happen in the database. A simpler tracker that keeps GPX files on disk and parses them per request has a much lighter install and no extension requirements, at the cost of doing spatial work in application code. Neither is wrong; they optimise for different things, and FitTrackee has chosen the heavier, more queryable option.
Licence and the cost of keeping an instance current
FitTrackee is AGPL-3.0. For a self-hoster running a private instance, that is unremarkable. The obligation that matters appears if you modify the code and let other people interact with it over a network: the AGPL's network clause is the reason some organisations treat it differently from MIT or Apache-2.0 dependencies. This is a description of the licence family, not legal advice; if you plan to offer a modified FitTrackee to users outside your household, get your own reading of the terms.
The maintenance cost is the release cadence plus the beta line. The recent releases shown are v1.3.5 (September 2026), v1.4.0b1 (August 2026) and v1.3.4 (July 2026). That is a steady patch rhythm on the 1.3 series with a 1.4 beta running in parallel. Every upgrade is a Python package or Docker image swap plus whatever database migration the changelog describes. Because the project is hosted primarily on Codeberg with GitHub as a mirror, security advisories and issue discussion will appear there first, so a Codeberg watch is more useful than a GitHub one.
Translation is handled through Weblate, per the README. If you run an instance in a language other than English, the translation status badge reflects the development branch and, as the README warns, may differ from the released version. That is a small but real operational detail: translated strings can lag the code you are actually running.
Who should run FitTrackee, and what to check first
The fit is narrow and clear. You record outdoor activities with FitoTrack, OpenTracks, OSMAnd, Runner Up or Amazfish, you are comfortable running PostgreSQL with PostGIS, and you want the resulting tracks on a server you administer. You do not need live tracking, and you accept that the project describes itself as under heavy development. The README's framing of data on your own server is the reason to pick it over a hosted service, and if that reason does not apply to you, the operational cost is hard to justify.
The people who should look elsewhere are those who want to hit record in a browser, those whose only sync path is Gadgetbridge (no integration, per the README), and those who cannot provide PostgreSQL 14 to 18 with PostGIS 3.4 to 3.6. Anyone who needs a stable plugin API should also wait, given the parallel beta line.
Before you commit, do three concrete things. Export one workout from your actual recording app and confirm the import accepts it, since the README lists example apps rather than guaranteeing every export format. Read the changelog at docs.fittrackee.org/en/changelog.html for the jump between the version you install and the one before it, so the migration is not a surprise. And decide now whether you will track the 1.3 stable series or the 1.4 beta, because mixing them across upgrades is how a self-hosted instance ends up in the troubleshooting guide.
Editorial conclusion
Adopt FitTrackee if you already export GPX files from FitoTrack, OpenTracks, OSMAnd, Runner Up or Amazfish (integration from v2.9.0) and you want the data on a server you control, with no live-tracking requirement. Do not adopt it if you need real-time recording on the phone, if you cannot run PostgreSQL 14 to 18 with PostGIS 3.4 to 3.6, or if AGPL-3.0 obligations are incompatible with how you plan to distribute your own changes. Before committing, verify three things: that your exporter produces files the import accepts, that the v1.4.0b1 beta branch does not carry features you would come to depend on, and that you are prepared to run the documented upgrade path and database migrations on every release.
Community notes