Files
EvolioHealth/docs/deployment.md
T

4.4 KiB

Deployment and operations

Compose contract

Ship one compose.yaml. Operators launch it with their normal manager; no Compose profiles or mandatory override files. APP_ENV=dev|prod selects application behavior.

Conceptual topology:

services:
  app:
    image: ghcr.io/example/evoliohealth-server:VERSION
    user: "${PUID:-1000}:${PGID:-1000}"
    environment:
      APP_ENV: "${APP_ENV:-prod}"
      APP_URL: "${APP_URL}"
      TZ: "${TZ:-UTC}"
    ports:
      - "8080:8080"
    volumes:
      - evoliohealth_config:/config
      - evoliohealth_data:/data
    networks: [frontend, backend]
    security_opt: ["no-new-privileges:true"]
    cap_drop: [ALL]

  pocketbase:
    image: ghcr.io/example/evoliohealth-pocketbase:VERSION
    user: "${PUID:-1000}:${PGID:-1000}"
    expose: ["8090"]
    volumes:
      - evoliohealth_data:/data
    networks: [backend]
    security_opt: ["no-new-privileges:true"]
    cap_drop: [ALL]

networks:
  frontend:
  backend:
    internal: true

volumes:
  evoliohealth_config:
  evoliohealth_data:

The final implementation may split PocketBase into a dedicated volume/subpath to avoid both containers having unnecessarily broad write access. Prefer least privilege. PocketBase MUST NOT have ports, join frontend, or be targeted by the reverse proxy.

Named volumes and bind mounts

The distributed Compose uses named volumes by default. Documentation shows users how to replace only the Compose volume entries with fixed host paths, for example:

volumes:
  - /volume1/docker/evoliohealth/config:/config
  - /volume1/docker/evoliohealth/data:/data

Do not use environment variables for volume sources. Internal paths remain /config and /data. Bind-mount owners/permissions must match PUID/PGID.

Reverse proxy

Proxy only app:8080 or the host-published application port. Enable WebSocket/streaming support if future endpoints require it. Preserve host and scheme headers. Use a dedicated hostname rather than a subpath. Provide concise examples for Caddy, Traefik, Nginx/Nginx Proxy Manager, and Synology without making any one mandatory.

PocketBase is inaccessible from the host and Internet. Diagnostic access, if ever needed, must be a documented temporary local tunnel or operator-only command, never a normal Compose option.

Initial installation

  1. Configure volumes/bind mounts, PUID/PGID, APP_URL, APP_ENV, and TZ.
  2. Start the stack through the chosen container manager.
  3. Visit /setup immediately.
  4. Create the first administrator, configure defaults and SMTP/photo policy.
  5. Download and separately secure /config/master.key.
  6. Create and verify an encrypted backup.

The simple open initial setup is an accepted product decision. Documentation MUST warn operators not to expose an unconfigured instance longer than necessary. The server must close setup atomically after the first administrator is committed and reject concurrent attempts.

Health checks

  • Liveness states only that the process event loop is responsive.
  • Readiness verifies configuration/key availability, PocketBase reachability/migrations, reference DB validity, and required storage writability.
  • Responses reveal no versions, paths, user counts, or secrets to unauthenticated clients.

Backup and restore operations

The Web administration UI creates password-encrypted global backups with progress. A restore runs preflight validation, creates a rollback point when feasible, enters maintenance mode, imports transactionally/staged, verifies, and resumes traffic. Never accept a raw database replacement uploaded through the browser.

Operators should copy backups off-host and test restoration. The master-key copy is stored separately. Backup passwords are never stored by EvolioHealth.

Upgrade

Use immutable semantic-version tags. Before schema-changing upgrades, require/encourage a verified backup. Apply migrations once under a distributed/single-instance lock, retain compatible rollback artifacts where possible, and refuse downgrade when schemas are incompatible.

Reference updates are independent of application image upgrades and signed. Provide manual update/check controls; automatic scheduling may be configurable later.

Resource posture

No hard user cap. Publish measured minimum/recommended CPU, RAM, and disk only after benchmarks. Bound SQLite caches, Go memory, photo processing concurrency, sync batch size, and backup jobs. The design must remain useful on modest NAS hardware and avoid idle background work.