Skip to content

Profiles and Environment

Christopher Holloway edited this page Oct 26, 2026 · 9 revisions

Profiles and Environment

Written on 24 September 2026 from hmailserver/docs/SettingsApply.md, SettingLevels.md, EnvironmentConfiguration.md and Profiles.md, and brought up to 6.3.4 (27 September 2026, schema 6104), on 26 September 2026. Everything on this page is new in 6.3.4, on top of the settings store of schema 6042 (Settings Overview). 6.3.5 (29 September 2026, schema 6105), 6.3.6 (6 October 2026, schema 6108) and 6.3.7, the latest release (17 October 2026, schema 6108), are not yet reflected here.

Four answers to four questions an administrator asks about a setting:

Question Answer Section
When does this change take effect? When it is saved, for 211 of the 241 [Settings] keys; the rest say when §1
Can a domain, or one person, have a different value? Yes, for 27 settings, each a limit, a gate or a preference §2
Can the deployment set it, as Kubernetes expects? Every setting has an environment name, and the environment wins §3
Which thirty settings make my server the kind of server it is? A profile: office, gateway, relay or sender §4

On 6.3.3 a [Settings] key is a line of hMailServer.ini, read at the next start; every database setting is the server's alone; a container takes sixteen HM_* variables; and there are no profiles.

1. A saved setting takes effect when it is saved

Since 6.3.4. Up to 6.3.3 every key of the settings store was latched into the server when the service started, which is what the Control Panel's "applies after a service restart" meant on page after page. Now a save publishes: the server rebuilds its settings from the store, and every key whose readers can take a new value is in effect when the save returns. Every key carries one of three marks, decided key by key from the code that reads it:

Mark Keys What it means Examples
now 211 A save applies it Limits, timeouts, rate limits, feature switches, log options, anti-spam and anti-virus knobs, DNS options, the update check
reinitialize 28 It is bound into something the servers build when they start, so it waits for a reinitialise A listener's port and bind address, a TLS context's certificate files, a work queue's size, AcmeEnabled, DatabaseStatementTimeout
restart 2 (and the 29 bootstrap keys) Read once per process, before the database is open The two service-account keys - retired in 6.3.4, read by nothing, and shown as pending until the next start - and every key of [Database], [Directories], [Security]

Where it shows:

  • Control Panel: a line under each field - Applies on save, After reinitialize, After a restart - and a pending bar at the foot of the window, "N saved setting(s) wait for a reinitialize", with Apply now. Apply now is a reinitialise: every service stops and starts in place, and it ends a drain (it asks first).
  • Control Deck: the same three words as a badge beside each field, and the same pending sentence and Apply now above the Settings view.
  • REST: applies on the ini routes, and GET /api/v1/server/settings/pending for what waits; COM: Settings.IniSettingApplies, IniSettingAppliesAll, PendingIniSettings.

A Control Panel connected to a 6.3.3 server says what it said then - every such field After a restart - and never claims a save took effect.

2. One value, three levels

Schema 6088. Twenty-seven settings may be set for the server, for a domain and for an account, and everywhere one is shown it shows what is in effect and where it came from. For an account: its own value, else its domain's, else the server's. How a level combines with the one above depends on the kind:

Kind Rule Who sets it Examples
Limit (15) A level below may tighten, never loosen; a looser value is refused with a sentence naming the level above, and a value the level above later tightens past is capped when read Whoever administers the level - a domain administrator for their domain The maximum message size, the session lifetimes, the quota grace and send-stop shares, the sending limits, the recall and recover-deleted windows, the reader maximums (fetch accounts, send-as, masked addresses, offline days)
Gate (4) The deepest level that holds a value wins, either way The server administrator only Zero-access mailboxes, the OpenPGP portal, a directory people edit themselves, plus addressing
Preference (8) The deepest level that holds a value wins The domain administrator The quarantine digest and its hour, the external-sender tag, impersonation protection, the quota warning, the country policy, message retention

The Control Panel's domain and account dialogs have a Levels tab; the Deck shows each level's value and source beside the field; GET /api/v1/settings/levels lists the twenty-seven with their kinds, and the domain and account routes answer <name>_effective and <name>_source; COM has EffectiveSetting, EffectiveSettingSource and SettingOverride on Domain and Account. Nothing changes for a domain or an account that holds no value of its own. A setting not on the list is the whole server's, and the domain and account routes refuse its name.

3. Every setting from the environment

Since 6.3.4. Every [Settings] key and every database setting the server reads has a name in the environment:

Variable Sets
HM_SETTING_<key> The [Settings] key - any of the 241. HM_SETTING_MaxSubmissionsPerIPPerMinute=30
HM_PROPERTY_<name> The hm_settings row - any the server reads, among them the message store's, object storage's, SNMP's and PST import's. HM_PROPERTY_maxmessagesize=20480
..._FILE after either The same, read from a file - a Docker, Compose or Kubernetes Secret. Never printed, never answered back

The server's own verb, hmailserver --apply-environment (hMailServer.exe --apply-environment on Windows), stores them into the database. It checks every value first, in the words the REST API would use, and stores nothing and exits 1 when any is refused - so a container does not start on settings it was not given. The container's entrypoint runs it at every start (Running in a Container); on Windows nothing runs it for you, since a Windows service has no environment of its own that anything sets.

The environment wins, every start. A setting the environment names is refused to an administrator's change - REST answers 409, COM refuses, the Deck and the Control Panel show it as Set by the environment with no control - because the next start would undo the change. Unset the variable and restart to manage it here again. The environment sets the server level only; a domain's or an account's value is never an environment setting, and _FILE is refused for a setting with levels, whose value in effect is shown to domain administrators. The two [SendingLimits] keys have no environment name. The database connection's TLS has two variables of the container's own, HM_DB_TLS_MODE and HM_DB_TLS_CA, which the entrypoint writes into [Database]. Not run in a container at 6.3.4: the verb had run on Windows and its Linux half compiled, and the entrypoint, the chart and the Compose file had been read and not executed. The tag pipelines of 6.3.6 and 6.3.7 have run it in a container since, each starting its pushed images through the entrypoint with the REST listener given through the environment, and on 23 October 2026 docker compose up with the tree's Compose file and helm install of the chart were run as a user runs them, against 6.3.7's published image (ContainerImage.md, The start test and What was run by hand; Running in a Container).

4. Profiles

A profile is the thirty or so settings that make a server the kind it is, named, with a reason for each written from what the setting's reader does. Four ship, reviewed, as documents in the repository:

Profile For What it changes that you would notice
office One server that receives an office's mail, holds its mailboxes and sends what its people write SPF, the MX check, DKIM and DMARC scoring; greylisting; spam over the delete threshold held in the quarantine; auto-ban and account lockout; a password policy and the breach check; people send only as themselves; a browser session lasts a working day (31 entries)
gateway Behind a filtering gateway that has already judged the mail The gateway's addresses judged through Incoming relays; greylisting off; XCLIENT and an ARC seal trusted only from the gateway and sealer you name (17 entries)
relay An outbound relay for applications that holds no mailbox anybody reads IMAP and POP3 closed at the next restart; hard bounces suppressed; the back-off and at most ten sessions to one destination; every message traced for three months (24 entries)
sender A high-volume sender judged on its bounce and complaint rates The relay's shape, plus more deliveries at once, a ceiling per destination and per sending domain, the feedback loops, the trace for six months (32 entries)
  • A diff first. Every surface shows each entry beside the value this server holds now, why, and when a change would apply. An entry that closes a listener, trusts an address range, turns a filter off or weakens a check, or shortens a window of days asks for a confirmation.
  • Then a snapshot, then the writes. The apply is all or nothing, saves what it replaces, and is refused if the server has changed since the diff was drawn.
  • The way back. Revert writes back each value the profile replaced - and leaves alone one an administrator has changed since. Discard forgets the way back; Keep the shipped settings records that no profile is wanted.
  • What a profile never touches: a port, a path, a bind address, a command or URL it would run or call, the database connection, a password or any secret, IP ranges, a domain's own settings. What only you know - the gateway's addresses, the complaint mailbox - is a step the profile lists under its diff, not an entry.
  • At the server level only; for a limit with levels, it sets the ceiling.

Where to choose one: the Control Panel's Maintenance → Setting profiles; the Control Deck's Checklist, where A profile for this server is the first item on a young server; the installer's last page for a new installation (/profile=NAME silently); HM_PROFILE in a container; and hmailserver --apply-profile NAME, hmctl settings apply-profile NAME, COM Settings.ApplyProfile, POST /api/v1/settings/profiles/{name}/apply. The installer page, the container's HM_PROFILE and the Linux verbs have been written and read, and not yet run.

What is not there: profiles of your own (four, shipped, reviewed - adding one is a JSON file and a generator run in the repository), more than one snapshot, parameters, and a profile per domain.

The full documents

See also: Settings Overview · Settings Reference · Running in a Container · The Control Panel · The Control Deck

Home — full index

Start here

1. Install and run

2. Secure it

3. Operate it

4. Extend it

5. Contribute to it

Look it up — from any journey


About this wiki

Clone this wiki locally