Get started with Docker Compose
The repository ships a Compose stack under deploy/compose/: a hardened
single-node deployment (embedded SQLite, zero external dependencies) plus two
overlays — a Postgres multi-tenant override and a disaster-recovery
backup profile. This tutorial takes you from up -d to a configured control
plane with backups.
The container wraps the same single binary as every other install; only
the packaging differs. The commands below are the stack’s own documented entry
points (deploy/compose/*.yml), and the first-run flow they drive is the same
one verified end-to-end against the binary in the
single-node tutorial.
1. Bring up the single-node stack (SQLite)
Section titled “1. Bring up the single-node stack (SQLite)”-
Start it:
On hosts that mediate user namespace creation with AppArmor, complete “Session confinement on AppArmor hosts” in
deploy/compose/README.mdon the Docker daemon host before starting the stack.Terminal window docker compose -f deploy/compose/docker-compose.yml up --wait --wait-timeout 120What you get, by design:
Property Value Ports 8443(HTTPS: REST + web UI),8444(gRPC) — published on every host interface, because this is a server. SetOLIVARES_BIND=127.0.0.1in.envto restrict them to the hostData named volume olivares-data→/var/lib/olivares(SQLite store, audit signing key, TLS material)Project folder at /project, read-write: the host folder whose absolute path is inOLIVARES_PROJECT_DIR, or an empty volume when it is unset. Sessions started in/projectcan change everything in it; see “Work on a host project folder” indeploy/compose/README.mdHardening runs as 65532:65532, read-only root, all capabilities dropped,no-new-privileges, tmpfs/tmpHealthcheck direct exec of the built-in olivares readyzcommand—no shell, curl, or wget. Only local/readyzHTTP 200 is healthy -
Ask the engine where it is, and read the one-time setup token from the logs:
Terminal window # where the console answers, and whether setup is still pending. It runs the binary# directly and needs no shell.docker compose -f deploy/compose/docker-compose.yml exec olivares olivares first-boot# the one-time setup token, printed once at first bootdocker compose -f deploy/compose/docker-compose.yml logs olivares \| sed -n '/FIRST-BOOT SETUP/,/========================/p' -
Create the first administrator, log in, and create your organization — exactly as in the single-node tutorial (the API is the same; the TLS certificate is self-signed on first boot, so
curl -kfor the bootstrap):Terminal window curl -ksf -X POST https://localhost:8443/v1/setup \-H 'Content-Type: application/json' \-d '{"token":"<olst_ token>","email":"you@example.com","password":"<strong-password>"}'
2. Wire sources
Section titled “2. Wire sources”Sources are declared in one operator file named by OLIVARES_SOURCES_CONFIG
(connect a source). For the container, mount the
file and set the variable with a small override:
# deploy/compose/docker-compose.sources.yml (yours — not shipped)services: olivares: environment: OLIVARES_SOURCES_CONFIG: /etc/olivares/sources.json volumes: - ./sources.json:/etc/olivares/sources.json:rodocker compose -f deploy/compose/docker-compose.yml \ -f deploy/compose/docker-compose.sources.yml up -ddocker compose -f deploy/compose/docker-compose.yml logs olivares | grep "ingest: wired source"Remember the paths inside sources.json are container paths — a pgAudit
log tail, for example, needs the Postgres log directory mounted read-only into
the container as well.
3. Encrypted DR backups (the backup profile)
Section titled “3. Encrypted DR backups (the backup profile)”The stack ships a one-shot backup service that produces an encrypted,
ledger-continuity-safe bundle (olivares dr backup):
Keep the passphrase in a private file outside the checkout and the image, and keep
a copy somewhere safe off this host: without it, no bundle can be restored. Give
the backup container read-only access to it (the image runs as UID 65532):
sudo install -d -o 65532 -g 65532 -m 0700 /srv/olivares-drsudo install -o 65532 -g 65532 -m 0400 /path/to/private-passphrase /srv/olivares-dr/dr-pass
BACKUP_TS="$(date -u +%Y%m%dT%H%M%SZ)" \docker compose -f deploy/compose/docker-compose.yml \ -f deploy/compose/docker-compose.backup.yml \ -f - --profile backup run --rm backup <<'YAML'services: backup: volumes: - /srv/olivares-dr/dr-pass:/run/secrets/dr-pass:roYAMLWrap that command in host cron for a scheduled RPO, and mirror the
olivares-backups volume offsite — a same-host backup is not disaster
recovery, and the passphrase must travel separately from the bundles (3-2-1).
The full procedure, including the restore drill (olivares dr verify), is
in backup & restore.
4. Optional: the Postgres multi-tenant override
Section titled “4. Optional: the Postgres multi-tenant override”For the multi-tenant topology, layer the Postgres override. It brings up a
Postgres 16, provisions the least-privilege olivares_app role (no
superuser, no BYPASSRLS — the engine refuses to start against a privileged
role, because row-level security is the tenant backstop), and points the
engine at it:
The override also provisions olivares_admin, a separate NOSUPERUSER BYPASSRLS
role with read-only access to the engine tables. The engine uses it through
--admin-dsn for cross-tenant reads, including first setup.
Set three distinct passwords first, using only A-Z a-z 0-9 . _ ~ - for this
Compose demo, then bring the stack up:
cp deploy/compose/.env.example deploy/compose/.env# set three distinct passwords in deploy/compose/.env:# POSTGRES_SUPERUSER_PASSWORD, OLIVARES_DB_PASSWORD, OLIVARES_ADMIN_PASSWORD
docker compose -f deploy/compose/docker-compose.yml \ -f deploy/compose/docker-compose.postgres.yml up -dHealth
Section titled “Health”curl -ks https://localhost:8443/readyz# {"leader":true,"setup_required":false,"status":"ok","store":"up"}curl -ks https://localhost:8443/metrics | grep olivares_store_upNext steps
Section titled “Next steps”- Wire real signals: the connector guides.
- Schedule and drill backups: backup & restore.
- Monitor it: Prometheus metrics, SLOs and alerts.
- Going multi-node? Kubernetes with Helm, including HA and the collectors DaemonSet.