- Compose file with pinned images (v0.16.6.1), healthchecks, Traefik routing - .env.example with all required variables and generation commands - README covering access, appdata, backup scope, upgrade procedure - KBA-002: deployment reference with verification and rollback steps - repo-deploy.prompt.md: reusable end-to-end deployment workflow prompt - Session snapshot 2026-05-10 Source: https://github.com/CodeWithCJ/SparkyFitness
7.1 KiB
SparkyFitness
Node: heimdall
Stack: sparkyfitness
URL: https://fitness.castaldifamily.com
Version: v0.16.6.1
Source: https://github.com/CodeWithCJ/SparkyFitness
Docs: https://codewithcj.github.io/SparkyFitness/
Overview
SparkyFitness is a self-hosted, privacy-first fitness and health tracking platform — a full alternative to MyFitnessPal. It stores all data on infrastructure you control with no reliance on third-party services.
Core capabilities:
- Nutrition, exercise, hydration, sleep, fasting, mood, and body measurement tracking
- Goal setting and daily check-ins
- Interactive charts and long-term reports
- Multiple user profiles and family access
- Native OIDC, TOTP, Passkey, and MFA support
- Health platform integrations: Apple Health, Google Health Connect, Fitbit, Withings, Garmin, Polar, Strava
- Food database integrations: OpenFoodFacts, USDA, FatSecret, Nutritionix
- Recipe app integrations: Mealie, Tandoor
- Optional AI chatbot for conversational food/exercise logging (beta)
Stack architecture:
| Container | Image | Role |
|---|---|---|
sparkyfitness-db |
postgres:18.3-alpine |
PostgreSQL database |
sparkyfitness-server |
codewithcj/sparkyfitness_server:v0.16.6.1 |
Node.js backend API |
sparkyfitness-frontend |
codewithcj/sparkyfitness:v0.16.6.1 |
React frontend (Nginx) |
Node
Runs on heimdall — the general-purpose applications node. No GPU is required. Workload is typical of a personal web application.
Access
| Method | Detail |
|---|---|
| URL | https://fitness.castaldifamily.com |
| Auth | SparkyFitness native auth (TOTP, passkeys, MFA supported) |
| SSO | Not configured — OIDC with Authentik can be added via env vars (see .env.example) |
| Admin panel | Set SPARKY_FITNESS_ADMIN_EMAIL in .env to auto-grant admin on first start |
⚠️ Set
SPARKY_FITNESS_DISABLE_SIGNUP=truein.envafter creating your initial account to prevent open registration.
Appdata
All persistent data lives under /mnt/appdata/sparkyfitness/data/ on the NFS share.
| Path | Contents | Backup Priority |
|---|---|---|
postgresql/ |
All user data — nutrition logs, workouts, health metrics, accounts | 🔴 Critical |
uploads/ |
Profile pictures and exercise images | 🟡 Important |
backup/ |
App-generated PostgreSQL exports | 🟢 Nice-to-have |
Pre-create these directories before first deploy:
mkdir -p /mnt/appdata/sparkyfitness/data/postgresql
mkdir -p /mnt/appdata/sparkyfitness/data/backup
mkdir -p /mnt/appdata/sparkyfitness/data/uploads
Environment Variables
Managed via .env (git-crypt encrypted). See .env.example for the full reference.
Required Secrets
| Variable | Purpose | How to Generate |
|---|---|---|
SPARKY_FITNESS_DB_PASSWORD |
PostgreSQL superuser password | openssl rand -base64 24 |
SPARKY_FITNESS_APP_DB_PASSWORD |
App-role DB password (limited privileges) | openssl rand -base64 24 |
SPARKY_FITNESS_API_ENCRYPTION_KEY |
64-char hex key for external integration encryption | openssl rand -hex 32 |
BETTER_AUTH_SECRET |
Signs sessions and encrypts TOTP/2FA data | openssl rand -hex 32 |
⚠️
SPARKY_FITNESS_API_ENCRYPTION_KEY— changing this after data is stored invalidates all encrypted external integration credentials.
⚠️BETTER_AUTH_SECRET— changing this after users have enabled TOTP/2FA locks them out. Do not rotate without disabling 2FA first.
Non-Secret Configuration (hardcoded in compose.yaml)
| Variable | Value | Notes |
|---|---|---|
SPARKY_FITNESS_FRONTEND_URL |
https://fitness.castaldifamily.com |
Used for CORS and session binding |
SPARKY_FITNESS_DB_HOST |
sparkyfitness-db |
Internal Docker service name |
SPARKY_FITNESS_DB_NAME |
sparkyfitness_db |
Database name |
SPARKY_FITNESS_DB_USER |
sparky |
Superuser for migrations |
SPARKY_FITNESS_APP_DB_USER |
sparky_app |
Runtime app user (limited privileges) |
SPARKY_FITNESS_LOG_LEVEL |
ERROR |
Use DEBUG temporarily for troubleshooting |
NODE_ENV |
production |
|
TZ |
Etc/UTC |
Adjust if local time is needed for date handling |
SPARKY_FITNESS_FORCE_EMAIL_LOGIN |
true |
Failsafe — prevents OIDC misconfiguration lockout |
Networking
| Network | Type | Used By |
|---|---|---|
proxy-net |
External (Traefik) | sparkyfitness-frontend only |
sparkyfitness-network |
Internal bridge | All three containers |
No host ports are exposed. All external traffic enters via Traefik.
Traefik Routing
| Field | Value |
|---|---|
| Router | sparkyfitness |
| Rule | Host(\fitness.castaldifamily.com`)` |
| Entrypoint | websecure (HTTPS) |
| TLS | Cloudflare cert resolver |
| Middleware | security-headers@file |
| Backend port | 80 (Nginx inside sparkyfitness-frontend) |
The frontend Nginx container internally proxies API requests to sparkyfitness-server:3010 over sparkyfitness-network. No separate Traefik route is needed for the API.
Dependencies
| Dependency | Type | Notes |
|---|---|---|
| PostgreSQL 18.3-alpine | Bundled | Self-contained — no shared DB instance |
| Traefik | External (core stack) | Must be running on proxy-net |
| Cloudflare DNS | External | Required for TLS cert resolver |
No Redis, GPU, or kernel module dependencies.
Backup & Recovery
What to Back Up
The postgresql/ directory is the single source of truth for all user data. This must be in the backup rotation before going live.
/mnt/appdata/sparkyfitness/data/postgresql/ ← Critical
/mnt/appdata/sparkyfitness/data/uploads/ ← Important
Restore Steps
- Stop the stack:
docker compose down - Restore the PostgreSQL data directory to
/mnt/appdata/sparkyfitness/data/postgresql/ - Restore uploads to
/mnt/appdata/sparkyfitness/data/uploads/ - Redeploy:
docker compose up -d - Verify the DB is healthy:
docker compose logs sparkyfitness-db
Upgrading
⚠️ Auto-updating containers is not recommended by the maintainer. Watchtower should be excluded from this stack.
- Review release notes at https://github.com/CodeWithCJ/SparkyFitness/releases
- Take a backup of
postgresql/ - Update image tags in
compose.yaml - Commit and push — Komodo will redeploy via webhook
- Check logs:
docker compose logs --tail=50
Known Issues / Notes
- Garmin microservice (
sparkyfitness-garmin) is still in development upstream. It is commented out of the compose file intentionally. Do not enable until the maintainer marks it stable. - Auto-update warning: The maintainer explicitly warns against automated container updates between releases. Ensure Watchtower is not targeting this stack.
- Postgres upgrade notice: The upstream release notes flag a forthcoming mandatory Postgres upgrade. Monitor release notes and follow the official Postgres upgrade guide when the time comes.
- AI chatbot is in beta — expect potential bugs if enabled.
- Family & Friends access is in beta — expect potential bugs if enabled.