Skip to content

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.

Terminal window
mkdir homefirst && cd homefirst
curl -fsSLO https://git.bcnelson.dev/home-first/homefirst/raw/branch/main/platform/compose/compose.yaml
curl -fsSL https://git.bcnelson.dev/home-first/homefirst/raw/branch/main/platform/compose/env.example -o .env
chmod 600 .env
$EDITOR .env # replace every CHANGE-ME; the file explains each one
docker compose up -d
curl -fsS localhost:8080/healthz && curl -fsS localhost:8081/healthz

What you need to set in .env:

VariableWhy
POSTGRES_PASSWORD, TENDANT_DB_PASSWORD, OPENPRM_DB_PASSWORDDatabase roles, created on first start.
TENDANT_PASSWORDDevice-pairing password. Without it no device can pair.
TENDANT_CREDENTIALS_KEY, OPENPRM_CREDENTIALS_KEYEncrypt stored tokens. Back these up separately.
OPENPRM_OWNER_PASSWORD_HASHYour 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.

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.

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:

Terminal window
docker compose exec backup /backup.sh

Restore one app’s database. The dumps are only readable inside the backup container, so run the restore there:

Terminal window
APP=tendant # or openprm
docker compose exec backup ls /backups # pick a dump
DUMP=/backups/tendant-20261004T031500Z.dump
docker compose stop $APP
docker compose exec backup dropdb $APP
docker compose exec backup createdb -O $APP $APP
docker compose exec backup pg_restore --dbname=$APP --single-transaction --exit-on-error $DUMP
docker compose start $APP

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.