Architecture
How are the pieces arranged, and what talks to what?
Vigo has three binaries and one loop. A central server (vigosrv) holds the desired state; a Rust agent (vigo) on every managed node (an envoy) pulls that state, applies it, and reports back; an admin CLI (vigocli) and an HTMX web UI drive the server's REST API. The agent always initiates — the server never reaches into a node — so envoys behind NAT or firewalls need no inbound ports.
The check-in loop
Everything an envoy does happens on a fixed interval, in three steps:
- CheckIn — the agent calls the server over gRPC/mTLS with its UUID, a fingerprint of its current state, and its traits (auto-discovered facts: OS, hardware, packages, …). Every request is ed25519-signed against the pubkey the server stored at enrollment.
- Resolve → PolicyBundle — the server matches the envoy's hostname against hostcrates (first match wins), resolves roles → configcrates → resources, merges variables and per-environment overrides, builds the dependency DAG, and returns an ordered bundle.
secret:references are replaced with opaque markers — plaintext never crosses the wire. - Apply → ReportResult — the agent applies each resource idempotently (check before act), honors
depends_onordering andnotify/subscribestriggers, fetches real secret values at apply time, and reports per-resource outcomes back to the server, which stores them.
The model is pull-based: there is no push channel from server to node for routine work. When an operator needs immediacy (a force-push, an ad-hoc task, a Scrier session), the server uses the agent's already-open stream rather than dialing in.
Why it's shaped this way
- The agent survives a missing server. It caches the last bundle, its traits, and a results queue in an embedded LMDB store, so it keeps converging offline and flushes results on reconnect. See convergence vs compliance.
- Files are the only source of truth. Operators edit YAML (
.vgo) under the stacks;vigocli config publishvalidates and reloads. There is no API/UI/DB path that writes config. - One server scales to tens of thousands of envoys at a normal cadence (fewer at a one-second cadence, where per-check-in CPU binds first — the cadence sets the ceiling), and past that, spanner federates write-equal peers.
Where this shows up
- Configcrates — how desired state is written and resolved.
- The security model — mTLS, signing, RBAC, the audit chain.
- Install the server · Enroll an envoy — the loop, set up for real.
Confidential — Alexander4, LLC. Not for redistribution.