Docs
Everything you need to get openGym running — on a phone, or on your own server. The deeper, maintainer-level docs live in the repository.
Install on Android
- Open the download on your phone and tap Download for Android.
- Your browser will ask whether it may install apps — allow it. This is standard for any app installed outside the Play Store (called sideloading), and you can revoke the permission right after.
- Open the downloaded
openGym.apk, confirm, done. No account, no setup.
Everything is stored on the phone itself. The only things fetched from the internet are the exercise images and animations (from a CDN, on demand).
Use on iPhone
Apple does not allow installing apps outside the App Store, so there is no iOS download — that's a platform rule, not a choice we made. What works instead:
- Self-host + home screen (recommended): open your own openGym instance in Safari → Share → Add to Home Screen. You get a full-screen app with its own icon, passkey sign-in and sync — no expiry, no fees.
- Build it onto your own iPhone: with a Mac and Xcode, the native app runs on your device with a free Apple ID (Apple expires the signature after 7 days; re-run from Xcode to renew). See docs/MOBILE.md.
- Just looking? Try the in-browser demo — the real app with example data, no account and nothing to install. The Android app above needs no account either.
Self-host with Docker
The self-hosted flavor adds passkey profiles, sync across devices, and (optionally) an admin dashboard. You need Docker with Compose:
git clone https://gitlab.com/DuarteSantos8/opengym
cd openGym
cp .env.example .env
docker compose pull # prebuilt images (amd64 + arm64) — skip to build from source
docker compose up -d
Open http://localhost:8080, tap Create profile, and you're in. The
first launch downloads the exercise media (~140 MB) once.
.env. The full guide, including reverse-proxy
examples and the invite-only/admin options, is in
docs/SELF_HOSTING.md.Settings worth knowing about
All of these live in .env; the defaults are what you get if you touch nothing.
RP_ID / ORIGIN | The domain passkeys are bound to, and the full URL you serve from. The two must agree, or sign-in fails. |
WEB_PORT | Host port for the web UI. Default 8080. |
INVITE_ONLY | Set 1 and new profiles need an invite code you generate. |
ALLOW_GUEST | Set 0 to remove Continue without account, so everyone using the instance has a profile. |
ADMIN_UIDS | Which user ids get the admin dashboard. |
SESSION_DAYS | How long a sign-in lasts. Default 90. |
BACKEND / PORT / NGINX_PORT | For fitting openGym into a stack that already has an api service, or putting it behind your own proxy on another port. The web container renders its nginx config at start-up, so these work on a prebuilt image. |
Ask an AI about your training
openGym ships an optional MCP server: a small read-only bridge that lets a client like Claude Desktop or Cursor answer questions from your actual log — "what did I bench last week?", "which muscle have I not trained this month?", "what's my estimated 1RM on squats?"
It runs on your machine, is spawned by the client, and reads your exported data directly. Nothing is sent anywhere, and it is not part of the Docker build — if you don't use an AI assistant, it simply isn't there. Setup is a few lines of client config: mcp/README.md.
Import your training history
Coming from another tracker? Settings → Data → Import from another app reads:
- FitNotes (both the Android and the FitNotes 2 iOS export)
- Strong and Hevy (CSV exports — session lengths carry over, so the activity heatmap fills in properly)
- Apple Health (body-weight history from the XML export)
- …and anything else with date, exercise-name and weight/reps columns
Exercise names are matched against the 1,324-exercise library; anything genuinely ambiguous becomes one of your own custom exercises instead of being guessed at. A summary shows exactly what will happen before anything is written, and importing is idempotent — running it twice never duplicates a workout.
Backups
Settings → Data → Export backup (JSON) writes your entire log — plan, workouts, weights, settings — into one file. On the mobile app it goes out through the share sheet (Files, AirDrop, mail…); in the browser it downloads. Import backup restores it anywhere: another phone, your self-hosted instance, or a fresh install. That file is the whole point of openGym — your training log as a file you own.
Build it yourself
Everything on this page is built from the public repo:
- Web / self-host:
docker compose up -d --buildbuilds the frontend inside the container — no local Node needed. - Android APK / iOS app: the Capacitor projects live in
frontend/androidandfrontend/ios— build, signing and distribution notes are in docs/MOBILE.md.
FAQ
Is it really free?
Yes — free as in cost and as in freedom (AGPL-3.0). No pro tier, no locked features, no ads, and the license keeps every fork open source too.
What data does openGym collect?
None. There is no telemetry, no analytics, no crash reporting. The mobile app's only network traffic is fetching exercise media from a CDN; a self-hosted instance talks only to your own server.
Why isn't it on the Play Store / App Store?
By choice (and on iOS, by Apple's rules for sideloading). Store accounts cost money, impose terms that sit badly with the AGPL, and put a gatekeeper between you and an app whose whole point is that your data is yours.
Mobile app or self-hosted — which one should I pick?
If you just want to track your training: the mobile app. If you want your data on your own hardware, synced across devices, with profiles for the people you train with: self-host. You can start with the app and move to a server later — the backup file migrates everything.
Where does the exercise database come from?
From hasaneyldrm/exercises-dataset: 1,324 exercises with animations and instructions in 10 languages. That dataset licenses the two halves differently, and so does openGym: the exercise metadata and instruction text are MIT, while the images and animations are © Gym visual, used under the dataset's terms rather than openGym's AGPL.
openGym does not redistribute that media — your instance downloads it from the upstream source on first run. If you want to reuse it yourself, commercially or otherwise, get your own licence from Gym visual first (terms & conditions).