openGym README

The project's README from github.com/DuarteSantos8/openGym. As one markdown file: README.md.

openGym

A self-hosted gym and body-weight tracker you actually own.

Plan your week, run guided workouts, log every set and your body weight,
on your phone, synced across your devices, behind your own passkey login.

Discord Online GitHub stars

DuarteSantos8%2FopenGym | Trendshift DuarteSantos8%2FopenGym | Trendshift

Release Downloads Tests Pipeline Coverage License: AGPL v3

Website · Live demo · Android APK · Self-hosting guide · Roadmap · Changelog

Buy Me A Coffee Support openGym on Ko-fi

Home screen
Home · today's workout and weight
Workout screen
Guided workout · demos and sets
Stats screen
Stats · heatmap, charts and PRs

Why openGym

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.

Features

Planning

Training

Progress

Accounts and data

Optional extras, off by default

The full list of what changed release by release is in the changelog.

Quick start

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 and Kubernetes.

[!NOTE] Images are published from the same tag to ghcr.io/duartesantos8/opengym-{api,web} (what docker-compose.yml pulls) and registry.gitlab.com/duartesantos8/opengym/{api,web}. Swap the image: lines if you prefer GitLab's registry, or run docker compose up -d --build to build locally. Either way you don't need Node on the host.

Configuration reference (all through .env)
Variable What it does Default
RP_ID Hostname passkeys are bound to localhost
ORIGIN Full URL the app is served from http://localhost:8080
WEB_PORT Host port for the web UI 8080
NGINX_PORT Port the web container listens on inside the container 80
BACKEND Name of the API service that /api is proxied to api
PORT Port the API listens on; the web container proxies to the same value 3000
RP_NAME Name shown in the passkey prompt openGym
SESSION_DAYS How long a sign-in lasts, in days 90
ADMIN_UIDS User ids that get the admin dashboard, comma-separated (none)
FIRST_USER_ADMIN 1: the first profile created on an empty instance becomes its admin (off)
INVITE_ONLY Require an invite code to create a profile (off)
ALLOW_GUEST Offer "Continue without account"; 0 requires a profile (on)
PASSWORD_LOGIN Offer name-and-password sign-in next to passkeys (off)
TRUST_PROXY Let the sign-in throttle read the client address from proxy headers 1 in docker-compose.yml
AUDIT_LOG Record sign-ins and admin actions; 0 records nothing (on)
AUDIT_MAX Events kept in the activity log; 0 for no limit 5000
AUDIT_DAYS Days kept in the activity log; 0 keeps until AUDIT_MAX 90
AUDIT_IP Record the caller's address: off, net (network only) or full off
ALLOWED_PRIVATE_IPS Private addresses push endpoints may resolve to (FakeDNS, split-horizon DNS): comma-separated IPs, a-b ranges or CIDR blocks (none)
VAPID_SUBJECT Contact URL sent with push notifications your ORIGIN
API_TARGET API image to build: default, or coach with the Claude Agent SDK and Codex CLI default
COACH_DISABLED 1 forces the AI coach off instance-wide (unset)

Push-notification keys are generated on first run into ./data/vapid.json. DATA_DIR is pinned to /data inside the container and mapped to ./data on the host; change the volume, not the variable. The self-hosting guide covers every option in detail.

Phone app

The same codebase builds a standalone app with Capacitor: no account, no server, everything stays on the phone, with native reminders and a rest countdown in the notification shade.

Details and build instructions: docs/MOBILE.md.

How it works

Architecture: the phone talks HTTPS to nginx (web), which serves the app and proxies /api to the Node api; the api stores JSON in ./data. The exercise media ship inside the web image; the AI coach and MCP server are optional.

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.

How sync works

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.

Sync: a device saves with the revision it last saw; if another device wrote in between, the server answers 409 with the current document, the device merges and saves again.

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.

Your data

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.

Documentation

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

Roadmap

A release roughly every two weeks, each small and themed. The full plan is in ROADMAP.md, and the issues sit in the GitHub milestones. The next two releases finish the community wishes, then comes a new exercise database and a themed release every two weeks after it.

Release When Theme
v1.3.10 released Oct 2026 New design, rotation, swipe actions, safer sync
v1.3.11 next Fixes, about thirty community pull requests, Health Connect, measurements
v1.3.12 Nov 2026 Community features: focus view, widget, timer rework
v1.4.0 Nov 2026 A new exercise database
v1.4.1 to v1.4.4 Dec 2026 and Jan 2027 Programmes, the progression engine, cardio
v1.4.5 to v1.4.10 Jan to Apr 2027 Search, accounts, the iOS app, Android and health, looks
later Database storage

Community

Contributors

Where the code lives

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 release artifacts: the signed APK, the multi-arch images and the SBOMs. 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.

How openGym is built

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.

Support

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 a coffee button below. A star, a bug report or a pull request helps just as much.

Buy Me A Coffee

Star History Chart

License

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.

Full third-party notices, including the body-diagram geometry, are in NOTICE.md.

openGym (DuarteSantos8/openGym)

Searching Database…

13.4K ·GitHub
这是什么?一个自托管的健身房和体重追踪工具,运行在你自己的服务器上:可以制定训练计划、跟练指导课程、记录每一组训练和你的体重。无需订阅、没有广告、不收集遥测数据;你的数据完全归你所有。
我在浏览器里用还是在手机上用?都可以。它是一个自托管的网页应用,可以作为 PWA 添加到主屏幕,而且同一套代码还能构建出独立的 Android APK(有意不上架 Play 商店)。在 iPhone 上通过 Safari 添加这个 PWA 即可。
我怎么把它跑起来?安装带 Compose 的 Docker,把仓库里的 docker-compose.yml 放到相应位置,然后运行 docker compose up;镜像从 ghcr.io 拉取,所以主机上不需要 Node。.env 中的 RPID 和 ORIGIN 会把通行密钥绑定到你的域名。
安装过程中有什么容易踩的坑吗?最常见的麻烦是登录:通行密钥绑定到你的主机名,所以出问题几乎都是 RPID/ORIGIN 不匹配造成的,自托管指南里有专门说明。
我的数据实际存在哪里?存在你自己主机的 ./data 目录里,就是普通的 JSON 文件,复制一下就能备份。没有广告,没有遥测,也不需要在别人的服务器上注册账号,通行密钥的私钥绝不会传到服务器。
有 AI 教练吗?运行它需要什么?有,属于可选功能,默认关闭:它能起草一周的训练计划,之后还会建议调整,由你逐条确认。它运行在你自己的服务器上,需要你自己的服务商密钥:Anthropic、OpenAI、Gemini、任何兼容 OpenAI 的接口或 Ollama 都可以。
MCP 服务器是干什么用的?它可以让 Claude Desktop 这类助手查询你的训练历史。它是只读的,在本地运行,也不属于 Docker 构建的一部分。
它支持多少种语言?19 种,包括从右到左书写的阿拉伯语和繁体中文,其中大部分语言的动作名称和说明都已翻译好。
openGym 多久更新一次?大约每两周发布一个小型主题版本;路线图上列出了 Health Connect、主屏幕小组件、新的动作数据库,以及未来的原生 iOS 应用。
What are similar projects?openGym, SparkyFitness, pl_mail, TREK, noop, layerling, Termix, edgeever
Size
298.7 MB
Stars
13.4K
Age
3mo
Commits · 90 Days