A server you own, joined once
Enrollment is the only moment a server needs anything from you beyond root SSH. After that, the agent dials out, the control plane pushes plans, and the box just runs containers.
The enrollment lifecycle
A server's status moves through a small set of states, all visible in the dashboard:
enrolling
You've created the server record and have a one-liner with a single-use enroll token, but the bootstrap script hasn't finished on the box yet.
bootstrapping
The bootstrap one-liner is running as root on the server — installing Docker, the agent, and the firewall baseline. This takes a couple of minutes.
ready
The agent has dialed home and the control channel is live. This flip happens within seconds of the agent connecting — the couple of minutes is all bootstrap, not this step.
Two other states exist outside the happy path: unreachable (was ready, hasn't heartbeated recently — usually the box is off or its network changed) and failed (bootstrap hit an unrecoverable error; the dashboard shows the exact step and captured logs, and re-running the same one-liner safely resumes since every step is check-then-act).
Outbound-only, always
The agent is a single static Go binary. It never listens for an inbound connection from Sproobo — it dials out on two channels:
- Control channel — a persistent WebSocket over WSS/443: tasks flow down, heartbeats and small events flow up.
- Bulk channel — HTTPS POST: fact snapshots, deploy logs, and larger results.
Both channels authenticate with the agent's mTLS client certificate. Nothing about enrollment or normal operation requires opening an inbound port on the server — see Security model for how that identity is issued and rotated.
Supported operating systems
Two families, detected automatically during bootstrap:
- Debian-family (apt + ufw) — Ubuntu 22.04, 24.04, 26.04; Debian 12, 13.
- RHEL-family (dnf + firewalld) — Amazon Linux 2023.
Firewall enforcement is the only OS-aware step in the whole system — everything else (Docker, the agent, the proxy, deploys) is identical across both families.
Keeping the fleet current
Once enrolled, the agent binary itself updates without you touching SSH again. The control plane converges the fleet to a desired version:
- A rollout reconciler updates connected, non-paused agents one at a time, oldest-version-first, health-gating each before advancing to the next.
- Any failure halts the rollout for the rest of the fleet rather than cascading — you see the failure surfaced, not a wave of broken servers.
- Each server has a pause updates toggle in the dashboard, for a box you want to freeze on its current version.
The swap itself is dual-guarded against a bad build: if the new binary crashes on start, systemd restores the previous binary automatically; if it starts but can't reach the control plane within a short soak window, it rolls itself back the same way. Either path leaves the server on its last known-good agent — never dark, never requiring a manual fix.
Lockout prevention is absolute: no operation — human or AI, including agent updates and firewall changes — is allowed to close SSH or sever the agent's control channel. Your own root access to the box always keeps working.
Hardening the box
Bootstrap gets a server enrolled; it doesn't harden SSH, add fail2ban, or configure unattended upgrades. That's a separate, optional one-liner — see Scripts & one-liners for the full harden.sh flag reference (Debian-family only today).
Moving and retiring servers
From a server's Danger Zone in the dashboard:
- Transfer to another organization — requires ADMIN or above in both the source and destination org. You pick the destination and type the server's name to confirm. It's a control-plane records-only move (apps, services, tasks, telemetry, backups, and certificates all follow) — the box and its agent aren't touched. It's refused while any deploy, backup, or restore task is in flight for that server, or if the destination org would exceed its plan caps.
- Delete an empty server — available once a server has zero apps and zero services. This removes the server's control-plane record; it does not reach out to the box. If the agent is still installed, it simply gets rejected the next time it tries to reconnect.
Next
- Walk the full enroll-to-deploy flow on Getting started.
- See every bootstrap and hardening flag on Scripts & one-liners.
- Read the full trust-boundary and data-ownership model on Security model.