- 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
221 lines
6.2 KiB
Markdown
221 lines
6.2 KiB
Markdown
# KBA-002: SparkyFitness — Initial Deployment on Heimdall
|
||
|
||
**Status:** Active
|
||
**Created:** May 10, 2026
|
||
**Last Updated:** May 10, 2026
|
||
**Affected Systems:** heimdall, Komodo, Traefik
|
||
**Severity:** Informational
|
||
|
||
---
|
||
|
||
## Summary
|
||
|
||
Reference article for deploying SparkyFitness (self-hosted fitness tracker) on the heimdall node. Covers pre-deployment checklist, secret generation, first-boot sequence, and verification steps.
|
||
|
||
---
|
||
|
||
## Use Case
|
||
|
||
You want to deploy SparkyFitness for the first time, or you are recovering from a failed deployment or data loss event and need to redeploy from scratch.
|
||
|
||
---
|
||
|
||
## Prerequisites
|
||
|
||
### Access Required
|
||
|
||
- [ ] SSH access to `heimdall`
|
||
- [ ] Gitea access: `git.castaldifamily.com`
|
||
- [ ] Komodo UI access: `komodo.castaldifamily.com`
|
||
- [ ] NFS share mounted and writable at `/mnt/appdata/` on heimdall
|
||
|
||
### Files in Repo
|
||
|
||
Confirm these files exist in `nodes/heimdall/sparkyfitness/` on `main`:
|
||
|
||
- [ ] `compose.yaml`
|
||
- [ ] `.env.example`
|
||
- [ ] `README.md`
|
||
|
||
---
|
||
|
||
## Resolution / Deployment Steps
|
||
|
||
### Step 1 — Generate Secrets
|
||
|
||
On any machine with `openssl` available, generate the four required secrets:
|
||
|
||
```bash
|
||
# API encryption key — SAVE THIS. Do not rotate after data is stored.
|
||
openssl rand -hex 32
|
||
|
||
# Better Auth secret — SAVE THIS. Do not rotate after users enable 2FA.
|
||
openssl rand -hex 32
|
||
|
||
# Database superuser password
|
||
openssl rand -base64 24
|
||
|
||
# Application user password
|
||
openssl rand -base64 24
|
||
```
|
||
|
||
Store these immediately in the git-crypt-encrypted `.env` file at:
|
||
|
||
```
|
||
nodes/heimdall/sparkyfitness/.env
|
||
```
|
||
|
||
Using `.env.example` as the template:
|
||
|
||
```bash
|
||
cp nodes/heimdall/sparkyfitness/.env.example nodes/heimdall/sparkyfitness/.env
|
||
# Edit .env and fill in all four required secret values
|
||
```
|
||
|
||
> ⚠️ Confirm `.gitattributes` marks `nodes/heimdall/sparkyfitness/.env` as a git-crypt file before committing.
|
||
|
||
### Step 2 — Create Appdata Directories
|
||
|
||
SSH into heimdall and pre-create the required directories:
|
||
|
||
```bash
|
||
ssh heimdall
|
||
mkdir -p /mnt/appdata/sparkyfitness/data/postgresql
|
||
mkdir -p /mnt/appdata/sparkyfitness/data/backup
|
||
mkdir -p /mnt/appdata/sparkyfitness/data/uploads
|
||
```
|
||
|
||
> PostgreSQL will fail to initialize if `postgresql/` does not exist or has incorrect ownership. Docker will create the directory automatically, but pre-creating it ensures the NFS mount is active and writable before the container starts.
|
||
|
||
### Step 3 — Commit and Push
|
||
|
||
```bash
|
||
git add nodes/heimdall/sparkyfitness/
|
||
git commit -m "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 documented
|
||
- README covering access, appdata, backup scope
|
||
|
||
Source: https://github.com/CodeWithCJ/SparkyFitness"
|
||
git push origin main
|
||
```
|
||
|
||
### Step 4 — Create Komodo Stack
|
||
|
||
1. Open Komodo UI → **Stacks** → **New Stack**
|
||
2. Configure:
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| **Name** | `sparkyfitness` |
|
||
| **Server** | `heimdall` |
|
||
| **Source** | Git Repo |
|
||
| **Repo** | `homelab` |
|
||
| **Branch** | `main` |
|
||
| **Run Directory** | `nodes/heimdall/sparkyfitness` |
|
||
| **File Paths** | *(leave blank — uses `compose.yaml` by default)* |
|
||
| **Webhook** | Enable — trigger on push to `main` |
|
||
| **Auto Update** | ❌ Disabled |
|
||
|
||
3. Click **Deploy**
|
||
|
||
### Step 5 — First Boot Sequence
|
||
|
||
The startup order is enforced by `depends_on` + `healthcheck` conditions:
|
||
|
||
```
|
||
sparkyfitness-db (healthy) → sparkyfitness-server (healthy) → sparkyfitness-frontend
|
||
```
|
||
|
||
Expected timeline:
|
||
- `sparkyfitness-db`: healthy within ~30 seconds
|
||
- `sparkyfitness-server`: ~60–90 seconds (runs DB migrations on first boot)
|
||
- `sparkyfitness-frontend`: starts once server is healthy
|
||
|
||
Monitor startup:
|
||
|
||
```bash
|
||
ssh heimdall
|
||
docker compose -f /etc/komodo/stacks/sparkyfitness/compose.yaml logs -f
|
||
```
|
||
|
||
### Step 6 — Set Admin Account
|
||
|
||
If `SPARKY_FITNESS_ADMIN_EMAIL` is set in `.env`, the first user with that email will be automatically granted admin on server startup.
|
||
|
||
Alternatively, register via the UI at https://fitness.castaldifamily.com, then promote from the Admin panel.
|
||
|
||
> After creating your account, set `SPARKY_FITNESS_DISABLE_SIGNUP=true` in `.env` to close open registration. Redeploy to apply.
|
||
|
||
---
|
||
|
||
## Verification
|
||
|
||
Run through the following checks after deployment:
|
||
|
||
### Container Health
|
||
|
||
```bash
|
||
docker ps --filter "name=sparkyfitness"
|
||
# All three containers should show: Up X minutes (healthy)
|
||
```
|
||
|
||
### Log Check
|
||
|
||
```bash
|
||
docker compose logs --tail=50 sparkyfitness-server
|
||
# Should show: server started, DB migrations complete, no ERRORs
|
||
```
|
||
|
||
### UI Access
|
||
|
||
- Open https://fitness.castaldifamily.com in a browser
|
||
- Confirm: HTTPS with valid certificate, no browser errors
|
||
- Confirm: Login page loads
|
||
|
||
### Traefik Routing
|
||
|
||
- Open Traefik dashboard → confirm `sparkyfitness` router is active and green
|
||
- Confirm TLS cert is issued via Cloudflare resolver
|
||
|
||
### Restart Resilience
|
||
|
||
```bash
|
||
docker restart sparkyfitness-frontend
|
||
# Wait 30s, then confirm the UI is still accessible
|
||
```
|
||
|
||
---
|
||
|
||
## Rollback
|
||
|
||
If deployment fails and you need to revert:
|
||
|
||
1. Stop the stack in Komodo: **Stack → Stop**
|
||
2. Remove containers: `docker compose down` on heimdall
|
||
3. The `postgresql/` data directory is untouched by `docker compose down` (bind mount, not a volume)
|
||
4. Revert the compose file changes in Git and push — Komodo will redeploy the previous version
|
||
|
||
> ⚠️ `docker compose down -v` would only affect named volumes. Since we use bind mounts, data in `/mnt/appdata/sparkyfitness/data/` is always preserved unless you manually delete it.
|
||
|
||
---
|
||
|
||
## Related Resources
|
||
|
||
- [SparkyFitness README](../../nodes/heimdall/sparkyfitness/README.md)
|
||
- [Upstream GitHub](https://github.com/CodeWithCJ/SparkyFitness)
|
||
- [Official Docs](https://codewithcj.github.io/SparkyFitness/)
|
||
- [Docker Compose Install Guide](https://codewithcj.github.io/SparkyFitness/install/docker-compose)
|
||
- [Environment Variables Reference](https://codewithcj.github.io/SparkyFitness/install/environment-variables)
|
||
- [Postgres Upgrade Guide](https://codewithcj.github.io/SparkyFitness/install/postgres-upgrade)
|
||
- [KBA-001: Komodo GitOps Stack Deployment Failures](KBA-001-Komodo-GitOps-Stack-Deployment-Failures.md)
|
||
|
||
---
|
||
|
||
## Revision History
|
||
|
||
| Date | Author | Change |
|
||
|---|---|---|
|
||
| 2026-05-10 | Nathan Castaldi | Initial deployment — SparkyFitness v0.16.6.1 on heimdall |
|