Skip to content

Getting started

Install & self-host

Production install of the single Olivares AI binary — no default credentials, TLS on by default, /readyz and /livez probes, SQLite or least-privilege Postgres

Olivares AI ships as one static binary with the web console embedded. The control plane — the part that observes, governs and audits the AI agents on your infrastructure — runs in your perimeter and can be air-gapped. This page covers the production-shaped install: one host, secure defaults, health probes, and the store choice that matters for multi-tenant deployments.

If you only want to look around first, the quickstart boots a synthetic demo estate in about five minutes. This page is the real posture.

Get the binary

There is no public download URL to copy here. You get the controlplane binary one of two ways:

  • A signed release artifact — verify it before you run it. See verify a release for the signature and provenance chain.
  • Build from source — the store is pure-Go SQLite, so there is no C toolchain. A task build produces ./bin/controlplane with the web UI and first-party connectors embedded; controlplane version confirms what you built.

Either way you end up with a single file. Install it and create a dedicated service user rather than running it as root.

Secure defaults

The defaults are chosen so a fresh install is safe before you touch any flags.

DefaultBehaviour
CredentialsNone. First boot prints a one-time, single-use setup token (prefix olst_); you create the first administrator with it.
TLSOn. With no --tls-cert/--tls-key, the engine generates a self-signed certificate in the data directory and logs its fingerprint_sha256. --insecure (plaintext) is for localhost development only.
BindLoopback. --listen defaults to 127.0.0.1:8443 and gRPC to 127.0.0.1:8444; expose them deliberately, behind your own ingress and TLS.

A minimal first boot:

controlplane serve \
  --listen 127.0.0.1:8443 \
  --grpc-listen 127.0.0.1:8444 \
  --data-dir /var/lib/olivares

The data directory holds the store, the audit signing key and the TLS material. Back it up and protect it with restrictive permissions.

Claim the one-time setup token

A fresh install has no default credentials. On first boot, while no users exist, the engine mints a single-use setup token and prints it to stdout only — never the logs:

=== FIRST-BOOT SETUP ===
No users exist yet. Create the first administrator:
  POST /v1/setup  {"token":"olst_…","email":"you@example.com","password":"..."}
This token is shown ONCE and is single-use.
========================

Only the hash of the token is stored, so a missed token cannot be recovered and a restart does not re-print it. On a brand-new install with no users yet, removing the stored token from the data directory and restarting mints a fresh one. That recovery works only while no users exist, so it can never take over a configured install.

After you create the first administrator, the setup endpoint is closed for good.

Health probes

The HTTP listener exposes two probes with deliberately different semantics. Wire them to the matching Kubernetes probe — confusing the two causes restart loops or stale routing.

/livez is liveness. It runs no dependency check: if the process can answer, it is alive. A failing dependency must never trigger a liveness restart.

curl -ks https://127.0.0.1:8443/livez
# {"status":"ok"}

/readyz is readiness, and it is the availability signal a load balancer should drain on. It returns 503 in two cases, distinguished in the body for your logs:

  • Store unreachable{"status":"unavailable","store":"down"}. The store ping runs with a short timeout, so a wedged backend drains the instance instead of hanging.
  • Not the active writer{"status":"standby","store":"up","leader":false}. In an active-passive cluster a standby reports 503 here so the Service stops routing to it, without restarting it (that is /livez’s job — a hot standby must stay up to take over). When the leader dies, a standby acquires leadership and this flips to 200, so traffic follows the new leader automatically.

When the engine is ready it returns 200:

{"status":"ok","store":"up","leader":true,"setup_required":false}

setup_required is reported for observability but does not fail readiness — a freshly booted engine is ready to be set up. On a single-node store the writer is always active, so /readyz simply tracks store reachability.

Choosing a store

The store is selected with --engine. Pick by topology, not by preference.

SQLite (default)

The embedded pure-Go SQLite store needs nothing external and is the right choice for a single node, a lab, a small estate, or an air-gapped install. The whole state lives in the data directory.

Postgres (multi-tenant)

For multi-host or multi-tenant deployments, use Postgres. Do not connect as a superuser or as a role with BYPASSRLS. Tenant isolation is enforced by FORCE ROW LEVEL SECURITY, and Postgres silently bypasses all row-level security for such roles — which would leave only the application-layer predicate between tenants. The engine refuses to start against a privileged role unless you explicitly pass --allow-privileged-db-role (single-tenant or dev only).

Provision a dedicated least-privilege role instead — NOSUPERUSER NOBYPASSRLS NOCREATEROLE NOCREATEDB. It owns its own database so it can apply schema migrations; FORCE ROW LEVEL SECURITY applies the tenant policy even to the table owner, so an owning-but-not-bypassing role stays fully isolated.

controlplane serve --engine postgres \
  --dsn "postgres://olivares_app:$DB_PASSWORD@db:5432/olivares?sslmode=verify-full" \
  --data-dir /var/lib/olivares

Use sslmode=verify-full and a strong SCRAM password. Genuinely cross-tenant System reads (the org list, multi-tenant checkpoint coverage) need a separate role: provision one that is NOSUPERUSER BYPASSRLS — least-privilege but able to read across tenants — and point --admin-dsn at it. Omit it for single-tenant deployments and those reads are simply RLS-limited.

Before you call it done

Two things decide whether your evidence survives an incident:

  • Back up the audit signing key off-box. It signs the append-only audit ledger; if it is lost, the ledger can no longer be re-verified. The engine warns on first boot — there is no enforced escrow.
  • Keep an off-box copy of the ledger public key. That off-host copy is what makes audit verification resistant after a host compromise.

Then schedule real backups of the data directory.

What runs where

Only the control plane is yours to place — air-gapped if you choose. The collectors (data plane) always run on your infrastructure. One caveat worth stating plainly: Olivares governs and audits Claude usage, but Claude inference itself is not self-hosted — it reaches Anthropic’s API (directly or via Bedrock, Vertex or Foundry). Only genuinely self-hosted models run offline. See the honesty & limits page for the full boundary.

Next steps