Deploy with Docker Compose
If your machine isn’t on NixOS, run the published images with Docker Compose.
The repository has a ready-made stack in
platform/compose/:
one Postgres (with pgvector) for both apps, tendant, openPRM, and a backup
container.
Set it up
Section titled “Set it up”mkdir homefirst && cd homefirstcurl -fsSLO https://git.bcnelson.dev/home-first/homefirst/raw/branch/main/platform/compose/compose.yamlcurl -fsSL https://git.bcnelson.dev/home-first/homefirst/raw/branch/main/platform/compose/env.example -o .envchmod 600 .env$EDITOR .env # replace every CHANGE-ME; the file explains each onedocker compose up -dcurl -fsS localhost:8080/healthz && curl -fsS localhost:8081/healthzWhat you need to set in .env:
| Variable | Why |
|---|---|
POSTGRES_PASSWORD, TENDANT_DB_PASSWORD, OPENPRM_DB_PASSWORD | Database roles, created on first start. |
TENDANT_PASSWORD | Device-pairing password. Without it no device can pair. |
TENDANT_CREDENTIALS_KEY, OPENPRM_CREDENTIALS_KEY | Encrypt stored tokens. Back these up separately. |
OPENPRM_OWNER_PASSWORD_HASH | Your openPRM login (a bcrypt hash; the file shows how to make one). |
Images come from git.bcnelson.dev/home-first/{tendant,openprm}. Set
HOMEFIRST_TAG to an exact version to control when you upgrade.
For tendant’s model connections and sources, write a tendant.toml (see
the configuration reference)
and uncomment its volume in compose.yaml.
Exposure
Section titled “Exposure”The ports bind to 127.0.0.1. Publish them on your tailnet with
tailscale serve (see Deploy on NixOS)
or set BIND_ADDR to the host’s tailnet IP. Don’t publish them to the internet
as they are.
Backups
Section titled “Backups”The backup container dumps both databases once a day into ./backups
(BACKUP_KEEP newest are kept). Take one now — for example before an
upgrade — with:
docker compose exec backup /backup.shRestore one app’s database. The dumps are only readable inside the backup container, so run the restore there:
APP=tendant # or openprmdocker compose exec backup ls /backups # pick a dumpDUMP=/backups/tendant-20261004T031500Z.dumpdocker compose stop $APPdocker compose exec backup dropdb $APPdocker compose exec backup createdb -O $APP $APPdocker compose exec backup pg_restore --dbname=$APP --single-transaction --exit-on-error $DUMPdocker compose start $APPUpgrades
Section titled “Upgrades”Take a backup, change HOMEFIRST_TAG, then
docker compose pull && docker compose up -d. Migrations run when the
containers start. To roll back, restore the dump and set the old tag again:
migrations only go forward, so an older version can’t open a database a newer
one has migrated.