Two ways to administer
From the admin console, while the server runs. Sign in at the server’s URL and open Settings → Backends → Open admin console. Users, passwords, workspace grants, the server-admin role, paired devices and audit reports are all there, and nothing has to be restarted. This is the normal path — adding a colleague costs no downtime. An invite is one act: a name, an email, a workspace with a role, and — on a server whose login is the password — an initial password. Then tell the person three things: the server address, the email, the password. No invite mail is sent; there is no email plane. The email is required for a user because it is what every sign-in joins on — a user admitted without one cannot sign in by any route until Set email on their row repairs it. Service accounts never have one. That is the whole invite. The person signs in from their own client — the extension or the desktop app’s Sign in to a server…, oroh login — in the browser, on the server’s consent page, with those
credentials or with the identity provider, and their device is bound to
them; nobody mints a code or a token for them. Each device they sign in
is listed under Paired devices as a session of theirs. See
how a person signs in from a client.
From the CLI, with the daemon stopped. storage.json is
single-writer, so the offline verbs refuse while the daemon runs. They
exist for scripting and for recovery — including the one case the
console cannot cover, a server with no administrator left.
Two kinds of role
They are deliberately independent.
Administering the server does not imply seeing every workspace. A
server admin with no grants can add users and mint tokens and still
read nothing — which is the posture an audit reviewer expects, and it
keeps workspace grants the single answer to “who may read this”.
The server refuses to remove the last server admin:Deactivating that user is not blocked, though — if a server ends up
with nobody who can administer it,
ohd user set-admin <id-or-email>
with the daemon stopped is the way back in.Local passwords
Set from the console, or offline:OH_DAEMON_USER_PASSWORD or
OH_DAEMON_USER_PASSWORD_FILE — never a flag.
A password is what lets a person sign in through a browser. Clearing
the password of the only holder on a server with no identity
provider leaves nothing a browser can sign in with, and the served web
app says exactly that rather than pretending to be a door.
Seats & licensing
The free tier includes 6 seats — active users in the directory. Paid plans only add seats above that; the software is otherwise identical. At the seat limit, adding a user refuses; an individual-seat key matching the user’s email admits past it:SSO login (OIDC)
Team deployments can let users sign in through an OpenID Connect provider — in the served web app and on the page every native client sends a person to. Configure the provider indaemon.json:
<redirectOrigin>/auth/oidc/callback as the client’s
redirect URI with the provider. For confidential clients, put the
client secret in daemon.json as oidc.clientSecret or (better) in
the service environment as OH_DAEMON_OIDC_CLIENT_SECRET; public
clients need no secret — the flow always runs PKCE. redirectOrigin
may be omitted for single-hostname deployments; the daemon then
derives it from the request.
A successful login maps the provider’s verified email onto a daemon
user and mints a session token bound to that user, expiring after the
server-wide sessionTtlDays (a top-level daemon.json key, default 30 —
the one policy every session on the server follows, whether it began in
a browser, at the claim, or on a device). Unknown emails are refused unless
autoProvision is true, which creates the user with zero workspace
grants — grant access from the console or with ohd user grant.
A server with an identity provider is never “unclaimed” and never
shows the setup card: configuring an IdP is itself an act of
administration performed on the box, so there is no second ceremony.
That also means no login mints the first administrator
automatically. Grant it once, offline, to a user who already exists
in the directory — one Every administrator after that is a toggle in the console.
ohd user add put there, or one a first SSO
login auto-provisioned: