Documentation
Server operations
Back up Postgres, apply updates, manage credentials, and troubleshoot sync failures.
Read as MarkdownBack up the database and configuration
For the Docker stack, create a Postgres custom-format backup from the repository root. Choose a new filename for each backup so you do not overwrite the previous one.
docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' > healthsync-backup.dump
docker compose exec -T db pg_restore --list < healthsync-backup.dumpThe archive listing confirms that the dump is readable, but it does not prove recovery works. Test a restore into a separate, empty database in an isolated environment using pg_restore with --exit-on-error, then verify expected tables and record counts. Never test a restore over your live database.
Keep encrypted backups off the server and retain a secure copy of .env, especially TOKEN_HASH_SECRET, along with the deployed Git revision. Database dumps contain private health data. For managed Postgres, also configure and test the provider's backup and restore process. A Docker volume alone is not a backup.
Apply updates
Back up the database and configuration first, record the current Git revision, and review the incoming changes. From your deployment checkout, run:
git rev-parse HEAD
git pull --ff-only
docker compose up --build -d
docker compose ps
curl --fail http://127.0.0.1:8080/healthKeep your existing secrets. The rebuilt API container applies migrations on startup. Verify an authenticated read and a real iPhone upload after updating. For manual deployments, update dependencies, run alembic upgrade head, and restart your API service. Code rollback alone may not undo schema changes; plan database recovery before rolling back a migration.
Manage credentials
- Self-hosted API_TOKEN: generate a replacement, update .env, run docker compose up -d api to recreate the service with the new environment, and update the iPhone and any trusted readers. Old credentials stop working when the new configuration takes effect.
- Hosted agent token: use Refresh read-only agent token in the app's Agent Access Details, then update your agent's credential store. Previous agent tokens for that workspace are revoked.
- TOKEN_HASH_SECRET: preserve it. Changing it makes existing hosted ingest and agent tokens unusable; it is not the routine way to rotate one token.
- Reset Hosted Storage deletes the current hosted workspace data when the saved token is valid, then creates a new workspace and credentials. Use agent-token refresh when only the agent credential needs replacement.
Troubleshoot connection and sync issues
- API will not start: check that the three required secrets are set, run docker compose config --quiet, and inspect docker compose logs --tail=100 api db for startup or migration errors. Config output without --quiet can include secrets.
- 401 response: supply Authorization: Bearer <token>. 403 response: check the token value and kind; an ingest token cannot read /api/agent/*, and a read-only agent token cannot upload.
- Phone cannot connect: verify DNS, HTTPS, firewall, and reachability from the phone. For local tests, use the server's LAN address and allow Local Network access.
- Successful sync but empty reads: confirm the app and reader use the same backend and workspace. Self-hosted API_TOKEN reads do not include hosted workspace data. Confirm you are running backend/, not the non-persistent backend_stub/.
- No new data: check Apple Health permissions, category selection, and date range. Try manual sync or backfill. Background sync timing is controlled by iOS.
- Uploads retry: inspect Sync Logs and server availability. Failed batches stay queued on the iPhone for later retries. Replayed record IDs are deduplicated; repeated uploads do not imply duplicate stored records.