Administrator roles end to end: the 27 permissions, giving a role, where each works
-
Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) is a security release that closes gaps in what this guide describes. Over COM an account given
serveradminwith a list of domains was the server's administrator, its list aside, and one givendomainadminwith a list that left out its own domain administered that domain's ordinary accounts; both are now confined as over REST, so before upgrading giveserveradminwith no list to any account that is to administer the whole server over COM, a script's or a Control Panel's account among them. A credential confined to named domains is refused a domain's rename, a domain alias, a custom role's creation, change or deletion, a rule action that reaches the server's own addresses, a route's stored credentials or the event script, a relay host that is not public, and the server-wide metric history, over REST and COM alike; and a role is given or taken away only by a credential that takes in what the account holds now and afterwards, somanage_rolesin named domains can no longer take a role from an account whose admin level is the server administrator's. A state-changing REST request that a browser reports as cross-site is refused. In the Control Panel, API & monitoring is Monitoring & alerts and REST API keys is under Sign-in & access; Ctrl+K takes every old title to its page. See the 6.3.7 announcement.This guide puts administrator roles in one place. Roles are new since 6.3.4 (schema 6047). The one thing to know first: an upgrade changes nobody's authority. The upgrade writes no assignment, and an account with no assignment holds exactly what its admin level has always given it. Nothing narrows until you give somebody a role.
Permissions, roles and assignments
A permission is one thing a credential may do, a role is a named set of permissions, and an assignment gives one account one role in named domains. An account holds at most one role.
Role For Reaches when no domain is named The same as serveradminEverything, including the secrets no other role reads Every domain The administrator password, admin level Server, an API key with Scope=fulland no roledomainadminThe accounts, aliases, lists and mailboxes of a domain The account's own domain Admin level Domain helpdeskFinding an account, resetting its password, unlocking it, and reading where its mail went, and nothing else The account's own domain Nothing before 6.3.4 auditorReading everything the administration exposes, the audit trail included, and changing nothing Every domain An API key with Scope=readonlyand no roleThe built-in roles cannot be edited or deleted. Their permissions are in the server's code, not the
hm_rolestable, so a change to the table cannot hand anybody a permission.The 27 permissions and who holds them
A permission marked server-wide is reached only by a credential with no list of domains. The queue, the quarantine, the archive, the logs and the settings carry every domain's mail, so a role confined to named domains is refused them whatever it holds.
Permission What it reaches serveradmindomainadminhelpdeskauditoradminister_serverEverything, secrets such as password hashes and private keys included; COM's "is this the server administrator?" yes administer_domainCOM's "is this a domain administrator?" yes yes view_configurationStatus, settings, listeners, certificates, rules, routes, anti-spam lists, the roles and who holds them, alert rules and events, bounce and complaint readings; never a secret yes yes yes view_accountsDomains, accounts, aliases, lists, groups (server-wide), fetch accounts yes yes yes yes view_mailboxAnother account's folders and messages yes yes yes view_queueThe delivery queue (server-wide) yes yes view_quarantineThe quarantine (server-wide) yes yes yes view_archiveThe archive (server-wide) yes yes view_logsThe logs (server-wide) yes yes view_message_traceThe message trace; with view_configuration, the reports and a domain's suppression listyes yes yes yes view_auditThe audit trail (server-wide) yes yes manage_accountsCreating, changing and deleting accounts, aliases, lists, groups, fetch accounts and app passwords; a domain's spam traps, DKIM rotation and suppression list; moving a mailbox (needs both domains) yes yes reset_passwordPOST /api/v1/accounts/{address}/password,Application.ResetPasswordyes yes yes unlock_accountPOST /api/v1/accounts/{address}/unlock,Application.UnlockAccount,Account.UnlockMailbox; clearing the logon-failure list (server-wide)yes yes yes manage_mailboxAnother account's folders, messages and folder rights, a support session, a PST migration job (with manage_accounts)yes yes manage_queueRetrying or deleting a queued message (server-wide) yes manage_quarantineReleasing or deleting held mail (server-wide) yes yes manage_archiveHolding and releasing archived messages (server-wide) yes manage_settingsEvery setting, listener, certificate, route, rule and anti-spam list, the alert rules (server-wide); the webmail's branding and file-link policy, a confined credential only its own domains' yes manage_domainsWhich domains exist (server-wide) yes manage_serverReinitialise, back up, reload scripts, clear caches, install an update, run a pass now (server-wide) yes manage_rolesRoles and who holds them (server-wide) yes send_through_apiSending through POST /api/v1/send; only an API key reaches ityes provisionSCIM 2.0 at /scim/v2, reads and writes; only an API key reaches ityes view_discoveryeDiscovery's cases, searches, holds and exports yes yes manage_discoveryOpening and closing a case, searching, legal holds, exports yes manage_inbound_webhooksRouting an address or a domain to a URL, as much as reading every message the route takes yes Four rules sit beside the table:
- The auditor reads mail. It holds
view_mailbox; the help desk does not. - The reports need two permissions.
GET /api/v1/reportsneedsview_configurationandview_message_trace, because it says who mails whom.domainadminandauditorread them;helpdeskis refused, and the Deck leaves the Reports view out for any role without both. - The trace follows the role's reach. A confined help desk traces one whole address in a domain it reaches and sees only events naming that address exactly:
[email protected]does not also show[email protected]. - Clearing the logon-failure list is server-wide.
hm_logon_failuresrecords only the address a failure came from, with no account or domain, so a confined help desk is refusedPOST /api/v1/settings/logon-failures/clear, andSettings.ClearLogonFailureListanswers the server administrator alone. The help desk unlocks one account withPOST /api/v1/accounts/{address}/unlockinstead; a password reset clears the lockout too. A ban already placed is an IP range under/api/v1/ipranges, which needsmanage_settings.
What only serveradmin has
Reading a secret. No
view_permission covers a password hash or a private key: an auditor that could read one would be an offline attack away from being every role.Handing out authority. No custom role may hold
administer_server,administer_domainormanage_roles, and a credential may never give a role holding a permission, or reaching a domain, that it does not hold itself.Taking over a wider account. A credential may not reset the password of, or change, an account whose whole authority it does not take in. A help desk is refused a domain administrator's or an auditor's password, even in its own domain, because otherwise it could sign in as them; a domain administrator is refused an auditor's. Where the server administrator's own mailbox is in a domain somebody else administers, that domain's administrator is refused all of these on it, over REST and COM. Over COM this is asked where the write is made, not where the object was reached:
Account.Save,Account.Delete,Account.MoveTo,Application.ResetPassword, the app passwords and every write to what is in an account (FetchAccount.Save,Rule.Save,IMAPFolder.Save,Message.Saveand the rest) ask that the credential reach the account and take in its authority. An event script's objects carry no credential and are left as they were. Roles.md lists every route and COM member that asks this.Which domains a role reaches
Credential No domains named *A list An assignment of serveradminorauditorEvery domain Every domain Only those An assignment of any other role, custom ones included The account's own domain Every domain Only those An API key's Domains=line, whatever its roleEvery domain Matches no domain Only those A custom role holding a server-wide permission needs
*before an account can use it at all. The listings answerevery_domainover REST, and a fourth field over COM. A credential confined to named domains sees only the assignments of accounts in those domains.Giving a role, surface by surface
Control Panel (Windows only): Accounts & domains → Administrator roles lists the roles and who holds them. Type an address, choose a role, optionally name the domains, and press Give the role; select a row and press Take the role away. It applies at once.
Control Deck (Windows and Linux): the Roles view does the same.
REST: giving or taking away a role needs
manage_roles, which onlyserveradminholds and which is server-wide: the administrator password, or aserveradmincredential reaching every domain.PUT /api/v1/role-assignments/[email protected] {"role":"helpdesk","domains":"example.test,example.org"} DELETE /api/v1/role-assignments/[email protected] GET /api/v1/role-assignments GET /api/v1/rolesCOM (Windows only): an empty role name takes the role away, and
Account.RoleName,RoleDomainsandRolePermissionsread it back:$app = New-Object -ComObject 'hMailServer.Application' $account = $app.Authenticate('Administrator', 'your-admin-password') if (-not $account) { throw 'Authentication failed.' } $app.AssignRole('[email protected]', 'helpdesk', 'example.test') $helen = $app.Domains.ItemByName('example.test').Accounts.ItemByAddress('[email protected]') $helen.RoleName; $helen.RoleDomains; $helen.RolePermissionsWith a second factor on the administrator,
Authenticaterefuses and the script usesAuthenticateWithCode.Application.CurrentRoleandCurrentPermissionssay what a session holds.An API key:
POST /api/v1/apikeyswith"role":"helpdesk"writes aRole=line tohMailServerApiKeys.ini. The key store answers to the administrator password alone. The Deck's API keys view, signed in with that password, also makes a key with a role and its domains, showing the token once.curl -u Administrator:your-admin-password \ -H "Content-Type: application/json" \ -d '{"label":"help desk tool","role":"helpdesk","domains":"example.test"}' \ https://<host>:8045/api/v1/apikeysUse the address and port your listener answers on; bound to loopback with no certificate, it is
http://127.0.0.1:8045(https://once a certificate, or an ACME one, is in place). A key's role decides what it reaches. The Control Panel's REST API keys page, as its reference describes it, names no role; give a key its role over REST or in the Deck. No API key signs in to the Deck.Custom roles are made over REST from a name, a description and a comma-separated permission list; both editors list them and give them out. A role that releases held mail holds server-wide permissions, so it is given with
*and reaches every domain's held mail:POST /api/v1/roles {"name":"quarantine-desk","description":"releases held mail","permissions":"view_quarantine,manage_quarantine"} PUT /api/v1/role-assignments/[email protected] {"role":"quarantine-desk","domains":"*"}A permission the server does not know is dropped, not refused, so a custom role ends with less authority than it asked for, never more. A custom role somebody holds cannot be deleted:
DELETE /api/v1/roles/{name}answers409saying how many accounts hold it, and the Deck's Delete shows that sentence. Give each holder another role or take this one away first; assignments are never removed for you, because an account with none falls back to its admin level. A built-in role answers400, and COM cannot delete a role. An assignment decides even when its role holds nothing: holders of a custom role whose permissions name nothing this version knows are ordinary accounts, not their admin level.Where each role works
Role Control Deck REST API Control Panel (COM) serveradminEvery view Every route Every page domainadminDashboard, DANE / TLSA, domains, fetch accounts, lists, roles and reports for its domains Its domains' accounts, aliases, lists and mailboxes, the status, who holds a role there Domains and Administrator roles helpdeskDomains, fetch accounts and lists, with Reset password and Unlock on every account The reset, the unlock, the account listings, the trace of an address in its domains Welcome and About only; Application.ResetPassword,UnlockAccountandGlobalObjects.MessageTraceanswer a scriptauditorEvery view that reads, the audit trail and reports included Every read, the audit trail and alerts included; every write refused Welcome, About and Administrator roles The help desk and the auditor work in the Deck. COM's settings objects answer only the server administrator, so an auditor reads the configuration through the Deck or REST. A domain administrator is not shown the settings, rules, routes, remote domains, certificates, ports, IP ranges, groups, backup, server messages, queue, logs or audit trail, which are server-wide. The quarantine is server-wide as well, so a domain administrator confined to its domain is refused it.
Hiding a page is a courtesy, not the boundary. The server refuses the request whatever a page draws, and a Control Panel connected to a server that predates roles shows every page.
A role holder signs in with its own address and password, and its second factor where it has one. An app password never carries the role: over REST it is an ordinary account's request, and COM's
Application.AuthenticateandAuthenticateWithCodetreat it as a wrong password. A support session into a mailbox does not carry the person's role either. A role holder's own mail and settings under/api/v1/mestay its own.Setting up a help desk
- Turn the REST listener on if it is off. It needs
RestApiPortset,RestApiBindAddressset to an address staff can reach (the default,127.0.0.1, serves this machine alone), a certificate unless it is bound to loopback, and a name staff can reach. On Windows set them on the Control Panel's API & monitoring page (Monitoring & alerts since 6.3.7) and press Apply now, since they wait for a reinitialise. On Linux runsudo hmailserver --set-setting RestApiPort=8045and the same forRestApiBindAddressand, for any address but loopback,RestApiCertificateFileandRestApiPrivateKeyFile(or let an ACME certificate stand in), thensudo systemctl restart hmailserver. The Control Deck topic has the details. - Give each person a mailbox of their own; the role goes to that account.
- Decide the domains. With none named,
helpdeskreaches only the account's own domain; name several, comma separated, for a desk serving more. - Give the role on any surface above and check it with
GET /api/v1/role-assignmentsor the Roles view. - The person signs in to the Deck at
https://<host>:8045/as themselves, then uses Reset password or Unlock on an account. - Tell them the limits: no mail reading, no reports, no domain administrator's or auditor's password, no removing a ban, and, when confined, no clearing of the logon-failure list.
Each change the help desk makes is on the audit trail as its own, over COM and REST, with actor type
accountand a detail ending[role: helpdesk].What a refusal says
- A permission the role lacks:
403naming both, for examplethe role 'helpdesk' does not hold the permission 'manage_settings'. - A domain it does not reach:
the role 'helpdesk' does not reach that domain, whether or not the account exists, so nobody can list another domain's mailboxes one request at a time. Over COM,Application.ResetPasswordandUnlockAccountanswerNo such account.for both. - An account wider than the credential: that account holds authority this credential does not.
- Over COM, since 6.3.4 a refusal carries the server's sentence rather than a bare
Exception from HRESULT: 0x800403E9. - An API key on the key store, the
[Settings]routes, the audit trail or the alerts:401with{"error":"authentication failed"}, the same as "not a key".
The two stores only the administrator password opens
The key store (
/api/v1/apikeys) and the[Settings]section ofhMailServer.ini(/api/v1/settings/ini) answer to the administrator password and nothing else: not an account holdingserveradmin, not a key of any role or scope. A key that could mint keys could issue itself an unrestricted replacement, and the file holds the server's secrets. An account is refused403with the reason, a key401.The audit trail (
/api/v1/audit) and the alerts (/api/v1/alerts/...) are refused to every API key with the same401, so a stolen key cannot read what it did or silence the alerting. An account whose role reaches every domain reaches them throughview_audit,view_configuration,manage_settingsormanage_server; a confined role is refused them.Upgrades, the audit trail and backups
The upgrade. Schema step 6047 adds
hm_roles, seeded with the four built-in rows, andhm_roleassignments, and writes no assignment. Roles are data, not settings: nothing goes intohm_settingsorhMailServer.ini.The audit trail. Every role created, changed or deleted, and every role given or taken away, is a row naming the credential that did it; an assignment's row reads like
role: helpdesk -> auditor; domains: the account's own domain -> every domain. The actor type follows the role: the administrator password and holders ofserveradminordomainadminareadministrator, every other account isaccount.Backup and restore. An account's assignment travels with it, by role name, and the custom roles travel whenever the domains or the settings do, restored first. A role the restoring server already has is kept as it is, with any difference named in the backup log. The admin level waits until the assignment is written, so a restore that stops part-way leaves no account wider than its role. An assignment naming a role neither side has is dropped, the level stays withheld, and
HM6129names the account. No archive carries the API key store.What it does not do
- No mapping from an identity provider. There is no claims mapping; an identity provider saying somebody is an administrator is not obeyed. The server's roles and
oidc_administratorsorsaml_administratorsdecide. - No role on an app password or a support session.
- No Control Panel or COM on Linux: roles are given there in the Deck and over REST.
Where to read more
- Roles.md, the authority on all of this.
- Sign-in and Identity §7, The Control Deck, The REST API §2 and The COM API and Scripting §23.2.
- AlertsAndAuditTrail.md, Backup.md and Reports.md.
- On this forum: The Control Deck: browser administration at /, The REST API: turning it on, credentials and roles, The COM API on Windows, Hardening a public mail server, Alerts and the audit trail and IP ranges, auto-ban and lockout.
- The auditor reads mail. It holds
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login