Add an operator#
You will end up with an account for one person, with one role, that they must change the
password on at first sign-in. Give every person their own: the audit log records who did
what, and it can only do that when "who" is a person rather than a shared admin.
Before you start#
- The admin role.
- A licence — creating an account is a write.
- The person's name, and a decision about their role.
Step 1 — Choose the role#
Pick the lowest one that lets them do their job.
| Role | Give it to |
|---|---|
viewer | Anyone who needs to see the router but not change it: a colleague diagnosing something, a monitoring account |
operator | Anyone who changes configuration: stage, commit, commit-confirm, roll back, reconcile, install apps |
admin | Anyone who manages accounts, tokens, agent settings, the licence, power or boot images |
Roles are enforced server-side on every route. Promoting later is one PATCH; starting someone at admin because it is easier is how a router ends up with four admins.
Step 2 — Create the account#
Administration → Users → + Add user.
R=https://<router>:8443
T=wh_... # an admin token
curl -sk -X POST -H "Authorization: Bearer $T" -H 'Content-Type: application/json' \
-d '{"name":"jo","role":"operator","password":"a passphrase they will change"}' \
"$R/api/admin/users"The rules the agent enforces:
- The name may use letters, digits, dot, underscore and hyphen, 1 to 64 characters.
admin-tokenand anything beginningtoken:are reserved for the break-glass token and API tokens. - The role must be
viewer,operatororadmin. - The password must be non-empty and at most 1024 characters. There is no minimum
length and no complexity rule, deliberately: an operator picks their own password, and
a rule that pushes people toward
Summer2026!buys nothing. What protects the login is the rate limiting and, when you turn it on, two-factor. - A name that already exists is refused with 409.
The new account is flagged must change password, so the person is made to replace whatever you set at their first sign-in.
Step 3 — Hand over the password out of band#
Not in the same channel you told them the router's address in.
Check it worked#
They can sign in, and were asked to change the password.
The audit log has the creation, attributed to you:
curl -sk -H "Authorization: Bearer $T" "$R/api/audit?limit=20"The entry's operation is create-user and its path carries the name and role.
Changing a role, or resetting a password#
curl -sk -X PATCH -H "Authorization: Bearer $T" -H 'Content-Type: application/json' \
-d '{"role":"viewer"}' "$R/api/admin/users/jo"
curl -sk -X PATCH -H "Authorization: Bearer $T" -H 'Content-Type: application/json' \
-d '{"password":"a new one"}' "$R/api/admin/users/jo"PATCH takes role, password, oidc_subject and email. The Users page does all four.
Changing a password signs out that account's other sessions.
Removing an account#
Administration → Users, the row's delete, or:
curl -sk -X DELETE -H "Authorization: Bearer $T" "$R/api/admin/users/jo"Do this when someone leaves. Also revoke any API tokens they issued — a token carries its own role and outlives the account that created it.
See also#
- Enrol a second factor
- Issue a token for automation
- Single sign-on with an OIDC provider — accounts from your IdP instead
- Users and Roles
Checked against agent/admin.go ·
agent/authhttp.go ·
ui/src/pages/Users.tsx ·
docs/security.md