All apps · 0 apps
LiftTrace
Docker app from TraceApps' Repository
Overview
Readme
View on GitHubLiftTrace
Track Every Rep, Set, and PR
A self-hosted weightlifting tracker.
No accounts, no telemetry, no cloud sync unless you opt in.
Coming to Apple devices: the Trace apps have no iPhone app yet, because building and testing one needs a Mac and an iPhone. Chip in on Ko-fi. Self-hosting stays free either way.
Jump to: What it is · Features · Install · Env vars · Docs
What LiftTrace is
LiftTrace runs entirely in a single Docker container on your own hardware, with a PWA for the browser and a native Android app for your phone. No accounts on external services, no data leaving your network, no subscriptions. Log workouts, run programs, browse a multi-source exercise library, and ask an AI coach for form checks, all against your own SQLite file.
Principles
- Self-hosting is free. No paid tiers, no premium-only features behind a subscription, no nag screens.
- No telemetry. LiftTrace never phones home. There is no central server that receives your data, no analytics, no crash reporting, no fingerprinting.
- Your data, your hardware. Everything lives in a single SQLite file and an uploads folder on your machine. Back up either with
cp, restore withcp, migrate to a new server by moving the volume. - AGPL-3.0. The source is open and the network-use clause keeps it that way.

Features
- Diary and set logging. Weight, reps, RPE, warm-up marking, Smart Add prose parser, superset-aware rest timer, floating workout mode bar, workout completion share card. → full guide
- Programs and templates. Starter templates (Push/Pull/Legs, Upper/Lower, Full Body 3x), multi-week progression with Sessions or Calendar advance modes (v1.0.1). → full guide
- Exercise library. Four sources: wger (~600, CC-BY-SA), Free Exercise DB (~870, public domain), ExerciseDB (~1,300, RapidAPI BYO key), and ExerciseDB Open Source (self-hostable mirror, no key). Plus custom exercises and XLSX bulk import. → full guide
- Statistics and PRs. Metric-pill layout with Overview, Exercise Progress, Records, Volume, Frequency, and Body Weight views; automatic PR detection. → full guide
- Progress photos. Dated photos alongside your body stats, with a drag-to-compare before/after view for any two dates. Photos never expire, sync across devices, and are included in full backups. → full guide
- Trace AI coach. Reads your workouts, programs, PRs, body stats, and coach prescriptions; can log a workout, prescribe (if you are a coach), start a program template, or update your active program, all conversationally. 18 tools total. Multi-provider (Claude / OpenAI / Gemini / any OpenAI-compatible endpoint). Hold-to-record voice log, FFT visualizer. → full guide
- Radio player. Stream from Subsonic (Navidrome, Airsonic, Funkwhale, Gonic), Jellyfin, Plex, Emby, plus Icecast/Shoutcast/HLS internet radio with now-playing metadata. → full guide
- Coaching. Trainer accounts prescribe workouts to athletes; prescriptions surface in Diary on the right day. → full guide
- Workout history import. Bring your old log in from Strong, Hevy, FitNotes, Jefit (CSV) or Garmin FIT files. → full guide
- Multi-user and OIDC SSO. Role-based access (admin/trainer/member), invites, session policy, plus OIDC 1.0 SSO via Authentik, Keycloak, Pocket ID, Authelia, Google, Auth0, or any compliant provider. → full guide
- Native Android app. Local-only mode with on-device SQLite, or connect to your self-hosted server for sync. Media3 ExoPlayer, WorkManager reminders, biometric sign-in. → full guide
Apps
- Web (PWA). Install from any modern browser via the address bar (Chrome) or share menu (Safari). Works offline once cached.
- Android. Sideload the signed APK from the Releases page. Release APKs require HTTPS to your server; debug APKs accept plain HTTP. See DEPLOY.md for the four supported paths.
- iOS. No native build yet. Install the PWA from Safari (Share → Add to Home Screen).
Install
Published to two registries with identical tag sets: ghcr.io/traceapps/lifttrace (primary) and traceapps/lifttrace on Docker Hub (mirror). The snippet below uses GHCR; swap in traceapps/lifttrace:latest if that suits your setup.
Unraid: LiftTrace is in Community Applications. Search for LiftTrace in the Apps tab; the template sets the port, the appdata folders and the settings. Fill in JWT Secret before the first start.
services:
lifttrace:
image: ghcr.io/traceapps/lifttrace:latest
container_name: lifttrace
ports:
- "3002:3002"
volumes:
- ./data/db:/data/db
- ./data/uploads:/data/uploads
environment:
- DB_PATH=/data/db/lifttrace.db
- UPLOADS_PATH=/data/uploads
- JWT_SECRET=change-me-to-a-long-random-string
restart: unless-stopped
docker compose up -d
Open http://localhost:3002 and you're lifting.
See DEPLOY.md for image tag conventions, reverse proxies, subpath mounting, Cloudflare Tunnel, Docker secrets, and the four Android HTTPS paths.
Pre-release testers can grab the rolling dev-latest APK; occasional milestone builds also get numbered -devNN pre-releases. See DEPLOY.md for details.
Env vars
The essentials. Full reference in DEPLOY.md, .env.example, and the env vars docs page.
| Variable | Default | Purpose |
|---|---|---|
DB_PATH |
./lifttrace.db |
SQLite database file path |
UPLOADS_PATH |
./uploads |
Uploaded exercise media directory |
JWT_SECRET |
(required in prod) | JWT signing secret; server refuses to start in prod with the dev default |
TOKEN_ENC_KEY |
derived from JWT_SECRET |
At-rest encryption key for OIDC client secrets |
PORT |
3002 |
Server port inside the container (3003 before 1.3.0) |
LOG_LEVEL |
info |
error | warn | info | debug |
EXERCISE_SOURCES |
wger,free-db |
Sources to auto-seed on first boot (wger, free-db, exercisedb, exercisedb-oss) |
EXERCISEDB_OSS_URL |
(upstream) | Point the OSS exercise source at your own mirror |
INSECURE_COOKIES |
0 |
Set 1 only for non-HTTPS deployments |
BASE_URL |
(none) | Mount at a subpath (e.g. /lifttrace) instead of root |
RECOVERY_TOKEN |
(none) | Token for the "Disable user management" recovery endpoint |
SMTP_* |
(none) | SMTP for password reset emails and user invites |
AI_* |
(none) | Server-side AI proxy; AI_PROVIDER accepts claude | openai | gemini | oai-compat |
OIDC_* / OIDC_PROVIDER_N_* |
(none) | OIDC SSO declared in env instead of the UI |
OIDC_ENABLE_EMAIL_PASSWORD_LOGIN |
(none) | Set to 0 to disable password login server-wide (SSO-only) |
Data persistence and updating
All data lives in two bind-mounted directories: /data/db/lifttrace.db (SQLite) and /data/uploads/ (exercise media and backup ZIPs). Back up both with cp -r, restore by stopping the container and putting them back. Update with docker compose pull && docker compose up -d; volumes persist across updates.
Tech stack
- Frontend: Svelte 5 (Svelte-4 compatibility mode), svelte-spa-router, Vite 6, custom SVG charts
- Backend: Express 5, better-sqlite3, bcryptjs 3, cookie-based JWT auth
- PWA: vite-plugin-pwa, installable on any device
- Android: Capacitor 8, Media3 ExoPlayer, WorkManager, @capacitor-community/sqlite
- AI: Multi-provider (Claude, OpenAI, Gemini, OpenAI-compatible) with multimodal image support
- Deploy: Docker multi-stage build, GitHub Actions CI → GHCR
Trace family
Part of the TraceApps family. Sister apps: CookTrace for recipes and pantry, NutriTrace for nutrition tracking. Full docs for all three at traceapps.github.io/docs.
Roadmap, changelog, contributing, license
- ROADMAP.md for what's next.
- CHANGELOG.md for release history.
- CONTRIBUTING.md for pull-request guidance. Translations: see Contributing → Translations.
- AGPL-3.0: see LICENSE. By contributing you agree your contributions are licensed under the same.
Support
LiftTrace is free to self-host and always will be. No paid tier, nothing behind a donation, no telemetry. It's built and maintained by one person.
The current goal is a Mac and an iPhone. None of the Trace apps run properly on an iPhone, because building and testing for iOS needs Apple hardware, plus the developer accounts for both app stores. That comes to about $1,300, and the itemised breakdown is on the Support page.
Helping doesn't have to cost anything: starring the repo, reporting bugs with detail, and translating all count, and stars are how self-hosted projects get found.
Disclaimer
LiftTrace is not medical, health, or fitness-professional software. Exercise library content, Trace AI coaching, program templates, rest-timer guidance, and any analytical output are for informational and self-tracking purposes only. Resistance training carries inherent injury risk; consult a qualified healthcare professional or certified coach before starting a new program, returning from injury, or making significant changes. Trace AI answers can be incorrect; treat them as a starting point, not a substitute for professional advice. Use at your own risk.
Categories
Download Statistics
Related apps
Explore more like this
Explore allDetails
ghcr.io/traceapps/lifttrace:latestRuntime arguments
- Web UI
http://[IP]:[PORT:3002]/- Network
bridge- Shell
sh- Privileged
- false
Template configuration
Port for the web interface. Change the host port if 3002 is already taken.
- Target
- 3002
- Default
- 3002
- Value
- 3002
Folder for the SQLite database (lifttrace.db). Back up this folder and the Uploads folder.
- Target
- /data/db
- Default
- /mnt/user/appdata/lifttrace/db
- Value
- /mnt/user/appdata/lifttrace/db
Folder for photos and other uploaded files.
- Target
- /data/uploads
- Default
- /mnt/user/appdata/lifttrace/uploads
- Value
- /mnt/user/appdata/lifttrace/uploads
Required. Signs sign-in sessions and protects stored secrets. Use a long random string, for example the output of: openssl rand -base64 48. Keep it secret and keep it the same: changing it signs everyone out and makes stored sign-in and connection secrets unreadable.
- Target
- JWT_SECRET
1: sign-in works over plain http://, the way the WebUI link opens the app on your LAN. Session cookies then travel unencrypted, so keep the app on a network you trust. 0: session cookies are HTTPS-only. Use 0 behind an HTTPS reverse proxy; over plain http:// the browser drops them and signing in sends you back to the login page.
- Target
- INSECURE_COOKIES
- Default
- 1|0
- Value
- 1
Optional. Serve the app under a subpath behind a reverse proxy, for example /lifttrace. Empty: served at the root.
- Target
- BASE_URL
Optional. Turns on the lockout recovery option on the login page (Disable user management), which asks for this token. Empty: recovery stays off.
- Target
- RECOVERY_TOKEN
How much the server logs. Default: info.
- Target
- LOG_LEVEL
- Default
- info|error|warn|debug
- Value
- info
Database file inside the container. Leave as is: it sits in the Database folder above.
- Target
- DB_PATH
- Default
- /data/db/lifttrace.db
- Value
- /data/db/lifttrace.db
Uploads folder inside the container. Leave as is: it is the Uploads folder above.
- Target
- UPLOADS_PATH
- Default
- /data/uploads
- Value
- /data/uploads