Why Vigo
Simplicity, security, reliability, scalability, and price — where Vigo is different from every other distributed state enforcement system and configuration management tool.
Puppet vs Vigo — side by side
Create a user with passwordless sudo and an SSH key — a task every team does. Puppet needs 4 resources across 2 files. Vigo needs one.
class profile::admin_user ( String $username, String $ssh_pubkey, String $comment = '', Array $groups = ['sudo'], ) { user { $username: ensure => present, managehome => true, shell => '/bin/bash', comment => $comment, groups => $groups, } file { "/home/${username}/.ssh": ensure => directory, owner => $username, group => $username, mode => '0700', require => User[$username], } ssh_authorized_key { "${username}_key": ensure => present, user => $username, type => 'ssh-ed25519', key => $ssh_pubkey, require => File["/home/${username}/.ssh"], } file { "/etc/sudoers.d/${username}": ensure => file, owner => 'root', group => 'root', mode => '0440', content => "${username} ALL=(ALL) NOPASSWD: ALL\n", } }
classes: - profile::admin_user profile::admin_user::username: 'alice' profile::admin_user::comment: 'Alice Nguyen' profile::admin_user::groups: - sudo - adm profile::admin_user::ssh_pubkey: 'AAAAC3NzaC1lZDI1NTE5AAAAIJqR...'
name: os-users resources: - name: alice type: user username: alice comment: Alice Nguyen shell: /bin/bash groups: sudo, adm state: present password: secret:vigo/os-users/alice sudo_nopasswd: true authorized_keys: | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJqR... alice@laptop
📄 Simplicity
One server at any scale
No compile masters, no worker pools, no database clusters, no load balancers. One process, one SQLite file, one config directory. The architecture does not change whether you manage 10 nodes or 100,000.
~5 MB static agent binary
No Ruby, no Python, no JVM, no package manager ecosystem on managed nodes. Copy the binary, run it. Zero runtime dependencies.
One config format, one config path
There is exactly one way to configure Vigo: edit YAML files and publish. No API writes, no database config, no UI mutations. One source of truth, one format, one tool.
No DSL
The configuration language is YAML. Go templates appear only inside content: attributes. No custom language to learn, no compiler, no parser quirks.
Bootstrap is one command
curl | sudo sh downloads the binary, generates TLS certificates, registers with the server, installs the service, and verifies connectivity. Under management in 30 seconds.
Seven OS families from one codebase
Linux, macOS, FreeBSD, OpenBSD, NetBSD, illumos, and Windows. Write type: service and it dispatches to systemd, launchctl, rc.d, rcctl, SMF, or sc.exe.
Conditional resources without an if DSL
when: "os_family('debian')" on any resource or module. Boolean logic, builtins like has_command, arch, version_ge. Server evaluates what it can, passes the rest to the agent. No DSL, no plugins.
Visibility — trace any decision back to its source
One command — vigocli config trace danlap — shows the complete resolution chain for any node. Every module, variable, dependency, compliance tag, waiver, and conditional traced to the exact file that defined it.
when: expression with its evaluation side. Server-side conditions (like changed) are resolved before dispatch; agent-side conditions (like os_family and hour_range) run on the managed node. Template variables are resolved and shown beneath the original expression.🔒 Security
Per-request ED25519 signatures
Every agent request is individually signed and verified against stored public keys. Not just TLS — actual cryptographic proof of identity on every API call. Replay and impersonation require the private key, not just a valid certificate.
Secrets are never materialized
The secret: prefix resolves at config load through a pluggable provider and is stripped before transmission. Secrets never appear in YAML files, environment variables, logs, database rows, gRPC payloads, or run result reports.
No plaintext mode
mTLS is the only transport. There is no --no-ssl flag, no plaintext fallback, no "development mode" that skips encryption. The insecure path does not exist in the codebase.
One-time enrollment tokens
Tokens are bcrypt-hashed at rest and bound to hostname glob patterns. A token that matches *.web.prod cannot enroll a machine named db01.staging. Used once, then permanently invalidated.
Self-protection guardrails
The validation pipeline blocks any resource that targets the agent binary, server binary, config directory, or service unit. Even --dangerous mode cannot bypass these checks. The system cannot be used to break itself.
Verified agent binary
The agent binary is distributed with ED25519 signatures and SHA-256 checksums, verified at bootstrap. Binary hardening includes PIE, full RELRO, stack protectors, stripped symbols, and LTO.
⚡ Reliability
Signed policy bundles with offline convergence
The server signs bundles with ED25519. The agent verifies, caches in LMDB, and continues converging indefinitely if the server disappears. Pending results queue and drain on reconnect.
Adaptive stream promotion
Agents default to lightweight stateless polling. Persistent streams are promoted only when the server has work to dispatch, then released. Idle agents consume zero stream resources.
Evaluation resilience
A template render error or a when: parse error in one resource skips that resource and continues with the rest of the convergence run. A single bad resource does not abort the entire policy.
Zero database operations on the hot path
The FleetIndex is a fully in-memory index with async dirty-set flushing. An agent check-in — lookup, policy compilation, and response — touches zero database queries.
The agent never exits on transient failures
Server unreachable, TLS handshake failure, malformed response, policy evaluation crash — all handled with backoff and retry. The agent binary, once started, runs until explicitly stopped.
Reload with graceful fallback
Config publish validates, syncs, and reloads. If the new config fails validation, the server keeps the previous working config. No downtime, no partial state.
Browser-based remote access (Scrier)
SSH terminals, RDP desktops, and live session shadowing from the web UI. No VPN, no bastion, no port forwarding. Tunnels through the agent's existing mTLS connection. Ephemeral keys per session. Shadow/assist mode lets help desk see and control a user's live desktop with consent.
Observe mode for safe migration
Run Vigo alongside existing CM. Agents report what they would change without applying anything. Cut over when confident. Per-node or fleet-wide.
📈 Scalability
50,000–200,000 nodes per server
On a single 4-core, 8 GB machine. No compile masters, no worker pools, no database clusters. See the analysis →
~300 µs check-in latency
Cache-hit check-ins complete in microseconds, not milliseconds. No catalog compilation, no Ruby interpretation, no database round-trips. 3,300 check-ins per second on a single core.
~50 MB RAM at 10,000 nodes
The in-memory FleetIndex stores only what it needs. Puppet Server requires 8–16 GB for the same fleet. Chef requires 4–8 GB. Vigo runs on a Raspberry Pi.
No external database
SQLite in WAL mode. No PostgreSQL cluster to provision, tune, backup, upgrade, or keep alive at 3 AM. The database is a single file you can copy with cp.
Delta streaming protocol
After the initial check-in, agents send only what changed — traits deltas, run completions, heartbeats. No redundant full-state transfers on every cycle.
Hub-spoke spanner for multi-region
When one server is not enough, spanner fans out enrollment, queries, and tasks across spoke servers. Each spoke manages its own fleet. The hub aggregates results. No shared database.
💰 Price
Free for 25 nodes. No time limit.*
No credit card, no feature gates. Every capability — orchestration, workflows, queries, native integrations, compliance export, AI assistant — is included at every tier.
No enterprise-only features
There is no "Enterprise Edition" with critical features held back. RBAC, OIDC, API tokens, compliance export, spanner — all included. The free tier is the full product.
Infrastructure cost: near zero
One process, one SQLite file, ~50 MB RAM at 10,000 nodes. No PostgreSQL cluster, no Redis, no message queue, no compile master fleet. The server that runs your monitoring can run Vigo too.
No per-node agent licensing
The agent binary is freely distributable. You pay for the server-side node count, not per agent install. Decommission and re-enroll without license churn.
Simple per-node pricing
$144/node/year at 26 nodes, dropping to $84/node/year at scale. Volume discounts are automatic. No sales calls required until 5,000+ nodes.
Lowest total cost of ownership
License is the only meaningful cost. No compile masters, no PostgreSQL DBA, no dedicated CM engineers. At 1,000 nodes, Vigo's total TCO is ~$172K. Puppet's is ~$284K. See the full TCO breakdown →
See how it compares
Detailed head-to-head analysis against Puppet, Ansible, Chef, Salt, and CFEngine.
* Free tier is for evaluation purposes only and is provided AS IS with no support obligation. See Commercial Terms.