LiftTrace

LiftTrace

Docker app from TraceApps' Repository

Overview

LiftTrace is a self-hosted weightlifting tracker. Log sets with weight, reps and RPE, run multi-week programs from starter templates or your own, and pick exercises from a library drawn from wger, Free Exercise DB and ExerciseDB, plus your own custom exercises. Statistics cover progress per exercise, records, volume, frequency and body weight, with automatic PR detection and dated progress photos. Trainer accounts can prescribe workouts to athletes, and you can import your history from Strong, Hevy, FitNotes, Jefit or Garmin FIT files. Multi-user with OIDC single sign-on and a native Android app. No telemetry and no accounts on external services; your data stays in your appdata folder. Before the first start, set JWT_SECRET to a long random string, for example the output of openssl rand -base64 48. INSECURE_COOKIES starts at 1 so that signing in works over plain http:// on your LAN, which is how the WebUI link opens the app. Once the app sits behind an HTTPS reverse proxy, set it to 0.

LiftTrace

Track Every Rep, Set, and PR

A self-hosted weightlifting tracker.
No accounts, no telemetry, no cloud sync unless you opt in.

LiftTrace

License Latest release Downloads Stars Platform
Documentation GHCR Docker Hub pulls Translation status

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 with cp, 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.

LiftTrace diary view


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

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.

Ko-fi GitHub Sponsors

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

15,813
Total Downloads

Related apps

Explore more like this

Explore all

Details

Repository
ghcr.io/traceapps/lifttrace:latest
Last Updated2026-10-11
First Seen2026-10-11

Runtime arguments

Web UI
http://[IP]:[PORT:3002]/
Network
bridge
Shell
sh
Privileged
false

Template configuration

Web UI PortPorttcp

Port for the web interface. Change the host port if 3002 is already taken.

Target
3002
Default
3002
Value
3002
DatabasePathrw

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
UploadsPathrw

Folder for photos and other uploaded files.

Target
/data/uploads
Default
/mnt/user/appdata/lifttrace/uploads
Value
/mnt/user/appdata/lifttrace/uploads
JWT SecretVariable

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
Insecure CookiesVariable

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
Base URLVariable

Optional. Serve the app under a subpath behind a reverse proxy, for example /lifttrace. Empty: served at the root.

Target
BASE_URL
Recovery TokenVariable

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
Log LevelVariable

How much the server logs. Default: info.

Target
LOG_LEVEL
Default
info|error|warn|debug
Value
info
Database FileVariable

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 FolderVariable

Uploads folder inside the container. Leave as is: it is the Uploads folder above.

Target
UPLOADS_PATH
Default
/data/uploads
Value
/data/uploads