Skip to content

Othela configuration

Othela is configured entirely by CLI flags. There is no config file and no environment variable layer, which is the opposite of the agent: Othela runs in one place under one systemd unit, so the flexibility the agent needs would only be surface area here.

FlagShortDefaultDescription
--fleet-reponone, requiredGit repository containing the helvilette.yml manifests
--fleet-branchmainRevision of the fleet repository to check out
--fleet-sync-interval1mHow often the fleet repository is re-pulled
--state-dir/var/lib/helvilette/othelaWritable directory for the SQLite database and the fleet clone
--port-p8080Port to listen on
--log-level-linfodebug, info, warn or error

--fleet-repo has no default and Othela exits immediately without it:

[FATAL] --fleet-repo is required

Othela reads manifests from Git and writes state to disk. Those are different locations on purpose, and Othela never writes into the first one.

LocationContentsAccess
--fleet-repo (remote)Manifests, pulled every --fleet-sync-intervalRead-only
--state-dirSQLite database and the fleet cloneRead-write

Inside --state-dir:

PathContents
{state-dir}/db/state.dbNode registrations, labels and reports
{state-dir}/fleetThe working clone of the fleet repository

Development, on your own machine:

Terminal window
go run ./cmd/othela \
--port=8080 \
--fleet-repo=/home/you/fleet \
--state-dir=./data/othela \
--log-level=debug

A local filesystem path is a valid Git URL, so a fleet repository that exists only on your laptop works without a Git server.

Under systemd, with a real Git host:

[Service]
Type=simple
User=helvilette
ExecStart=/usr/local/bin/othela \
--port=8080 \
--fleet-repo=http://git.example.com/helvi-test/baseline.git \
--state-dir=/var/lib/helvilette/othela
Restart=always
RestartSec=5
  1. On startup, and then every --fleet-sync-interval, Othela clones or pulls --fleet-repo into {state-dir}/fleet and checks out --fleet-branch.
  2. It walks that clone recursively for files named helvilette.yml, skipping hidden directories such as .git.
  3. Each manifest is validated. A rejected one is logged at WARN and its playbook is never dispatched.
  4. Accepted manifests replace the in-memory set that agent polls are matched against.

--fleet-branch is resolved as a Git revision rather than strictly a branch name, so a tag or a commit SHA pins the fleet to an exact state.

A failed sync leaves the previous set in place and logs at ERROR:

[ERROR] Failed to sync fleet repository http://git.example.com/org/fleet.git: ...

Othela keeps serving the last good scan, so a stale manifest set is a symptom worth checking the log for. See diagnose a manifest that deploys nothing.

The playbook the agent actually runs does not come from the fleet repository. It comes from spec.repo and spec.playbook inside the manifest, and the agent clones it directly. The two repositories can be the same one.

Both of these now exit with an error naming the replacement. Neither is accepted as a deprecated alias, because neither maps cleanly onto one successor.

Removed flagReplacement
--data-dir, -d--fleet-repo for manifests, --state-dir for writable state
--playbook-dir--fleet-repo

--data-dir named the directory playbooks were loaded from and received the SQLite database at {data-dir}/server/db/state.db, so read-only input and read-write state shared one directory. In the e2e stack that directory was bind-mounted from inside the Go module tree, and Othela running as root wrote root:root files into it, which broke go vet ./... on the host before it compiled anything. Splitting the two is ADR-0003.

--playbook-dir was the read-only half of that split, and it lasted only until manifest resolution moved to Git entirely. Othela no longer reads manifests from local disk at all.