github DuarteSantos8/openGym v1.2.9

latest releases: v1.3.5, v1.3.4, v1.3.3...
4 hours ago

If you run openGym for other people, you have had no way to answer "who signed in, and when?" —
the server kept no record of anything. It does now: an activity log in the admin dashboard,
covering sign-ins, sign-outs, the attempts that failed, and every admin action. The other half of
this release is that the live demo is back, self-hosted this time, after two months offline.
And the project has a working home again: openGym now lives on GitLab, where CI builds the
container images and the signed Android APK for every release — the thing that has been missing
since the GitHub account went.

Activity log

  • 🧾 The admin dashboard has an activity log. Successful and failed sign-ins, profile
    creations and refused signups, sign-outs (including "sign out everywhere"), and every admin
    action: disabling or re-enabling an account, creating or revoking an invite code, and clearing
    the log itself. Filter it by sign-ins, admin actions or failures, and page back through it.
  • 📄 It is a plain file. ./data/audit.log, one JSON object per line — tail -f and jq
    read it directly, which also means it is its own export format. Deliberately not part of
    db.json: that file is rewritten in full on every save, and the sign-in handshake is
    unauthenticated, so a log living in there would have turned one junk request into a full
    rewrite. Retention is a cap rather than an archive — the last AUDIT_MAX events (5,000) or
    AUDIT_DAYS days (90), whichever runs out first.
  • 🔒 It records less than you might expect, on purpose. No IP addresses unless you turn them
    on (AUDIT_IP=net keeps only the network, full keeps the address); never the browser's
    user-agent; and never the passkey id behind a failed sign-in, because that id is a stable handle
    for one device and storing it would let an admin follow an unknown device from one attempt to
    the next. A rejected invite code is not stored either — a near-miss guess sitting in a log file
    helps nobody.
  • 🧹 Clearing it is itself logged, and the event ids keep counting, so an erased stretch always
    leaves a visible gap.
  • ⚙️ On by default when you update, and one variable turns it off. It records strictly less
    than your instance already holds — every profile is in db.json, every workout is in
    state-<uid>.json, and any admin can already read both — and a log that ships switched off
    tells you nothing on the day you need it. AUDIT_LOG=0 disables it completely; no file is
    written. Nothing leaves your server either way: this is a local file, not telemetry.
  • Guests still never appear anywhere — guest mode does not talk to the server at all.

The live demo is back

  • ▶️ https://opengym.duarte-santos.ch/demo/ — the in-browser demo, running on the project's
    own site instead of GitHub Pages, which went down in August with the suspended account. Same
    build as before: no backend, no account, seeded example history, and a reset button in its
    settings. The embedded demo on the landing page works again too.

openGym moved to GitLab

  • 🏠 https://gitlab.com/DuarteSantos8/opengym is the home of the project. Same history,
    same tags, same AGPL. gitea.com was the stopgap after the GitHub suspension and stays as a
    mirror; it never had a CI runner, which is why releases there had no images.
  • 🐳 Prebuilt images are back. docker compose pull now fetches
    registry.gitlab.com/duartesantos8/opengym/api and /web, built for amd64 and arm64 on
    every release. Pulling is anonymous — the project is public, no login, no token.
  • 🤖 The APK is built by CI now, not by hand. Every vX.Y.Z tag produces a zipaligned,
    signed APK, attached to the GitLab release and mirrored onto the download page. The signing
    key sits in protected CI variables, so it exists only on main and on version tags — a
    merge request from a fork builds an unsigned APK and never touches the key.
  • Every merge request is tested again. The frontend suite (346 tests), the locale checks,
    the fatigue probe and the MCP suite all run on GitLab CI. The GitHub Actions workflows stay
    in .github/ for the day that account comes back.
  • 🌐 The in-browser demo also builds to GitLab Pages
    (https://opengym-bc111a.gitlab.io/, which https://duartesantos8.gitlab.io/opengym/
    redirects to); https://opengym.duarte-santos.ch/demo/ remains the copy the landing page
    embeds.
  • 📄 Security reports have a private channel again: a confidential issue on GitLab. See
    SECURITY.md.
  • 🔁 Dependency updates continue. GitLab has no Dependabot, so Renovate runs from a monthly
    scheduled pipeline with the same deliberately quiet policy the Dependabot config had:
    grouped per ecosystem, majors on their own, odd-numbered Node images skipped, and the
    generated android//ios/ projects left to follow their @capacitor/* packages. Security
    advisories ignore the schedule and land on their own.

Housekeeping

  • The self-hosting docs, SECURITY.md and .env.example cover the activity log, and the
    api/server.js line references in SECURITY.md are accurate again.
  • Every repository link in the README, the docs, the app and the website points at GitLab, and
    the website's live star/release numbers come from GitLab's API.

Published on GitHub on 2026-09-11, mirroring the GitLab release of the same tag, where the artefacts above were built (!NN numbers are GitLab merge requests). The same images are on GHCR, built from this release by GitHub Actions: ghcr.io/duartesantos8/opengym-api:1.2.9 and ghcr.io/duartesantos8/opengym-web:1.2.9.

Don't miss a new openGym release

NewReleases is sending notifications on new releases.