openGym APK for Android v1.3.9

openGym is an open-source, self-hosted fitness and body-weight tracker designed for people who want complete control over their workout data. Instead of storing training history on a third-party service, it runs on your own server and keeps your data in files you control.

The application combines workout planning, guided training, body-weight tracking, statistics, muscle analysis, and cross-device synchronization in a web application that can also be installed as a Progressive Web App.

Features

openGym provides a weekly workout planner with routines organized by day. Users can create and modify training sessions, move workouts between days, and choose from predefined workout plans such as Push/Pull/Legs, Upper/Lower, Full Body, and 5×5.

The exercise library contains more than 1,300 exercises with animated demonstrations. Exercises can be searched, browsed by muscle group, and filtered according to available equipment.

During workouts, the application supports regular sets, supersets, warm-ups, cardio, rest timers, and exercise tracking. It records training history and provides statistics including personal records and progress charts.

Muscle analysis is another notable feature. openGym can show which muscles are being trained, fatigued, or detrained, helping users understand how their training volume is distributed over time.

The application can import workout history from services and applications including FitNotes, Strong, and Hevy. This makes switching to a self-hosted system considerably easier for existing users.

Authentication uses passkeys, while the application can operate offline and synchronize data when connectivity returns. The synchronization system uses revisions to prevent one device from silently overwriting changes made by another device.

Download openGym APK v1.3.9 - Software Mirrors

openGym APK v1.3.9 for Android

openGym-1.3.9.apk | 15.41 MB

openGym APK v1.3.9 Source Code

openGym APK v1.3.9 Source code (zip)

openGym APK v1.3.9 Source code (tar.gz)

openGym APK v1.3.9 Release Notes:

The milestone was "edit your history", and it is in: fix a saved workout after the fact, move it to another day, change how long it took, attach photos and videos to it. Around it, the two reports from Discord that mattered most — a paired phone that quietly stopped syncing and lost a week, and a routine planned at 2 × 10 that opened at 2 × 15 — are fixed at the root. Password sign-in for instances that want it, more than one passkey per profile, your own picture on your own exercises, Structural Balance, plate loading per set, the rest countdown in an Android notification, Ukrainian and Arabic. Thirty-nine community pull requests from eighteen contributors, plus five more taken in part. Web bundle, APK and API image. The two reports from Discord

  • ๐Ÿ”Œ A paired phone can no longer lose your workouts without telling you (andi242). After the

server refused a phone's sign-in once — "Sign out everywhere" does that, so does an expired token — the next start of the app unpaired it silently but kept you on screen, every sync after that went nowhere and was counted as done, and Disconnect then wiped the phone. Every paired phone since v1.2.10 could get there. Now:

  • The app says when it is not connected, always: a line at the top for offline, a server that

-- cannot be reached, a server that refuses this phone, an answer that is not the server's, and -- phone-only or guest use.

  • A refused phone keeps its pairing and its data and offers Pair again. Phones already stuck

-- in that state from an earlier version are healed when they start, and their unsynced workouts -- reach the server once they are paired again.

  • Settings → Server & sync shows the host, the account, the status, the last sync, what is

-- still waiting, and a Sync now button.

  • Disconnect and Sign out ask first when something has not reached the server yet — try again,

-- export it, or go ahead anyway. Going ahead keeps a copy on the device, and it is merged back -- the next time you connect to the same account.

  • Pairing again or signing in to the same account merges, instead of replacing the phone's copy

-- with the server's. A phone in use renews its sign-in on its own.

  • Signing in or pairing waits for your answer to "add this device's workouts?" before it touches

-- anything, and a kg ↔ lb conversion, a reset or a backup import now reaches every device.

  • Tip if you were hit by this: the phone's daily backup files (Documents/openGym/, or

-- Documents/opengym-backup-….json from before this version) may still hold the lost days — -- Settings → Import.

  • ๐Ÿ“‹ The plan owns the reps (seals187, Supportlik, #275, #216). A session copied its reps from

the last time you did that exercise in any routine, so a 2 × 10 day opened at the 2 × 15 you had done somewhere else. Now a planned session starts from the plan (Settings → "Planned sessions start from": your plan, or your last session), progression runs per routine slot and falls back to the exercise's history only when the slot has none, an edited plan restarts progression with its new weight, and the card says "Plan: 2 × 10" (or "2 × 10–15" for a range).

  • ๐Ÿ” Double progression waits for the top of the range (Diego-Sanchez2000, #278, bluzername's

#297) before it adds weight.

  • ๐Ÿ—‚️ A stale second tab can no longer overwrite the server (danielkleinert, #283). Each tab

tracks the revision it last saw, and a conflict keeps the latest edit of every routine and workout instead of whole copies.

  • ๐Ÿ“ด The iPhone home-screen app opens offline again (tpodolak, #274, bluzername's #298) — and a

slow connection no longer cuts a download off halfway. Editing your history

  • ✏️ Edit a saved workout (Space-Hermes, #203, #143, #229) — weights, reps, sets and exercises,

in the same screen you logged it on; progression and records re-read the corrected session. A workout emptied in the editor offers to delete it instead of saving nothing.

  • ๐Ÿ• Date, start time and duration (Parth-Vasave, #263, expressiveminute, #218), without

touching what you lifted.

  • ๐Ÿ“ธ Photos and videos on a workout — attach them on the finish screen or in the workout's

detail. They live on your server and the device, never in the synced data.

  • ๐Ÿ—“️ Log a missed day (svillar, #284) — mark a planned routine from a past day as done; its

rows only look at the history from before that day.

  • ๐Ÿ“š Drop sets and supersets show in History, an exercise's history opens from a past workout, a

workout copies as text, a finished session saves as a routine of its own (Space-Hermes, #211), and every weigh-in has a history with weekly averages.

  • ๐Ÿšซ "Don't count for progression" for one exercise or a whole workout (the ⋯ and ⋮ menus) —

an injury day stays out of the next session's numbers. Accounts and sign-in

  • ๐Ÿ” Password sign-in, if you want it (#118). Off by default; an instance switches it on with

PASSWORD_LOGIN=1, and each profile opts in by setting a password in Settings. Sign in with the profile's name or an e-mail address you add (no mail is ever sent). Passwords are stored with scrypt, repeated wrong guesses pause sign-in for that name, and an admin can hand out a one-time reset code. Removing a passkey or the password asks for proof first.

  • ๐Ÿ”‘ More than one passkey, and a new device by code (AlexanderVott, #95). Settings lists a

profile's passkeys to add, rename or remove, and Add another device shows a one-time code and QR; the code creates a passkey on the new device, never a session by itself. During a workout

  • ⏸️ Pause the rest timer — paused time does not count, and the alert moves with it.

  • ๐Ÿ”” The rest countdown in an Android notification (vitox013, #296, #122), with Pause, ±15 s and

Skip, on time with the screen off. A louder chime, and a Vibrate switch of its own.

  • ๐Ÿ‹️ Plate loading per set (kurktchiev, #194) — each row shows the plates for its weight, from

the plates you own; "No bar" Smith machines count from zero, and drop sets land on a weight you can actually load.

  • ⌨️ Keyboard shortcuts (#133) — Space or Enter ticks the next set, the arrow keys switch

exercise, for a keyboard or a Bluetooth button.

  • ⏱️ Rest timers stay on Ready when they run out, and a timed hold may run into overtime

(Space-Hermes, #204). The rest timer and a hold can no longer run at once (kurktchiev, #251).

  • The line under each exercise can show your best set instead of last time (Flxp49, #173); the

next workout card peeks in while you swipe (Space-Hermes, #202, sgoendoer, #113); "Set current" goes straight to card view (bluzername, #262, xwr3, #260); typing an exact RIR/RPE no longer ticks the set on the first keystroke (kurktchiev, #288). Plan, library and stats

  • ๐Ÿงฎ Structural Balance (Josevi, !140) — Stats compares your lifts with each other against the

Poliquin, Thibaudeau and ATG ratios and names the weakest one.

  • ๐Ÿ–ผ️ Your own picture on your own exercises (#126, #170; based on horusglez's #295 and

Vaibhav159's #246) — one photo, GIF or short video (up to 40 MB and 60 s) and one link per custom exercise. The file is stripped of its location data, kept on your server and on the device, never in the synced data, and works offline once seen; a YouTube link makes no request until you tap it. Shared plans carry the link, never the file.

  • ๐Ÿ”„ Replace an exercise in the routine editor (codedmind, #110) and keep its sets, reps, weight

and rule; print a single routine or save it as PDF (Teo230, #282); swipe left to delete a routine in Plan (Agripa22, #286); a drag handle on computers (seals187, #277, sgoendoer, #114).

  • A compact "+" on a day that already has a routine (seals187, #276), a live result count in

exercise search (GitLab !31), "benchpress" finds "bench press", cardio speed in mph for imperial users, the activity heatmap by time or by volume (Space-Hermes, #205), repeated exercises add up the same way in History and Stats (Space-Hermes, #212), a changed load cascades down the sets without overwriting the ones you set by hand (Space-Hermes, #209), and the Home body-weight card can be hidden (sacgsxr, #279). Languages

  • ๐Ÿ‡บ๐Ÿ‡ฆ Ukrainian (illinoiseeee, #285) and ๐Ÿ‡ธ๐Ÿ‡ฆ Arabic, laid out right to left (smsmy, GitLab

!36) — seventeen languages in all.

  • ๐Ÿ“– Exercise names in seven languages: German (mkoester, #290), Spanish (AlexRomero12, #245),

Russian (dima-po, #266), Italian and French (giulioleuci, #254), next to Brazilian Portuguese and Hungarian — each with a switch to show the English name beside it, or only the English name.

  • ๐ŸŒ DEFAULT_LANG (edgardjnr, #303) — an instance can pick the language of its sign-in screen and

of profiles that never chose one; otherwise a new visitor starts in their browser's language.

  • Russian demo strings (dima-po, #265), untranslated Coach equipment chips (dima-po, #264), and CSV

imports that read localized month names (sTOrM2202, #273).

  • "1 workout and 1 weigh-in" instead of "1 workouts and 1 weigh-ins" when signing in finds entries

from while you were signed out. The AI Coach

  • A review that swaps in an exercise the routine already has is told the rule and keeps the rest of

its proposal, instead of failing as "unusable" (fama-lama, #313).

  • Routine icons from the Coach work, and its plans pick more varied exercises (ameer-khan-ashraf,

#311).

  • The maximum message length is an admin setting (bluzername, #280, SSamDav, #267, #268).

  • A bonus set no longer reads as a stall you never had (kurktchiev, #287); Save in the Coach setup,

the demo Coach's failure state and the intake line are fixed (kurktchiev, #289); a weekly review is due until it has run, not for one minute a week (kurktchiev, #249).

  • On an iPhone the Coach waits out a slow local model instead of giving up after 30 seconds

(thedandano, part of #187), and the phone refuses a plain http:// endpoint with a reason.

  • A run that fails before its first status check still answers in the chat.

Imports

  • Strong: a workout's Duration is its length and its Workout Notes the session note, and timed

holds come in as seconds. Hevy: supersets come in as supersets. The import summary shows the year when the range is not this year. Android and iPhone

  • ๐Ÿ“ฑ Android 15: sheets sit on top of the keyboard with the field you are typing in above it,

and with three-button navigation the tab bar sits above the navigation bar, so a tap on a tab no longer lands on Home or Recents.

  • ๐ŸŽ iPhone: large photos and videos are kept in a form Safari can read back, so they play and

upload. The iOS build targets iOS 15.5 (clown-doing-code, #270).

  • ๐Ÿ“ฆ The release APK carries only the ARM builds and is about 12 MB smaller (#136). Automatic

backups go to Documents/openGym/ and only the newest 14 are kept (#161).

  • ๐Ÿ—‚️ Exercise pictures stay available offline in the installed web app (xwr3, #281).

Self-hosting

  • ๐Ÿšข Kubernetes (chriscowley, #304) — manifests in kubernetes/ and a guide,

docs/SELF_HOSTING_KUBERNETES.md, with both images pinned to the same release.

  • Settings shows your account id, for an admin who needs to find your data (ItzEarthy, #219); the

admin's "last sync" counts pulls as well as pushes. Security and robustness

  • ๐Ÿ›ก️ Coach hardening: everything that goes into a Coach prompt — what you typed, the plan, the

log, every id, and the "compare with others" figures — is bounded field by field before it is sent, so no text from another account can reach your prompt and an oversized request is never made.

  • ๐Ÿšฆ A sign-in throttle in front of the password routes, counted before the check.

  • The API answers a client's mistake as a client error and keeps its state cache bounded

(kurktchiev, #249); a push that carries nothing of the profile can no longer empty it on the server; the admin's activity log names what each pause was for. Community pull requests

  • Space-Hermes: edit saved workouts (#203), Ready rest timers and hold overtime (#204), the heatmap

by time or volume (#205), load cascades that keep manual edits (#209), save a session as a routine (#211), consistent totals for repeated exercises (#212), the swipe preview (#202).

  • kurktchiev: plate loading per set (#194), a build that names itself (#244), API hardening (#249),

the part of #250 this release took, the timer and hold fixes (#251), the API reference with the Coach routes (#255), check-locales that reads the translations (#256), sheet pinning (#257), a lighter tab bar (#258), and three Coach and effort fixes (#287, #288, #289).

  • bluzername: Set current to card view (#262), the Coach message length (#280), double progression

(#297), the service-worker timeout (#298).

  • dima-po: Coach equipment chips (#264), Russian demo strings (#265), Russian exercise names (#266).

  • Parth-Vasave (#263), vitox013 (#296), chriscowley (#304), ameer-khan-ashraf (#311), AlexRomero12

(#245), giulioleuci (#254), mkoester (#290), illinoiseeee (#285), clown-doing-code (#270), sTOrM2202 (#273), sacgsxr (#279), Agripa22 (#286); on GitLab smsmy (!36) and Josevi (!140).

  • Taken in part, with thanks: AlexanderVott (#95), thedandano (#187), horusglez (#295),

Vaibhav159 (#246). Thank you to everyone who reported, tested and wrote code for this one: andi242, seals187, Supportlik, Diego-Sanchez2000, danielkleinert, tpodolak, svillar, expressiveminute, ncbachh, codedmind, Teo230, Flxp49, xwr3, sgoendoer, fama-lama, SSamDav, edgardjnr, ItzEarthy, asierlama, Space-Hermes, kurktchiev, bluzername, dima-po, Parth-Vasave, vitox013, chriscowley, ameer-khan-ashraf, AlexRomero12, giulioleuci, mkoester, illinoiseeee, clown-doing-code, sTOrM2202, sacgsxr, Agripa22, smsmy, Josevi, AlexanderVott, thedandano, horusglez and Vaibhav159. Upgrading

  • Nothing to migrate: v1.3.8 data opens as it is.

  • Update paired phones. The fixes for silently unpaired phones are in the app, not the server;

a phone still on v1.3.8 can still get stuck.

  • "Sign out everywhere" unpairs phones too — each one then shows Pair again, and keeps its data.

  • New, all optional, in .env (see .env.example and docs/SELF_HOSTING.md):

  • PASSWORD_LOGIN=1 switches password sign-in on. It is off by default. Give the api container

-- at least 256 MB of memory when it is on.

  • TRUST_PROXY lets the sign-in throttle read the client's address from X-Forwarded-For. The

-- bundled docker-compose.yml now sets it, because there the api is reachable only through the -- web container. Running the api any other way, turn it on only when whatever sits in front -- overwrites that header.

  • MEDIA_* for exercise and workout photos and videos: MEDIA_UPLOADS=0 turns uploads off,

-- MEDIA_QUOTA_MB (200 per profile by default), MEDIA_MIN_FREE_MB (uploads stop below that much -- free disk), and the per-type size limits. Media needs disk space — on a small disk or with -- open signup, lower MEDIA_QUOTA_MB. Keep the web container's MEDIA_UPLOAD_MAX above -- MEDIA_VIDEO_MAX_MB.

  • DEFAULT_LANG for the instance's default language.

  • The api image carries new files (password.js, rate-limit.js, passkeys-store.js,

device-link.js, media.js). If you build your own image with an explicit file list, add them.

  • A reverse proxy with a short read timeout can cut off a slow video upload; photos are unaffected.

Known and not fixed: counts in Russian, Ukrainian and Polish still use the English two-form plural rule ("2 ะดะฝะตะน" where it should read "2 ะดะฝั"). The Ukrainian, Arabic, Hindi, Korean, Thai and Chinese packs have not been read by a native speaker yet — corrections are very welcome.

  • registry.gitlab.com/duartesantos8/opengym/api: 1.3.9 1.3 latest | sha256:88b192dd743ed3746ddeeb973952bdf380c810d6b69337b8205d96d053d7962f

  • registry.gitlab.com/duartesantos8/opengym/web: 1.3.9 1.3 latest | sha256:eb97d4f78a9d495a41d0181440ae3394feab41e7200b7a4a36099cee36e80036

Both images are linux/amd64 + linux/arm64. Android: openGym-1.3.9.apk (16.2 MB, ARM only), SHA-256 bf484160250db1bfb86baf99d585ef0d5c2306a6b364846ced8848bfa4820fb1 — check it with sha256sum -c openGym-1.3.9.apk.sha256. Signed with the same certificate as every release since v1.2.7 (0d22a49e…), so it installs over your current one. Built from e6c920eb.


Published on GitHub on 2026-09-28, mirroring the GitLab release of the same tag, where the artefacts above were built. The same images are on GHCR, built from this release by GitHub Actions: ghcr.io/duartesantos8/opengym-api:1.3.9 and ghcr.io/duartesantos8/opengym-web:1.3.9.

Performance and Compatibility

openGym is designed primarily as a self-hosted web application, but it also provides an Android application and can be installed as a PWA. The Docker deployment supports both AMD64 and ARM64, making it suitable for conventional servers as well as ARM-based systems.

The deployment architecture is relatively lightweight. The API uses Node.js, while the frontend is served through nginx. User data is stored under the application's data directory, including profiles, workout state, settings, and the session signing key. This makes backups straightforward because backing up the data directory effectively backs up the application data.

Offline functionality is particularly useful for a fitness tracker because workouts can continue even when the phone temporarily loses connectivity. Changes that have not reached the server are retained, and the application indicates when it is operating offline.

There are some important self-hosting considerations. Passkey authentication requires a properly configured HTTPS origin when accessing the application from a phone. The project provides guides for Cloudflare Tunnel, Caddy, Traefik, nginx, LAN HTTPS, and Kubernetes deployments.

The exercise media also deserves attention. The application downloads the exercise images and animations from an upstream dataset rather than redistributing them directly. The repository explicitly notes that the media has separate third-party licensing considerations and should not automatically be treated as covered by openGym's AGPL license.

System Requirements

  • Docker with Docker Compose for the recommended self-hosted deployment

  • AMD64 or ARM64 system for the provided container images

  • Persistent storage for application data and exercise media

  • HTTPS and a suitable domain when using passkeys from external devices

  • Android device for the native Android application

  • Modern web browser for the web/PWA interface

Pros and Cons

Pros

  • Open-source and self-hosted

  • Your workout data stays under your control

  • No subscription

  • No advertising

  • No required third-party account

  • Passkey authentication

  • Offline workout support

  • Cross-device synchronization

  • Progressive Web App support

  • Android application

  • Extensive exercise library

  • Animated exercise demonstrations

  • Workout planning and guided sessions

  • Supersets, warm-ups, and cardio tracking

  • Body-weight tracking

  • Muscle fatigue and detraining analysis

  • Personal records and statistics

  • Imports from FitNotes, Strong, and Hevy

  • Docker deployment

  • AMD64 and ARM64 container images

  • Kubernetes deployment support

Cons

  • Self-hosting requires some technical knowledge

  • HTTPS configuration is necessary for convenient passkey access from phones

  • Users are responsible for server backups and maintenance

  • Exercise media has separate third-party licensing considerations

  • The project is relatively young compared with established commercial fitness platforms

  • Some advanced functionality is still actively evolving

How to Install

The simplest deployment method is Docker Compose.

Clone the repository, create the environment file, pull the prebuilt images, and start the services:

git clone https://github.com/DuarteSantos8/openGym
cd openGym
cp .env.example .env
docker compose pull
docker compose up -d

The application can then be accessed through the configured web port. The first startup downloads the exercise media required by the application.

For access from a phone, configure HTTPS and a domain before relying on passkey authentication. The project documentation provides deployment examples for common reverse proxies and tunnel solutions.

Once installed, create a profile and configure your weekly routine. Existing workout history can also be imported from supported fitness applications.

Final Verdict

openGym is an impressive self-hosted alternative to conventional workout tracking services. Its strongest feature is not simply workout logging, but the combination of data ownership, offline support, passkey authentication, cross-device synchronization, exercise analytics, and a surprisingly complete training workflow.

The Docker-based deployment is particularly attractive for technically inclined users. The application can run on relatively inexpensive hardware, while its data directory makes backup and migration straightforward.

The main drawback is that self-hosting transfers responsibility for availability, HTTPS, backups, and updates to the user. The separate licensing situation surrounding exercise media is another consideration for anyone redistributing an installation.

For users who want a modern fitness tracker without handing their workout history to a third-party service, openGym is an excellent project and one of the more compelling self-hosted fitness applications available.

openGym APK for Android v1.3.9
Free
Software Informations:
Developer:

Operating System:
Android
Date Added:
2026-10-05T16:17:14.000Z
Categories:

Post a Comment/Report Broken Link: