Skip to content
Accquix Register
Esc
↑↓navigate↵open⌘Jpreview
On this page

Coolify, Dokploy and similar

Deploy on a platform that runs Docker Compose from a Git repository, with every secret in the platform's environment settings.

Platforms such as Coolify, Dokploy or Portainer stacks run a Docker Compose file from a Git repository and keep the secrets in their own settings screen. They cannot run make-secrets.sh, so the reference docker compose setup, which reads secret files, does not fit them. deploy/paas/compose.yaml is the same stack configured only through environment variables.

It is a good fit when you already run a server for something else: the register adds about 2.5 GB of disk, a busy first sync of about 15 minutes, and very little afterwards.

Service Runs Lifecycle
postgres PostgreSQL 18 Always on, with a health check
roles Creates or updates the four database roles Once per deployment, as the superuser
migrate accquix-register migrate Once per deployment
setup One operator command from REGISTER_SETUP_COMMAND Once per deployment; version by default
sync accquix-register sync --every 1h Always on
serve accquix-register serve on port 8080 Always on, behind the platform’s proxy

Steps

Add the resource

Create a Docker Compose resource from the repository (or your fork), with the compose file deploy/paas/compose.yaml. The image is built from the source; set REGISTER_IMAGE to a released image once there is one.

Set the variables

Copy the names from deploy/paas/.env.example into the platform’s environment settings:

openssl rand -hex 32      # one value for each of the five passwords
key=$(openssl rand -hex 24); echo "API key: $key"
printf 'default:%s\n' "$(printf %s "$key" | shasum -a 256 | cut -d' ' -f1)"   # REGISTER_API_KEYS
Variable Value
POSTGRES_PASSWORD The superuser; only the roles service uses it
REGISTER_MIGRATE_PASSWORD, REGISTER_SYNC_PASSWORD, REGISTER_OPERATOR_PASSWORD, REGISTER_API_PASSWORD One per role
REGISTER_API_KEYS name:sha256hex, the hash of each API key; store the key itself elsewhere
REGISTER_SETUP_COMMAND suppress --init-empty, for the first deployment only

Use hex values: the passwords go into connection URLs as they are.

Route the domain

Point a domain at the serve service, port 8080, with TLS from the platform. Nothing is published on the host’s ports.

Deploy, then remove the setup command

The first deployment confirms that this is a new installation with no objections to restore; until then the API answers 503 reason=setup. Then delete REGISTER_SETUP_COMMAND. Left in place, it would fail harmlessly on the next deployment, but after a rebuilt database it would confirm “no objections” without anyone checking.

Wait for the first sync

GET /readyz answers ready when every source is published, after about 15 minutes.

Operator commands

REGISTER_SETUP_COMMAND runs any accquix-register command once with the operator role, but its output lands in the platform’s logs, where an objection’s identifier does not belong. Use it for suppress --init-empty only. Run objections and their backups from the server’s shell, on the project’s Docker network (the platform shows its name), with the operator password:

mkdir -p backup && chmod 777 backup     # the image runs as uid 65532
docker run --rm --network <project network> -v "$PWD/backup:/backup" \
  -e REGISTER_OPERATOR_DATABASE_URL="postgres://register_operator:<password>@postgres:5432/register?sslmode=disable" \
  <image> suppress --export --output /backup/objections.tsv --overwrite

The same form runs suppress --subject …, --undo or --restore /backup/objections.tsv. See Operations for what each does. The image has no shell, so docker exec … sh does not work.

Sharing an existing PostgreSQL

To use a PostgreSQL that already runs on the server instead of the postgres service, create a separate database and the roles from Database, and point the four URLs at it with the variables of Configuration. Keep the sync on a direct connection, never through PgBouncer.