# First-run setup What's left after the first `nixos-rebuild switch` of the [README's all-local quick start](../../README.md#quick-start-an-all-local-swarm) — from a freshly built host to your first agent. Step 0, the NixOS flake, module and required options, is [`nixos.md`](nixos.md). Everything after that takes one command, which you run as **root on the host**: ```bash swarmctl setup ``` It walks the ten steps interactively, in order. It checks where you stand first, so a rerun continues where it stopped. It shows `Step n of N`, prompts for what each step needs, shows a running action as one live line, and prints the secrets you must record under a ⚠️ warning until you type `yes` to say you stored them. A step this host can't do, because it doesn't run that service, names the deploy option it needs and the host to run `swarmctl setup` on. A session that starts at the SSO account, with the store already set up, looks like this: ```console # swarmctl setup swarmctl setup: 10 steps, 4 left to do ✔ 1 secret store initialised ✔ 2 secret store unsealed ✔ 3 granter bootstrapped ✔ 4 granting units active ✔ 5 store unsealed after the granting units ○ 6 SSO account in the admins group ○ 7 first swarm UI and forge login ○ 8 forge site admin ○ 9 ruth created and up ○ 10 another agent (optional) Step 6 of 10: SSO account in the admins group (4 left, this one included) no enabled user in the "admins" group; the placeholder is disabled Your SSO account is made in the `admins` group, which the swarm UI gates on. Username: mara Display name [mara]: Mara Email address (the forge needs one): mara@example.com ✔ added mara ⚠️ Its generated password follows. It is shown once and stored nowhere. password: … Type `yes` once you have stored the password: yes ``` Steps the tool can't do for you print their command and wait: the unseal under the `shamir` seal, the restart after the granter, and the browser login. Run `swarmctl setup status` at any point to see how far you have got. It changes nothing, and it works from a script: it exits 0 when every step it can see has finished. ```console # swarmctl setup status 🏗️ setup: 6/8 steps done ███████░░░ ❓ 2 unknown ✅ 1 secret store initialised ✅ 2 secret store unsealed ✅ 3 granter bootstrapped the granting units log in through it ✅ 4 granting units active 2 units ✅ 5 store unsealed after the granting units 👉 6 SSO account in the admins group no enabled user in the "admins" group; the placeholder is disabled ↳ setup.md § 2: `swarmctl user add --email
--group admins` ❓ 7 first swarm UI and forge login unknown (not observable: a browser login leaves nothing to read) ❓ 8 forge site admin unknown (not observable: the controller has no read route for it; `forge make-admin` is safe to re-run) ⬜ 9 ruth created and up ruth is declared paused ✅ 10 another agent [optional] 1 besides ruth next: step 6, setup.md § 2: `swarmctl user add --email
--group admins` ``` > **Not all-local?** Each step says which host it runs on. A split swarm > also has credentials you can't generate where they're read — each > host's mTLS identity at the secret store. Read [`2-handbook/swarm/credentials.md`](../2-handbook/swarm/credentials.md) first; it > says which files you place, and where. ## The steps by hand The sections below are the same steps, one command each. Use them to know what a step does, to script one, or to redo one. Do them in order; each one assumes the ones before it. ### 1 · Secret store _On the host running `swarm-bao`._ Everything else fetches its credentials from the store, so it comes first. ```bash swarmctl bao init ``` It prints the unseal (or, under the default `pkcs11` seal, recovery) keys and the root token **once**, and stores none of them: not in a file, and the root token is never in a process's argument list (so not in `ps`). Record them off this host before you do anything else. It refuses an initialised store, and works from any host that can reach the store and has `bao` on `PATH`; the wrapper installed on the store host already knows the store's address and CA, and presents a client certificate: the hive's own where a hive runs on that host, else the `operator` leaf that `swarm-bao-pki` mints. Both open the TLS handshake, and neither logs in to a role. Then bootstrap the **granter**, the one principal that writes every `swarm-*` policy and role from then on. This is the only step that needs the root token. Run it as root on the host running `swarm-bao`: ```bash swarmctl bao grant-bootstrap # prompts for the root token, input hidden ``` It writes the `bao-bootstrap` policy, places a 24h grant token for `swarm-bao-granter-role` and restarts that unit. The token comes from the hidden prompt, or from stdin when stdin isn't a terminal; never from an argument or environment variable. If the granter exists already, it says so and does nothing. To do both steps in one go, without re-typing the root token, run `swarmctl bao init --and-grant` instead (it needs the `pkcs11` seal, which unseals itself). If the host running `swarm-bao` has no `swarmctl` (the controller runs elsewhere), the granting units print the equivalent `bao` commands when the store refuses them. Check `systemctl status swarm-bao-granter-role` logs `Uploaded policy: bao-granter`, then restart the granting units that failed while they waited. The granter unit deletes the token itself after a successful run: ```bash systemctl reset-failed 'swarm-bao-*-policy.service' swarm-bao-agent-pki.service systemctl restart 'swarm-bao-*-policy.service' swarm-bao-agent-pki.service systemctl status swarm-bao-controller-policy # Uploaded policy, Data written to: auth/cert/certs/swarm-controller ``` ⏱️ A first attempt right after a rebuild may fail with `local node not active` while the store comes up; the units retry every 30s for a day. With the default `pkcs11` seal the store unseals itself from here on. With `deploy.bao.seal = "shamir"`, run `bao operator unseal` after every restart. What the granter is, why it's root-equivalent, and the store's TLS: [`4-implementation/swarm/bao.md`](../4-implementation/swarm/bao.md). ### 2 · Your SSO account _On the host running authelia._ Until this runs, `auth.` serves a login page that refuses everyone: its only subject is a placeholder marked `disabled`. ```bash swarmctl user add mara --display-name Mara --email mara@example.com --group admins ``` It prints a generated password once — record it. Keep both flags: - **`--group admins`** — the swarm UI and other operator surfaces gate on it. Without it you log in fine and are then refused. - **`--email`** — the forge won't create an account without one. Fix either afterwards with `swarmctl user update mara --add-group admins --email …`. Details: [`2-handbook/swarm/sso.md`](../2-handbook/swarm/sso.md). ### 3 · Swarm UI login Open `https:///` and sign in with the account from step 2. The name resolves on the box itself through `/etc/hosts`; from anywhere else it needs a real DNS record. → [`2-handbook/swarm/ui.md`](../2-handbook/swarm/ui.md) Signing in to the forge once through SSO creates your forge account under the same username. Then, _on the swarm-controller's host_: ```bash swarmctl forge make-admin mara ``` If the forge already has a local account with your username, the first SSO login asks for its forge password once, to link the two. Agents learn your pronouns from the **Pronouns** field of your forge profile settings. Leave it empty and agents refer to you by name only. ### 4 · Clippy, then ruth hive-c0re creates no agent at startup. On the swarm UI's start page, the paperclip (clippy, the setup assistant) offers to set up ruth, the manager agent. Select it: it opens the create form with `ruth` filled in and the `ruth` archetype picked. The archetype sets her model to `sonnet` and checks the `manage_root_agent` permission, which mounts the other agents into her container so she can recover them, plus `logs` and `metrics`. The form declares her and deploys her to the hive you pick. An archetype agent has no config repo of its own. The form lists archetypes from the swarm builder; until the list has `ruth` it says so and creates a plain agent with the default permissions, so wait for the list and reopen the form. The swarm declares a new agent `paused`, so without a further step ruth runs but drives no turns. Open `/agents` in the swarm UI and set her `up` from her card. On a hive that already has a ruth container from an earlier release, create her once the same way, so that her store identity exists. The container keeps starting with the hive meanwhile. ### 5 · Ask ruth for further help From here on, ask ruth. Open her card on `/agents` in the swarm UI and use the message box under her terminal. She is the manager agent: her MCP surface is the privileged one that configures agents, and she can recover the others. Changes to an agent's config arrive as PRs you merge. → [`2-handbook/agents/agent-permissions.md`](../2-handbook/agents/agent-permissions.md) To create an agent yourself instead, use the swarm UI, or: ```bash swarmctl agent create --hive firsthive ``` The name is yours to choose; it has no meaning to the swarm. The controller provisions the agent's identity, forge user and config repo (`agent-configs/`, from the default template), then has the hive build and start the container. The hive builds from a copy of hyperhive on the swarm's own forge: the controller mirrors it there as `hyperhive/hyperhive` on a fresh swarm, so the first agent needs no extra step (see [`nixos.md`](nixos.md#the-hyperhive-mirror)). It returns once the scheduler queues the job — watch the swarm UI's job view for progress. Later config changes are PRs on `agent-configs/`; you merge them on the forge, and the merge deploys them. → [`2-handbook/agents/persistence.md`](../2-handbook/agents/persistence.md#config-changes) ## After setup: use the swarm UI Day-to-day operation happens in the swarm UI at `https:///`: agents, hives, jobs and messages. Swarm-level operations take over from the per-hive dashboard and `hivectl`. → [`2-handbook/swarm/ui.md`](../2-handbook/swarm/ui.md)