- 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
150 lines
5.1 KiB
YAML
150 lines
5.1 KiB
YAML
x-info:
|
|
repo: https://github.com/CodeWithCJ/SparkyFitness
|
|
releases: https://github.com/CodeWithCJ/SparkyFitness/releases
|
|
documentation: https://codewithcj.github.io/SparkyFitness/
|
|
|
|
# nodes/heimdall/sparkyfitness/compose.yaml
|
|
# Deployed via Komodo | Managed by GitOps
|
|
# Service: sparkyfitness
|
|
# Source: https://github.com/CodeWithCJ/SparkyFitness
|
|
|
|
networks:
|
|
proxy-net:
|
|
external: true
|
|
sparkyfitness-network:
|
|
driver: bridge
|
|
|
|
services:
|
|
|
|
# ── Database ────────────────────────────────────────────────────────────────
|
|
sparkyfitness-db:
|
|
image: postgres:18.3-alpine
|
|
container_name: sparkyfitness-db
|
|
restart: unless-stopped
|
|
networks:
|
|
- sparkyfitness-network
|
|
environment:
|
|
POSTGRES_DB: sparkyfitness_db
|
|
POSTGRES_USER: sparky
|
|
POSTGRES_PASSWORD: "${SPARKY_FITNESS_DB_PASSWORD}"
|
|
PUID: 1000
|
|
GUID: 1000
|
|
volumes:
|
|
- /mnt/appdata/sparkyfitness/data/postgresql:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U sparky -d sparkyfitness_db"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
start_period: 30s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: "1.0"
|
|
memory: 512M
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ── Backend Server ───────────────────────────────────────────────────────────
|
|
sparkyfitness-server:
|
|
image: codewithcj/sparkyfitness_server:v0.16.6.1
|
|
container_name: sparkyfitness-server
|
|
restart: unless-stopped
|
|
networks:
|
|
- sparkyfitness-network
|
|
environment:
|
|
# Database connection
|
|
SPARKY_FITNESS_DB_HOST: sparkyfitness-db
|
|
SPARKY_FITNESS_DB_PORT: 5432
|
|
SPARKY_FITNESS_DB_NAME: sparkyfitness_db
|
|
SPARKY_FITNESS_DB_USER: sparky
|
|
SPARKY_FITNESS_DB_PASSWORD: "${SPARKY_FITNESS_DB_PASSWORD}"
|
|
SPARKY_FITNESS_APP_DB_USER: sparky_app
|
|
SPARKY_FITNESS_APP_DB_PASSWORD: "${SPARKY_FITNESS_APP_DB_PASSWORD}"
|
|
# Security — values sourced from .env (git-crypt)
|
|
SPARKY_FITNESS_API_ENCRYPTION_KEY: "${SPARKY_FITNESS_API_ENCRYPTION_KEY}"
|
|
BETTER_AUTH_SECRET: "${BETTER_AUTH_SECRET}"
|
|
# Application
|
|
SPARKY_FITNESS_FRONTEND_URL: "https://fitness.castaldifamily.com"
|
|
SPARKY_FITNESS_LOG_LEVEL: ERROR
|
|
NODE_ENV: production
|
|
TZ: Etc/UTC
|
|
SPARKY_FITNESS_DISABLE_SIGNUP: "false"
|
|
SPARKY_FITNESS_FORCE_EMAIL_LOGIN: "true"
|
|
ALLOW_PRIVATE_NETWORK_CORS: "false"
|
|
PUID: 1000
|
|
GUID: 1000
|
|
# Garmin microservice (disabled — service not yet stable)
|
|
# GARMIN_MICROSERVICE_URL: http://sparkyfitness-garmin:8000
|
|
volumes:
|
|
- /mnt/appdata/sparkyfitness/data/backup:/app/SparkyFitnessServer/backup
|
|
- /mnt/appdata/sparkyfitness/data/uploads:/app/SparkyFitnessServer/uploads
|
|
depends_on:
|
|
sparkyfitness-db:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -qO- http://localhost:3010/ 2>&1 | grep -q '.' || exit 1"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 60s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: "1.5"
|
|
memory: 512M
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ── Frontend ─────────────────────────────────────────────────────────────────
|
|
sparkyfitness-frontend:
|
|
image: codewithcj/sparkyfitness:v0.16.6.1
|
|
container_name: sparkyfitness-frontend
|
|
restart: unless-stopped
|
|
networks:
|
|
- proxy-net
|
|
- sparkyfitness-network
|
|
environment:
|
|
SPARKY_FITNESS_FRONTEND_URL: "https://fitness.castaldifamily.com"
|
|
SPARKY_FITNESS_SERVER_HOST: sparkyfitness-server
|
|
SPARKY_FITNESS_SERVER_PORT: 3010
|
|
PUID: 1000
|
|
GUID: 1000
|
|
depends_on:
|
|
sparkyfitness-server:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -q --spider http://localhost:80/ || exit 1"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 30s
|
|
labels:
|
|
# Enable Traefik
|
|
- "traefik.enable=true"
|
|
# HTTPS Router
|
|
- "traefik.http.routers.sparkyfitness.rule=Host(`fitness.castaldifamily.com`)"
|
|
- "traefik.http.routers.sparkyfitness.entrypoints=websecure"
|
|
- "traefik.http.routers.sparkyfitness.tls=true"
|
|
- "traefik.http.routers.sparkyfitness.tls.certresolver=cloudflare"
|
|
- "traefik.http.routers.sparkyfitness.service=sparkyfitness"
|
|
- "traefik.http.routers.sparkyfitness.middlewares=security-headers@file"
|
|
# Service definition
|
|
- "traefik.http.services.sparkyfitness.loadbalancer.server.port=80"
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: "0.5"
|
|
memory: 128M
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|