Users#
Administration → Users lists the agent's own accounts and is where an admin creates them, changes a role, resets a password, links an account to an identity provider or deletes one. None of this is router configuration: accounts live in the agent's state file, not in the configuration tree, so nothing here is staged and nothing here is rolled back by a configuration rollback. Every action takes effect the moment you click it, and every one is written to the audit log.
The page and every route behind it are admin-only. The navigation entry is hidden from
anyone else, and the routes are wrapped in adminOnly, so hiding the entry is a courtesy
rather than the control (ui/src/components/nav.ts,
agent/main.go).
The three role cards#
Across the top, one card per role with a count and the sentence the UI itself uses:
| Role | What the page says |
|---|---|
| Viewer | Reads everything. Cannot stage, commit or roll back. |
| Operator | Everything a viewer can do, plus staging, committing, rollback and reconcile. |
| Admin | Everything, plus accounts, API tokens and agent settings. |
Roles has the same three, checked against the route table rather than summarised.
The table#
GET /api/admin/users returns one row per account
(agent/admin.go userViewOf).
| Column | What it means |
|---|---|
| User | The account name. Your own account carries a you badge. |
| Role | viewer, operator or admin. |
| Two-factor | enabled, or off. |
| Password | set; must change when the account still has to change it at next sign-in; none — SSO only when the account has no password hash at all. |
| Single sign-on | The identity provider's subject, truncated, with the full value as the cell's tooltip — or not linked. |
| Created | Relative time. |
| Last sign-in | Relative time, or never. |
The Password and Single sign-on columns exist to answer one question at a glance on an internet-facing router: which accounts can come in, and by which door.
Creating an account#
+ Add user asks for a username, an initial password and a role. The panel's subtitle states the consequence — the account is asked to change that password at first sign-in — and the password field's hint asks you to hand it over out of band rather than in a ticket.
POST /api/admin/users then checks, in this order
(agent/admin.go handleCreateUser):
- A name is required, and must match
^[A-Za-z0-9._-]{1,64}$— letters, digits, dot, underscore and hyphen. - Two name shapes are reserved.
admin-tokenand anything beginningtoken:are refused: those are the synthetic principals the break-glass token and API tokens act as. An account with one of those names would be indistinguishable from them in the audit trail, and a token principal would resolve to that account's password and two-factor settings. - The role must be one of the three.
- The password must not be empty, and must be at most 1024 characters. There is no minimum length and no complexity rule — that is deliberate, and Account explains what protects the login instead.
- The name must be free, or the answer is
409.
The account is created with the must change password flag set, and the creation is recorded in the audit log with the actor, their role, their address, the new account's name and its role.
Editing an account#
Clicking a row opens a panel with four sections. Save changes is disabled until
something actually changes, and sends only the fields that did — PATCH
/api/admin/users/{name}.
Single sign-on#
One field: the provider's own identifier for this person — the sub claim, not their email
address. Leaving it empty unlinks the account. The field starts as the current value and is
only sent when you edit it, so saving a role change cannot unlink somebody by accident.
The agent refuses a subject another account already claims, with 409 naming that account:
linking is a privilege grant, and two names sharing one identity is not something to allow
quietly.
When the account has no password of its own, the panel warns that unlinking would leave nobody able to sign in as that user — set a password first.
The hint under the field states the other half of the policy, which is enforced during sign-in rather than here: an identity whose username matches a local account that is not linked is refused rather than handed that account. See single sign-on.
Account#
Read-only facts: whether two-factor is enabled, whether the password must be changed at next sign-in, and the last sign-in. There is no control here that disables somebody else's two-factor, and there is none anywhere else either — see the warning below.
Role#
A select, with the same one-line description under it. Demoting the last admin is
refused with 409 and the message this is the only admin — promote another before changing
this one. The count and the change happen under one write lock, because two concurrent
demotions each saw two admins and left none.
Reset password#
Type a new one to set it; leave it blank to keep the current one. A reset:
- sets the must change password flag, so the person is asked to change it at next sign-in;
- deletes the first-boot
initial-passwordfile when the account is the one the agent bootstrapped (agent/main.goclearInitialPassword); - signs the account out everywhere. A role change, a password reset and a subject change each drop every session that account holds. The toast says so.
Changing your own password from this page works, but the panel points you at the Account page instead, which keeps your current session alive.
Deleting an account#
Delete user arms first and needs a second click on Confirm delete. The button is not shown at all on your own row, and the agent refuses it anyway: you cannot delete the account you are signed in as, and you cannot delete the last admin. Deleting removes the account's sessions with it, and is audited.
Deleting an account does not revoke API tokens it created. A token is an independent credential with its own role — see API tokens.
What this page is not#
- Not the router's accounts.
system login user— thevyosconsole account and its SSH keys — is router configuration, edited on the System settings screen and committed like any other change. The accounts here exist only inside the agent. - Not per-object permissions. There are three roles, enforced per route. An account cannot be given the firewall and not NAT.
- Not a group or directory integration. Group-to-role mapping exists for single sign-on and is configured by flags on the agent, not here — see single sign-on.
See also#
- Roles — what each role may actually do, from the route table.
- Account — what a person can change about their own account.
- API tokens — credentials for automation, with the same three roles.
- Single sign-on — provisioning, linking, and what only a flag can change.
- Accounts and sessions — the concept.
- System — audit — where every action on this page lands.
- System — settings — the router's own
system loginaccounts, which are configuration and are not these. - Locked out of the UI — the way back.
Checked against#
ui/src/pages/Users.tsx,
ui/src/lib/api.ts,
ui/src/components/nav.ts,
agent/admin.go,
agent/auth.go,
agent/authhttp.go,
agent/main.go,
agent/oidc.go.