README.md
Rama main · réplica de lectura del repositorio original.
<!--
THIS FILE IS AUTOGENERATED - DO NOT EDIT MANUALLY
Source: dbuild templates
-->
# SparkyFitness
[](https://github.com/daemonless/sparkyfitness/actions)
[](https://github.com/daemonless/sparkyfitness/commits)
[](https://hub.docker.com/r/daemonless/sparkyfitness)
Self-hosted privacy-first fitness tracker on FreeBSD.
| | |
|---|---|
| **Registry** | `ghcr.io/daemonless/sparkyfitness` |
| **Source** | [https://github.com/CodeWithCJ/SparkyFitness](https://github.com/CodeWithCJ/SparkyFitness) |
| **Website** | [https://github.com/CodeWithCJ/SparkyFitness](https://github.com/CodeWithCJ/SparkyFitness) |
## Version Tags
| Tag | Description | Best For |
| :--- | :--- | :--- |
| `latest` | **Upstream Binary**. Built from official release. | Most users — recommended. |
## Parts
| Service | Image | Role | |
|---|---|---|---|
| **sparkyfitness** | `ghcr.io/daemonless/sparkyfitness:${SPARKYFITNESS_TAG:-latest}` | | [docs](https://github.com/daemonless/sparkyfitness) |
| **sparkyfitness-db** | `ghcr.io/daemonless/postgres:18` | | [docs](https://github.com/daemonless/postgres) |
## Prerequisites
Before deploying, ensure your host environment is ready. See the [Quick Start Guide](https://daemonless.io/guides/quick-start) for host setup instructions.
## Deployment
### Podman Compose
**1.** Save as `.env` and fill in what is empty:
```env { data-zip-bundle="sparkyfitness-podman" data-zip-filename=".env" }
# SparkyFitness for FreeBSD (Daemonless)
# Copy to .env and edit.
# Timezone (TZ identifier)
# TZ=UTC
# Where data lives on the host
UPLOADS_LOCATION=/containers/sparkyfitness/uploads
BACKUPS_LOCATION=/containers/sparkyfitness/backups
DB_DATA_LOCATION=/containers/sparkyfitness/postgres
# PostgreSQL superuser + database (provisioned by the sidecar)
SPARKY_FITNESS_DB_NAME=sparkyfitness
SPARKY_FITNESS_DB_USER=sparky
# Change this to a random password! A-Za-z0-9 only.
SPARKY_FITNESS_DB_PASSWORD=sparky
# Limited app role the backend creates during migrations
SPARKY_FITNESS_APP_DB_USER=sparky_app
SPARKY_FITNESS_APP_DB_PASSWORD=sparky_app
# Secrets: no defaults on purpose -- these become the catalog's install
# defaults, and a shipped value would be shared by every install. Generate
# your own, e.g. `openssl rand -hex 32` for each.
SPARKY_FITNESS_API_ENCRYPTION_KEY=
BETTER_AUTH_SECRET=
# Public URL the browser uses to reach the app, e.g. http://myhost:3004.
# No default on purpose: Better Auth compares this against the request origin
# and rejects the sign-up POST when it does not match, so a shipped default is
# wrong for everyone who does not browse from the server itself.
SPARKY_FITNESS_FRONTEND_URL=
```
**2.** Save as `compose.yaml`:
```yaml { data-zip-bundle="sparkyfitness-podman" data-zip-filename="compose.yaml" }
name: sparkyfitness
services:
sparkyfitness:
# Tag in a ${VAR} so the catalog exposes it as an image_tag variable and the
# install wizard can offer this repo's published versions. The database is
# pinned deliberately: retagging it would be a destructive migration.
image: ghcr.io/daemonless/sparkyfitness:${SPARKYFITNESS_TAG:-latest}
container_name: sparkyfitness
restart: unless-stopped
network_mode: host
depends_on:
- sparkyfitness-db
environment:
- PUID=1000
- PGID=1000
- TZ=${TZ:-UTC}
- NODE_ENV=production
- SPARKY_FITNESS_DB_HOST=${SPARKY_FITNESS_DB_HOST:-127.0.0.1}
- SPARKY_FITNESS_DB_PORT=5433
- SPARKY_FITNESS_DB_NAME=${SPARKY_FITNESS_DB_NAME}
- SPARKY_FITNESS_DB_USER=${SPARKY_FITNESS_DB_USER}
- SPARKY_FITNESS_DB_PASSWORD=${SPARKY_FITNESS_DB_PASSWORD}
- SPARKY_FITNESS_APP_DB_USER=${SPARKY_FITNESS_APP_DB_USER}
- SPARKY_FITNESS_APP_DB_PASSWORD=${SPARKY_FITNESS_APP_DB_PASSWORD}
- SPARKY_FITNESS_API_ENCRYPTION_KEY=${SPARKY_FITNESS_API_ENCRYPTION_KEY}
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
- SPARKY_FITNESS_FRONTEND_URL=${SPARKY_FITNESS_FRONTEND_URL}
- SPARKY_FITNESS_SERVER_HOST=127.0.0.1
- SPARKY_FITNESS_SERVER_PORT=3010
- SPARKY_FITNESS_LOG_LEVEL=ERROR
volumes:
- ${UPLOADS_LOCATION}:/app/server/uploads
- ${BACKUPS_LOCATION}:/app/server/backup
sparkyfitness-db:
image: ghcr.io/daemonless/postgres:18
container_name: sparkyfitness-db
restart: unless-stopped
network_mode: host
annotations:
org.freebsd.jail.allow.sysvipc: "true"
# Generic daemonless PostgreSQL 18 image. Only the superuser role + database
# are provisioned here; the SparkyFitness backend creates its own limited
# app role (SPARKY_FITNESS_APP_DB_USER) during migrations.
environment:
- POSTGRES_DB=${SPARKY_FITNESS_DB_NAME}
- POSTGRES_USER=${SPARKY_FITNESS_DB_USER}
- POSTGRES_PASSWORD=${SPARKY_FITNESS_DB_PASSWORD}
# Distinct port (NOT 5432) so this can run alongside another host-networked Postgres
# (e.g. Immich on 5432) without colliding. ⚠ Requires the daemonless/postgres image to
# honor POSTGRES_PORT — if it doesn't, it falls back to 5432 and WILL collide. Two
# host-net Postgres must never share a port.
- POSTGRES_PORT=5433
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
```
Then run `podman-compose up -d`.
### AppJail Director
**.env**:
```
# .env
DIRECTOR_PROJECT=sparkyfitness
PUID=1000
PGID=1000
TZ=UTC
NODE_ENV=production
SPARKY_FITNESS_DB_HOST=127.0.0.1
SPARKY_FITNESS_DB_PORT=5433
SPARKY_FITNESS_DB_NAME=sparkyfitness
SPARKY_FITNESS_DB_USER=sparky
SPARKY_FITNESS_DB_PASSWORD=sparky
SPARKY_FITNESS_APP_DB_USER=sparky_app
SPARKY_FITNESS_APP_DB_PASSWORD=sparky_app
SPARKY_FITNESS_API_ENCRYPTION_KEY=<SPARKY_FITNESS_API_ENCRYPTION_KEY>
BETTER_AUTH_SECRET=<BETTER_AUTH_SECRET>
SPARKY_FITNESS_FRONTEND_URL=
SPARKY_FITNESS_SERVER_HOST=127.0.0.1
SPARKY_FITNESS_SERVER_PORT=3010
SPARKY_FITNESS_LOG_LEVEL=ERROR
UPLOADS_LOCATION=/containers/sparkyfitness/uploads
BACKUPS_LOCATION=/containers/sparkyfitness/backups
DB_DATA_LOCATION=/containers/sparkyfitness/postgres
```
**appjail-director.yml**:
```yaml
# appjail-director.yml
options:
- alias:
- ip4_inherit:
services:
sparkyfitness:
name: sparkyfitness
options:
- container: 'args:--pull'
oci:
user: root
environment:
- PUID: !ENV '${PUID}'
- PGID: !ENV '${PGID}'
- TZ: !ENV '${TZ}'
- NODE_ENV: !ENV '${NODE_ENV}'
- SPARKY_FITNESS_DB_HOST: !ENV '${SPARKY_FITNESS_DB_HOST}'
- SPARKY_FITNESS_DB_PORT: !ENV '${SPARKY_FITNESS_DB_PORT}'
- SPARKY_FITNESS_DB_NAME: !ENV '${SPARKY_FITNESS_DB_NAME}'
- SPARKY_FITNESS_DB_USER: !ENV '${SPARKY_FITNESS_DB_USER}'
- SPARKY_FITNESS_DB_PASSWORD: !ENV '${SPARKY_FITNESS_DB_PASSWORD}'
- SPARKY_FITNESS_APP_DB_USER: !ENV '${SPARKY_FITNESS_APP_DB_USER}'
- SPARKY_FITNESS_APP_DB_PASSWORD: !ENV '${SPARKY_FITNESS_APP_DB_PASSWORD}'
- SPARKY_FITNESS_API_ENCRYPTION_KEY: !ENV '${SPARKY_FITNESS_API_ENCRYPTION_KEY}'
- BETTER_AUTH_SECRET: !ENV '${BETTER_AUTH_SECRET}'
- SPARKY_FITNESS_FRONTEND_URL: !ENV '${SPARKY_FITNESS_FRONTEND_URL}'
- SPARKY_FITNESS_SERVER_HOST: !ENV '${SPARKY_FITNESS_SERVER_HOST}'
- SPARKY_FITNESS_SERVER_PORT: !ENV '${SPARKY_FITNESS_SERVER_PORT}'
- SPARKY_FITNESS_LOG_LEVEL: !ENV '${SPARKY_FITNESS_LOG_LEVEL}'
- UPLOADS_LOCATION: !ENV '${UPLOADS_LOCATION}'
- BACKUPS_LOCATION: !ENV '${BACKUPS_LOCATION}'
- DB_DATA_LOCATION: !ENV '${DB_DATA_LOCATION}'
volumes:
- sparkyfitness_uploads: /app/server/uploads
- sparkyfitness_backup: /app/server/backup
sparkyfitness-db:
name: sparkyfitness_db
options:
- from: ghcr.io/daemonless/postgres:18
- template: !ENV '${PWD}/postgres-template.conf'
oci:
environment:
- POSTGRES_DB: !ENV '${SPARKY_FITNESS_DB_NAME}'
- POSTGRES_USER: !ENV '${SPARKY_FITNESS_DB_USER}'
- POSTGRES_PASSWORD: !ENV '${SPARKY_FITNESS_DB_PASSWORD}'
- POSTGRES_PORT: "5433"
volumes:
- db_data: /var/lib/postgresql/data
volumes:
sparkyfitness_uploads:
device: '/containers/sparkyfitness/uploads'
sparkyfitness_backup:
device: '/containers/sparkyfitness/backup'
db_data:
device: !ENV '${DB_DATA_LOCATION}'
```
**Makejail**:
```
# Makejail
ARG tag=latest
OPTION container=boot
OPTION overwrite=force
OPTION from=ghcr.io/daemonless/sparkyfitness:${tag}
```
Save the files above, then run `appjail-director up`.
## Parameters
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `PUID` | `1000` | User ID for the application process |
| `PGID` | `1000` | Group ID for the application process |
| `TZ` | `UTC` | Timezone for the container |
| `NODE_ENV` | `production` | Node runtime mode; leave as 'production' |
| `SPARKY_FITNESS_DB_HOST` | `127.0.0.1` | Where the backend finds PostgreSQL (fjord sets this; 127.0.0.1 on host networking) |
| `SPARKY_FITNESS_DB_PORT` | `5433` | PostgreSQL port; MUST match the sidecar's POSTGRES_PORT. Default 5433 (NOT 5432) so this can coexist with another host-networked Postgres (e.g. Immich on 5432) on the same host. ⚠ With network_mode: host, two Postgres on the same port silently collide — keep each service on a distinct port. NOTE: this only takes effect if the daemonless/postgres image honors POSTGRES_PORT (see project README / upstream fix); otherwise the sidecar falls back to 5432. |
| `SPARKY_FITNESS_DB_NAME` | `sparkyfitness` | PostgreSQL database name |
| `SPARKY_FITNESS_DB_USER` | `sparky` | PostgreSQL superuser |
| `SPARKY_FITNESS_DB_PASSWORD` | `sparky` | PostgreSQL password |
| `SPARKY_FITNESS_APP_DB_USER` | `sparky_app` | Limited app DB role the backend creates during migrations |
| `SPARKY_FITNESS_APP_DB_PASSWORD` | `sparky_app` | Password for the limited app DB role |
| `SPARKY_FITNESS_API_ENCRYPTION_KEY` | `<SPARKY_FITNESS_API_ENCRYPTION_KEY>` | 64-char hex encryption key |
| `BETTER_AUTH_SECRET` | `<BETTER_AUTH_SECRET>` | Auth session signing secret |
| `SPARKY_FITNESS_FRONTEND_URL` | `` | URL you will open this app at, e.g. http://myhost:3004 (sign-up fails if it does not match) |
| `SPARKY_FITNESS_SERVER_HOST` | `127.0.0.1` | Internal bind address for the node backend; leave as 127.0.0.1 (nginx proxies to it) |
| `SPARKY_FITNESS_SERVER_PORT` | `3010` | Internal node backend port; leave as default |
| `SPARKY_FITNESS_LOG_LEVEL` | `ERROR` | Backend log verbosity (e.g. ERROR, INFO, DEBUG) |
| `UPLOADS_LOCATION` | `/containers/sparkyfitness/uploads` | Path to store user uploads (profile pictures, exercise images) |
| `BACKUPS_LOCATION` | `/containers/sparkyfitness/backups` | Path to store server backups |
| `DB_DATA_LOCATION` | `/containers/sparkyfitness/postgres` | Path to store PostgreSQL data files |
### Volumes
| Path | Description |
|------|-------------|
| `/app/server/uploads` | User-uploaded files (profile pictures, exercise images) |
| `/app/server/backup` | Server backup data |
**Architectures:** amd64
**User:** `bsd` (UID/GID via PUID/PGID, defaults to 1000:1000)
**Base:** FreeBSD 15
---
Need help? Join our [Discord](https://discord.gg/Kb9tkhecZT) community.