Nathan 54a885120d feat(sparkyfitness): add sparkyfitness stack to heimdall
- 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
2026-05-10 21:58:38 -04:00
..

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=true in .env after 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

  1. Stop the stack: docker compose down
  2. Restore the PostgreSQL data directory to /mnt/appdata/sparkyfitness/data/postgresql/
  3. Restore uploads to /mnt/appdata/sparkyfitness/data/uploads/
  4. Redeploy: docker compose up -d
  5. 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.

  1. Review release notes at https://github.com/CodeWithCJ/SparkyFitness/releases
  2. Take a backup of postgresql/
  3. Update image tags in compose.yaml
  4. Commit and push — Komodo will redeploy via webhook
  5. 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.