Most workout apps keep your data on their servers, push you towards a subscription, or vanish when the company does. openGym runs on your own box, keeps your data in a folder you control, and is yours to fork. It still behaves like a modern app: installable on the home screen, passkey sign-in, works offline, syncs between your phone and your laptop.
No account on someone else's server, no subscription, no ads, no telemetry. One
docker compose up and it's running.
The in-browser demo is the real app with example data, if you want to try it before installing anything.
Planning
Training
Progress
Accounts and data
On the phone and the wrist
Optional extras, off by default
The full list of what changed release by release is in the changelog.
You need Docker with Compose.
git clone https://github.com/DuarteSantos8/openGym
cd openGym
cp .env.example .env
docker compose pull # prebuilt images, amd64 + arm64 (skip this to build from source)
docker compose up -d
Open http://localhost:8080, tap Create profile, and you're in. The exercise animations are part of the image, so there's nothing else to download.
To reach it from your phone with passkeys you need HTTPS on a domain; that's a two-line change in
.env. The self-hosting guide walks through Cloudflare Tunnel, Caddy,
Traefik and nginx, and there are separate guides for
HTTPS on a LAN, a Mac with Tailscale and Kubernetes.
[!NOTE] Images are published from the same tag to
ghcr.io/duartesantos8/opengym-{api,web}(whatdocker-compose.ymlpulls) andregistry.gitlab.com/duartesantos8/opengym/{api,web}. Swap theimage:lines if you prefer GitLab's registry, or rundocker compose up -d --buildto build locally. Either way you don't need Node on the host.
.env)The same codebase builds the phone apps with Capacitor. Use them on their own (everything stays on the phone, no account) or connect them to your server and sync.
| Get it | |
|---|---|
| iPhone and iPad, with the Apple Watch app | The App Store, in every App Store country |
| Android | The signed APK from the latest release or opengym.ch, in three sizes: Standard (openGym-X.Y.Z.apk, animations at 180 px, about 315 MB), Plus (openGym-Plus-X.Y.Z.apk, 240 px, about 424 MB) and HD (openGym-HD-X.Y.Z.apk, 360 px, about 760 MB). It updates itself and stays the kind you picked |
| Google Play | Coming: a new developer account has to run a closed test first |
Every APK sits next to its .sha256. The APK and the Play app share one signing key, so you can
switch between them (or between Standard, Plus and HD) without losing data. Details, building it
yourself and connecting to your server: docs/MOBILE.md.
frontend/ is React 19 and Vite (React Router, Zustand), built to static files inside Docker.api/ is plain node:http with three dependencies: @simplewebauthn/server for passkeys,
web-push for notifications and undici for the AI coach's provider calls. Everything is
stored as JSON under ./data.web/ builds the frontend and serves it with nginx, proxying /api so the whole app sits on
one origin, which passkeys require.The architecture overview has the longer version, with diagrams of the frontend, sync, the exercise media and the watch.
The training logic (progression rules, 1RM, how a logged session is read back) lives in pure
functions under frontend/src/lib/ with tests beside them. The HTTP API is documented as an
OpenAPI spec in api/openapi.yaml, browsable at
opengym.ch/api.html.
Each profile's data is one document with a server revision. A device sends the revision it last saw along with its changes; if another device wrote in between, the server refuses and returns the current document so the device can merge and retry. Every change carries its own stamp, down to a single setting or routine field, so the merge keeps the newest edit of each one and a deletion stays deleted.
Nothing that hasn't reached the server is discarded on disconnect or sign-out, and the app shows a banner whenever it's working offline.
Everything lives in ./data on your host:
| File | Contents |
|---|---|
db.json |
Profiles and public passkey data |
db.json.bak |
A copy of the last good db.json, used if the main file can't be read |
state-<user>.json |
Each user's plan, workouts, body weight and settings |
audit.log |
Admin activity log (no IP addresses unless you turn that on) |
secret |
Session-cookie signing key |
Back up ./data and you've backed up everything. Passkey private keys never reach the server; they
stay in your phone's secure hardware or your password manager.
The documentation index sorts every guide by who it's for. The most used ones:
| I want to | Read |
|---|---|
| Get a quick answer | FAQ |
| Set up my own instance | Self-hosting |
| Use the Android or iPhone app | Phone app |
| Bring my history from another app | Importing data |
| Turn on the AI coach | AI coach |
| Contribute code | Contributing |
| Report a security problem | Security |
A release roughly every one to two weeks, each one whatever has passed testing by then. The full plan is in ROADMAP.md, and the issues sit in the GitHub milestones.
| Release | When | Theme |
|---|---|---|
| v1.4.0 | released Oct 2026 | A new exercise database with 5,632 exercises, plus two rounds of community work |
| v1.4.1 | released Oct 2026 | Bug fixes for v1.4.0 |
| v1.4.2 | released Oct 2026 | The App Store, the Apple Watch, widgets, three APK sizes |
| v1.4.3 | released Oct 2026 | The Halloween and community release: gym reminder, health data read back, watch upgrades, CSV export |
| v1.4.4 | Nov 2026 | Programmes, a tour with tutorials, AirPods heart rate, kg or lb per exercise, bug fixes |
| v1.4.5 | Nov 2026 | Google Play, F-Droid, Settings → Integrations (Strava, webhooks, calendar, Nextcloud), timed holds that start themselves |
| v1.4.6 | Dec 2026 | Wear OS, deeper Health Connect, body composition |
| v1.4.7 | Dec 2026 | The progression engine by @giulioleuci, circuits, AMRAP and EMOM |
| later | dates are guesses | Search and catalogue, accounts, a trainer role, skins, Garmin, database storage |
RP_ID/ORIGIN mismatch; the
self-hosting guide covers it.GitHub is the home of the project. gitlab.com/DuarteSantos8/opengym
is a mirror, updated by a GitHub Actions workflow on every push to main and every release tag. It
exists because its CI builds the multi-arch images and the SBOMs for its registry (the APKs are
built and signed on the release machine and attached to the GitHub release). Nothing is merged there by hand. In the changelog, !NN refers to a GitLab merge request
from the weeks in August and September 2026 when the project lived there.
People have asked about this, so plainly: openGym is developed with
Claude Code, Anthropic's coding agent. A large share of the
code, tests and documentation is drafted in Claude Code sessions, and the repository carries a
CLAUDE.md with the project context those sessions start from.
What that does and doesn't mean:
Community pull requests are written by their authors, with whatever tools they like, and reviewed the same way.
openGym is free and stays free: AGPL, no paid tier, nothing held back for sponsors. If it replaced a paid tracker for you and you'd like to chip in, there's Buy Me a Coffee, Ko-fi and GitHub Sponsors (the app has the same three under Settings → About & updates, and on the iPhone a shortcut to leaving an App Store review). A star, a bug report or a pull request helps just as much.
openGym's own code is licensed under the GNU AGPL v3.0. You can self-host, use, modify and share it; if you run a modified version as a network service, you have to offer that version's source under the same license.
[!IMPORTANT] The exercise media is not covered by that license. The stills and animations are © Aliaksandr Makatserchyk, Gym visual, licensed for use in openGym only: 180 px in this repository and on self-hosted servers, larger only inside the app packages. A non-commercial fork may keep them unmodified with the notice; anything else needs your own licence from gymvisual.com. The exercise text in
catalogue/is openGym's and open to contributions.
Contributing: pull requests are signed off once with the Contributor License Agreement: you keep the copyright in your work, openGym may use and relicense it (so the app can stay in the App Store and Google Play long term), and every version released under the AGPL stays AGPL.
Full third-party notices, including the body-diagram geometry, are in NOTICE.md.
| 日期 | 榜单 | 排名 | 周期新增 | 总 STAR |
|---|