---
title: "The Control Deck: browser administration at /"
url: https://www.hmailserver.co.uk/topic/28192/the-control-deck-browser-administration-at
author: "Progressiverobot"
published: 2026-09-23T01:35:00.000Z
updated: 2026-09-23T01:35:00.000Z
category: "Webmail, portal & Control Deck"
tags: ["control-deck","api"]
site: hMailServer Community Forum
---

# The Control Deck: browser administration at /

*Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) refuses a state-changing REST request that carries a credential - HTTP Basic included - when the browser reports it as cross-site (`Sec-Fetch-Site`, or an `Origin` that is not this server's); the Deck and the webmail act on their own origin, and scripts, `hmctl` and the PowerShell module send no such header, so none of them is affected. A credential confined to named domains, a domain administrator among them, is refused a domain's rename, a domain alias, a custom role's creation, change or delete, a domain's or an account's rule's `bind_to_address`, `send_using_route` or `script_function` action, its domain's relay host changed to an address that is not public and the server-wide metric history, over REST as over COM, and so from the Deck. 6.3.7 also carries the first step of the Control Deck's and the webmail's rebuild planned for 6.4 - the framework decision (ControlDeckFramework.md), the threat model of the web surface and the authorisation matrix with its check - with no product code. See [the 6.3.7 announcement](/topic/28277).*

The Control Deck is the administration page hMailServer serves at `/`, on the same listener as the API and the portal. On Linux it is the only administration front end there is, because that build has no Control Panel and no COM. On Windows it does not replace the Control Panel and it does less.

**Turning it on.** One setting, `RestApiPort`, turns on the API, the Deck and the portal together. The default is 0, which leaves all three off, so a server upgraded without touching its settings serves none of them. The listener refuses to start rather than come up without a credential or without TLS, and logs which. Four messages begin `RestApi: Refusing to start`. The two you will meet are an unset administrator password and a non-loopback bind with no certificate. The TLS exemption applies only to a bind address that is exactly `127.0.0.1`, `localhost` or `::1`. [36.2](https://www.progressiverobot.com/hmailserver-documentation/#362-turning-them-on)

**Signing in.** The password goes once to `POST /api/v1/session` and is exchanged for an `hmailsession` cookie that is `HttpOnly` and `SameSite=Strict`. Two ceilings apply, 30 minutes idle and 12 hours absolute. Since 6.3.4 those are the defaults: `SessionIdleSeconds` and `SessionLifetimeSeconds`, server-wide or per domain, change them, and neither is set as shipped, after an upgrade or in a new database ([DevicesAndSessions.md](https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/DevicesAndSessions.md)). Any cookie-authenticated request whose method is not `GET` or `HEAD` must carry `X-Requested-With: hMailServer` or it answers 403; HTTP Basic and bearer keys are exempt. Since 6.3.7 a state-changing request that carries any credential is refused when the browser reports it as cross-site (`Sec-Fetch-Site`, or an `Origin` that is not this server's); scripts, `hmctl` and the PowerShell module send no such header and are unaffected, as are the Deck and the webmail, which act on their own origin. An API key cannot mint a session. Since 6.3.4 an account that holds an administrative role signs in with its own address and password, and a passkey can start the same session, as can the organisation's single sign-on for the addresses named in `oidc_administrators` or `saml_administrators` (both empty as shipped). Sessions are process-local, so a service restart ends every one. [36.3](https://www.progressiverobot.com/hmailserver-documentation/#363-signing-in-to-the-control-deck)

**What it does.** Dashboard, Domains, Delivery queue, DANE/TLSA, Settings, Rules, Routes, Certificates, Ports and Logs. 6.3.3 added full domain editing, the account editor in full, distribution lists and aliases, an IP-ranges view, fetch-account and backup views, the scripting, cache and indexing groups, and a CI harness of 292 checks. At 6.3.4 it has 40 views, in twenty languages besides English.

The settings forms are worth understanding. The Deck fetches `GET /api/v1/openapi.json` once per session and draws each form from the schema of that group's `PUT`. Nothing in the page lists a settings key by name, so a key added to the API appears on its own, with its type, its permitted words, and a badge when it is read-only, write-only, required, or takes effect only on restart; since 6.3.4 a key kept in the settings store says instead whether a save applies it at once, after a reinitialise or after a restart. The Ports view carries a Restart the services now button, which posts to `/api/v1/server/reinitialize`. It drops connections in progress and ends your session with everyone else's. [36.4](https://www.progressiverobot.com/hmailserver-documentation/#364-what-the-control-deck-can-do)

**What the Deck cannot write is measured, not asserted.** `build/check-deck-parity.py` counts every field the desktop Control Panel writes against the REST API and the Deck, and reports in `hmailserver/docs/DeckParity.md`. Of 330 properties, 240 were writable over REST and 153 reachable from a Deck view when that work started; 328 and 322 at 6.3.3. At 6.3.4 the census counts 466, finds 458 of them writable over REST and every one of those reachable from a Deck view, and lists eight as missing: an account's directory fields (title, department, phone, mobile, office, note, photo and the opt-out). Those are written too, by `PUT /api/v1/accounts/{address}/directory` and the directory card of the Deck's account editor, under names the census does not match.

[36.5](https://www.progressiverobot.com/hmailserver-documentation/#365-what-the-control-deck-cannot-do-yet) now opens with the 6.3.4 census and keeps its description of the 6.3.1 gaps, which were far wider, below it for the record; the 6.3.4 section of [CHANGELOG.md](https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/CHANGELOG.md) is the current statement. Check `DeckParity.md` in the [source tree](https://gitlab.com/hmailserver/hmailserver) before assuming a route does not exist.
