Ctrl K
ComunidadGuías…

compose.yaml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
name: sparkyfitness

x-daemonless:
  class: "service"
  title: "SparkyFitness"
  icon: ":material-heart-pulse:"
  category: "Productivity"
  description: "Self-hosted privacy-first fitness tracker on FreeBSD."
  upstream_url: "https://github.com/CodeWithCJ/SparkyFitness"
  web_url: "https://github.com/CodeWithCJ/SparkyFitness"
  user: "bsd"
  mlock: false
  # sparkyfitness is the one people open; its database stays on the stack's
  # private network, where it is found by the name fjord puts in
  # SPARKY_FITNESS_DB_HOST (127.0.0.1 on host networking).
  networking:
    sparkyfitness: default
    "*": private
  hostnames:
    sparkyfitness-db: SPARKY_FITNESS_DB_HOST
  # Sidecar for the AppJail director bundle, named as the service is so fjord
  # finds its jail by the service's name.
  appjail:
    director:
      options:
        - alias:
        - ip4_inherit:
    depends_on:
      - name: sparkyfitness-db
        image: ghcr.io/daemonless/postgres:18
        template: postgres-template.conf
        env:
          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

  docs:
    env:
      PUID: "User ID for the application process"
      PGID: "Group ID for the application process"
      TZ: "Timezone for the container"
      UPLOADS_LOCATION: "Path to store user uploads (profile pictures, exercise images)"
      BACKUPS_LOCATION: "Path to store server backups"
      DB_DATA_LOCATION: "Path to store PostgreSQL data files"
      SPARKY_FITNESS_DB_NAME: "PostgreSQL database name"
      SPARKY_FITNESS_DB_USER: "PostgreSQL superuser"
      SPARKY_FITNESS_DB_PASSWORD: "PostgreSQL password"
      SPARKY_FITNESS_API_ENCRYPTION_KEY: "64-char hex encryption key"
      BETTER_AUTH_SECRET: "Auth session signing secret"
      SPARKY_FITNESS_FRONTEND_URL:
        desc: "URL you will open this app at, e.g. http://myhost:3004 (sign-up fails if it does not match)"
        public_url: true  # fjord fills in where the app lands
      NODE_ENV: "Node runtime mode; leave as 'production'"
      SPARKY_FITNESS_DB_HOST:
        desc: "Where the backend finds PostgreSQL (fjord sets this; 127.0.0.1 on host networking)"
        level: advanced
        optional: true
      SPARKY_FITNESS_DB_PORT: "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_APP_DB_USER: "Limited app DB role the backend creates during migrations"
      SPARKY_FITNESS_APP_DB_PASSWORD: "Password for the limited app DB role"
      SPARKY_FITNESS_SERVER_HOST: "Internal bind address for the node backend; leave as 127.0.0.1 (nginx proxies to it)"
      SPARKY_FITNESS_SERVER_PORT: "Internal node backend port; leave as default"
      SPARKY_FITNESS_LOG_LEVEL: "Backend log verbosity (e.g. ERROR, INFO, DEBUG)"
    volumes:
      /app/server/uploads: "User-uploaded files (profile pictures, exercise images)"
      /app/server/backup: "Server backup data"
    ports:
      3004: "Web UI (nginx reverse proxy)"

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