Skip to content

Get started on a single node (binary + systemd)

This is the production-shaped first install: one Linux host, one static binary, systemd, the embedded SQLite store — and the real first-run path (a one-time setup token, TLS on by default, no default credentials, no demo data). By the end you will have Olivares AI running as a hardened service with a real source wired and a populated access graph.

It is the same engine the quickstart demos in five minutes; the difference is posture. If you want the instant look-around first, do the quickstart, then come back here for the real install.

  • A Linux host with systemd and curl.
  • Go 1.26+. Build this tutorial from source; Olivares 0.4 is the next release, not yet published.
  1. Build the one static artifact (engine + embedded web UI + first-party connectors):

    Terminal window
    task build # produces ./bin/olivares
    ./bin/olivares version
  2. Install it and create the service user:

    Terminal window
    sudo install -m 0755 bin/olivares /usr/local/bin/olivares
    sudo useradd --system --home /var/lib/olivares --shell /usr/sbin/nologin olivares

Create /etc/systemd/system/olivares.service:

[Unit]
Description=Olivares AI — self-hosted engine for enterprise AI
Documentation=https://olivares.ai/docs
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=olivares
Group=olivares
ExecStart=/usr/local/bin/olivares serve \
--listen 127.0.0.1:8443 \
--grpc-listen 127.0.0.1:8444 \
--data-dir /var/lib/olivares
Restart=on-failure
RestartSec=5
# The data directory holds the SQLite store, the audit signing key and the TLS
# material. StateDirectory creates /var/lib/olivares owned by the service user.
StateDirectory=olivares
StateDirectoryMode=0700
UMask=0077
# Hardening (mirrors the container posture: non-root, read-only, no escalation)
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictSUIDSGID=true
RestrictRealtime=true
LockPersonality=true
MemoryDenyWriteExecute=true
SystemCallArchitectures=native
CapabilityBoundingSet=
AmbientCapabilities=
ReadWritePaths=/var/lib/olivares
[Install]
WantedBy=multi-user.target
Terminal window
sudo systemctl daemon-reload
sudo systemctl enable --now olivares

The engine binds every interface by default (:8443): it is a server. The command above passes --listen 127.0.0.1:8443 to restrict this tutorial’s install to the host you are on, which is an explicit decision — drop those two flags to let the console answer from the network, and front it with your own ingress and TLS when you do (see hardening).

A fresh install has no default credentials. On first boot the engine mints a single-use setup token (olst_…) and prints it to stdout only — under systemd, that is the journal:

Terminal window
journalctl -u olivares -o cat | sed -n '/FIRST-BOOT SETUP/,/========================/p'
=== FIRST-BOOT SETUP ===
No accounts exist yet. Open the console and create the first administrator
with this one-time token — setup also creates your first organization and
makes that administrator its owner:
Console: https://127.0.0.1:8443
Token: olst_…
The console serves HTTPS with a self-signed certificate on first boot — your
browser will warn once; that is expected.
Passkeys will not work at that address:
a browser will not run a passkey ceremony at an IP address. Reach the
console by a host name.
On this machine the same console also answers at
https://localhost:8443
and at that address the relying party is derived from the name, which the
verifier accepts.
The token is shown ONCE and is
single-use. Prefer the API? POST /v1/setup {"token":"…","email":"…",
"password":"…"} — add "organization":"…" to name it (default: "Default
Organization"). The reply carries the new organization's tenant_id.
========================

Create the first administrator and log in:

Terminal window
SETUP="olst_…" # from the banner above
curl -ksf -X POST https://127.0.0.1:8443/v1/setup \
-H 'Content-Type: application/json' \
-d "{\"token\":\"$SETUP\",\"email\":\"you@example.com\",\"password\":\"<strong-password>\"}"
TOKEN="$(curl -ksf -X POST https://127.0.0.1:8443/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"you@example.com","password":"<strong-password>"}' \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])')"

Setup already created your organization. Everything in the product is tenant-scoped; read its tenant ID for the sources you will connect:

Terminal window
TENANT="$(curl -ksf https://127.0.0.1:8443/v1/auth/whoami \
-H "Authorization: Bearer $TOKEN" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["grants"][0]["tenant"])')"
echo "tenant: $TENANT"

Sources are declared in one operator-owned JSON file named by OLIVARES_SOURCES_CONFIG, read before the engine starts. Here is the PostgreSQL pgAudit source (the clean-tier R/RW signal — see the pgAudit guide for the Postgres-side setup):

Terminal window
sudo mkdir -p /etc/olivares
sudo tee /etc/olivares/sources.json >/dev/null <<JSON
{"sources":[{
"name": "salesdb-pgaudit",
"kind": "pgaudit",
"tenant": "$TENANT",
"config": { "log_path": "/var/log/postgresql/postgresql.csv", "format": "csvlog" }
}]}
JSON
sudo chmod 0600 /etc/olivares/sources.json && sudo chown olivares: /etc/olivares/sources.json

Point the service at it with a drop-in, and restart:

Terminal window
sudo systemctl edit olivares
[Service]
Environment=OLIVARES_SOURCES_CONFIG=/etc/olivares/sources.json
ReadOnlyPaths=/etc/olivares
Terminal window
sudo systemctl restart olivares
journalctl -u olivares -o cat | grep "ingest: wired source"
ingest: wired source (in-process fast-path) name=salesdb-pgaudit kind=pgaudit

If nothing is wired, the engine says so honestly rather than looking healthy on an empty map — see troubleshooting for the exact warnings and what each means.

On a fresh install, accessmap is off. As an administrator, turn it on in Settings > Edition & modules, keeping the other selected modules on. For the CLI, sign in to this engine as an administrator with olivares login, then run olivares modules on accessmap. Wait for each engine restart before continuing; running sessions stop and can be resumed. Otherwise these API calls return 404 module_not_enabled.

Terminal window
curl -ksf "https://127.0.0.1:8443/v1/m/accessmap/graph?limit=200" \
-H "Authorization: Bearer $TOKEN" -H "X-Olivares-Tenant: $TENANT" | python3 -m json.tool
curl -ksf "https://127.0.0.1:8443/v1/m/accessmap/drift" \
-H "Authorization: Bearer $TOKEN" -H "X-Olivares-Tenant: $TENANT" | python3 -m json.tool

The same graph renders in the embedded web UI at https://127.0.0.1:8443 (from a workstation, tunnel it: ssh -L 8443:127.0.0.1:8443 <host>).

Two artifacts in the data directory decide whether your evidence survives an incident — deal with them now, not after:

Artifact Why it matters Action
audit-signing.key Signs the append-only audit ledger. If it is lost, the ledger can no longer be re-verified. The engine only warns on first boot — there is no enforced escrow. Back it up off-box, with 0600 permissions, today.
The ledger public key An off-box copy of the public key is what makes verification attacker-resistant after a host compromise. curl -ksf https://127.0.0.1:8443/v1/audit/pubkey and store the result off-box.

Then schedule real backups — olivares dr backup produces an encrypted, ledger-continuity-safe bundle; the backup & restore guide is the full procedure, including the restore drill.

The engine exposes /livez (process up), /readyz (store reachable — this is the availability SLI) and /metrics (Prometheus) on the HTTP listener:

Terminal window
curl -ks https://127.0.0.1:8443/readyz
# {"leader":true,"setup_required":false,"status":"ok","store":"up"}

See monitor with Prometheus for the metric set, SLO targets and shipped alert rules.

  • Connect more signals: the connector guides — pgAudit, CloudTrail, Claude Code, eBPF, and the rest of the catalog.
  • Harden the deployment: security hardening — exposure, mTLS for collectors, approvals.
  • Govern: govern and approve — RBAC, policies, and the recorded-decisions guarantee.