Skip to content
  • Categories
  • Recent
  • Popular
  • Tags
  • Users
  • Groups
  • Documentation
  • Downloads
  • Report a bug
  • GitHub mirror
  • Paid support
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
hMailServer Community Forum
hMailServer 6.3.8 is the current release, signed 2 November 2026. Windows and Linux, and an in-place upgrade from 5.3 or later, but for the original hMailServer's 5.7.Download 6.3.8 Documentation FAQ
  1. Support and discussion for hMailServer
  2. Running hMailServer
  3. Linux
  4. The hmailserver command line on Linux: every verb, who runs it, the files, the unit

The hmailserver command line on Linux: every verb, who runs it, the files, the unit

Scheduled Pinned Locked Moved Linux
linuxadministrationsystemdpackagingsecurity
1 Posts 1 Posters 142 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • ProgressiverobotP
    ProgressiverobotP
    Progressiverobot
    hMailServer Team
    wrote on last edited by chris
    #1

    Written for 6.3.4. hMailServer 6.3.6 (6 October 2026) carries .deb and .rpm packages for x86-64 and AArch64, one for each of Debian 12 and 13, Ubuntu 24.04, Fedora 43 and 44, Enterprise Linux 9 and 10, and openSUSE Leap 16.0 and Tumbleweed, both AppImages and the first container image. Its commands say what they did on their own output rather than in the error log, and the store commands run as root refuse a data directory that another account could have linked into. See the 6.3.6 announcement. From 6.3.6 the root helper applies hMailServer 6.3.7 (17 October 2026), a security release, by the live update, for the generic .deb and .rpm of either architecture and both AppImages; a server from one of 6.3.6's per-distribution packages is offered the generic package, which apt refuses on Debian 12 and dnf on Enterprise Linux 9, and is upgraded with its package manager and its release's own package, and from 6.3.4 or 6.3.5 install 6.3.7 with apt, dnf or zypper, not by the live update. A server whose UpdateSigningIdentity, UpdateSigningIssuer and UpdateSourceRepository still name the path the project began at refuses 6.3.7 and 6.3.8 until sudo hmailserver --set-setting <name>= clears each of the three and the service is restarted. See the 6.3.7 announcement. From 6.3.6 or 6.3.7 the root helper applies hMailServer 6.3.8 (2 November 2026), a security release, by the live update in the same way; a server from one of 6.3.6's or 6.3.7's per-distribution packages is upgraded with its package manager and its release's own package, and from 6.3.4 or 6.3.5 install 6.3.8 with apt, dnf or zypper rather than by the live update, or turn the live update's apply off first with systemctl disable --now hmailserver-update.path. 6.3.8 names files in UTF-8 whatever LANG says: on a server that ran under a LANG that is not UTF-8, rename each file and folder named outside ASCII to its UTF-8 name before upgrading, for example with convmv -f iso-8859-1 -t utf-8 -r --notest <folder>. The values --set-setting, --apply-profile, --account and --domain take, and --config, are read as UTF-8 and refused with exit 2 when they are not. See the 6.3.8 announcement.

    On Linux the server is one executable, /usr/bin/hmailserver, and what cannot be done over the REST API, from creating the schema to rewriting the message store, is done with its own options. This topic lists every verb 6.3.4's documents name and who runs it, where the package puts its files, what the systemd unit lets the service touch, and how the root helper applies a live update. What a Linux server has and lacks is in hMailServer on Linux, the first install in First install on Linux. The one thing to know first: on a package installation /etc/hmailserver/hMailServer.ini is 0640 root:hmailserver, and the service cannot write it.

    Where the package puts things

    Path What it is
    /usr/bin/hmailserver the server, one file
    /usr/bin/tlds.txt, /usr/bin/dh2048.pem read from beside the binary; the second is required by every TLS context
    /usr/share/hmailserver/DBScripts/*.sql the schema creation and upgrade scripts
    /usr/lib/systemd/system/hmailserver.service the unit
    /etc/hmailserver/hMailServer.ini the configuration, a conffile an upgrade never overwrites; since 6.3.4 its [Settings] section is a copy of the database
    /usr/bin/hmctl since 6.3.4, the command-line client over the REST API
    /etc/logrotate.d/hmailserver the log rotation rule
    /etc/fail2ban/filter.d/hmailserver.conf, /etc/fail2ban/jail.d/hmailserver.conf the fail2ban filter and jail, the jail disabled as shipped
    /usr/lib/hmailserver/hmailserver-update, /usr/lib/hmailserver/autoban-hook the root update helper (since 6.3.4) and the firewall hook
    /var/lib/hmailserver, with temp, events and database under it the mail store, one directory per domain and one per mailbox; scratch space; event scripts
    /var/log/hmailserver the logs

    What the maintainer scripts do. They create the hmailserver system user and group, and the last two rows above, all 0750 hmailserver:hmailserver; install the configuration; and enable hmailserver.service without starting it, on purpose, because there is no database yet. On an upgrade they run hmailserver --upgrade-database as the service user, only if a database is configured, then try-restart the service if it was running. On removal they stop and disable, and leave the mail store and the logs alone; a .deb purge removes the configuration as well, and /etc/hmailserver with it when nothing else is in it, and still leaves the store.

    Which packages exist. 6.3.4 carries two x86-64 packages, hmailserver_6.3.4_amd64.deb and hmailserver-6.3.4-1.x86_64.rpm, and no container image of 6.3.4 is published. The .deb installs on Ubuntu 26.04 and 24.04, not on Debian 12; the .rpm on Fedora 43 and 44 and Enterprise Linux 10, not on Enterprise Linux 9; the rest of the platform picture is in hMailServer on Linux. The packages carry no Sigstore bundle, so no live update installs them: 6.3.4 is installed by hand (Upgrading to 6.3.4).

    Who runs what

    As root (sudo), because the file is root's: --set-admin-password, --set-setting, and the four stored-secrets verbs. All but the export write /etc/hmailserver/hMailServer.ini, and the export a new file of its own (below); --set-setting keeps the file's owner and mode.

    As the service user (sudo -u hmailserver), because the verb opens the database or writes the data directory: the rest, from --create-database to the store walks. --apply-new-install-defaults refuses to run as root (exit 2), whose certificate key the service could not read, and --sample-domain run as root leaves today's log owned by root.

    Two things follow from the file being root's. The running server cannot write its copy of a stored value back into [Settings]: a value stored over the API is in effect and the file's line goes stale, which the server says once a start in the application log, not as an error. The stale line is never taken for an edit, so nothing needs changing by hand; only what reads the file itself, such as a server that cannot read its table, sees the older value (how the settings store works). The exception is a [Settings] secret sealed once the stored-secrets key exists (below): its line cannot be rewritten, and HM5803 names it at each start until sudo hmailserver --set-setting <name> writes it. And a server that verifies an older MD5 or SHA-256 administrator password hash cannot write it again as PBKDF2: it says so once a process (HM7494), and sudo hmailserver --set-admin-password does it.

    Every verb

    Every row from --check-database to the stored-secrets verbs is new since 6.3.4.

    Verb Runs as What it does
    --config <file> The configuration to read. Default: hMailServer.ini beside the executable, then /etc/hmailserver/hMailServer.ini
    --foreground the unit Run in the foreground and log to standard error as well as the log directory. It is the default
    --check-config service user Print the configuration path, the directories and the database type, and exit without opening a listener or the database. Database type: 0 means the Type key did not take
    --set-admin-password root Read a new administrator password from standard input with echo off, hash it with PBKDF2, and write it to the file
    --create-database service user Create the database [Database] names, or use an existing empty one, and run the create script for its type. Refuses SQL Server and SQL Server Compact by name. Since 6.3.4, says the wiki's Installing on Linux, a database that holds this build's schema or an older one is left as it is with exit 0, and a newer one exits 1; 6.3.3 refused any database that held a schema. The documentation page (35.4, 35.7) still says a schema is refused, exit 1: test it on a scratch database first
    --upgrade-database service user Run every upgrade script from the database's version to this build's, in order. Refuses a database from a newer build; stops rather than loops if a script runs and the version does not move. Safe to run by hand
    --check-database service user Connect once with TlsMode and TlsCaFile, say whether the connection is encrypted and the certificate checked: exit 0 connected, 1 not, 2 not configured. Changes nothing, and runs beside a running service
    --set-setting NAME=VALUE, --set-setting NAME root Store one [Settings] value in the database and write the server's copy into the file (below)
    --apply-environment service user Store every setting the environment names (HM_SETTING_<key>, HM_PROPERTY_<name>, their _FILE forms, the container's HM_REST_*), each checked first: exit 1, with nothing stored, if one is refused. It writes the file's copy too, so the file must be writable, as the container's is; where it is not, as for the service user on a package installation, the verb refuses before it stores anything. EnvironmentConfiguration.md says it has been run on Windows only, and on Linux compiled but not run: try it on a scratch database first
    --apply-profile NAME [--confirm] [--once] [--if-new], --revert-profile service user, server stopped Apply one of the four setting profiles (office, gateway, relay, sender; none records that none is wanted), or put back what the last one changed. Exit 3 means an entry needs --confirm, 5 that --if-new found ten accounts or more. On Windows the verb refuses while the service runs (exit 4); Profiles.md says that on Linux nothing tells it whether a server runs, and that the POSIX verbs have been written and read, and not run: try them on a scratch database first
    --apply-new-install-defaults [--if-marked [<file>]] service user, server stopped The secure defaults of a new installation (below). Exit 0 applied, 1 something could not be written (HM7510, HM7511), 2 no database or run as root, 5 not a database this installation created, or not as the create script left it
    --sample-domain create, --sample-domain remove service user Make or remove the throwaway example.test. Exit 0 done, 2 refused, 1 failed. Remove it before the server takes real mail
    --measure-store service user What compressing the store and holding its large parts once would save. Changes nothing, and runs beside a running server
    --compress-store [--decompress], --recount-store service user, server stopped Rewrite the store in place, or back to plain RFC 822; recount the parts held once. Refused while the server runs (exit 4): on Linux the server holds a lock in the log directory for as long as it runs
    --encrypt-store, --decrypt-store service user, server stopped Encrypt what a mailbox encrypted at rest stored before it was switched on, or put it back. --decrypt-store reads the domain's recovery passphrase from HMAILSERVER_RECOVERY_PASSPHRASE, never from the command line
    --copy-store-to-object-storage, --copy-store-from-object-storage service user Copy the message store into the object store the settings name, or back, each file verified and a stopped run resumed. They run beside the server; --remove-source removes what was copied from once its copy is verified, and only with the server stopped (exit 4 beside it)
    --verify-update <file> Check a downloaded package or AppImage against the Sigstore bundle beside it; exit 0 when a signer the server trusts made it
    --create-stored-secrets-key, --export-stored-secrets-key <file>, --import-stored-secrets-key <file>, --forget-sealed-secrets <key id> root Make the stored-secrets key, export it, import it on another node, or, with the server stopped (exit 4 beside it), clear what was sealed under a key lost for good (below)
    --version, --help

    --measure-store, --compress-store, --encrypt-store, --decrypt-store and the two copies take --account <address> for one mailbox or --domain <name> for one domain's, and neither for the whole store; --decrypt-store needs one of the two.

    Signals. SIGTERM and SIGINT stop the server. SIGHUP, which systemctl reload hmailserver sends, re-reads the configuration; it stops and restarts the listeners inside the running process, so do it when nothing is mid-delivery. Since 6.3.4 the server drains before it stops: the mail listeners close at the socket, so senders retry, and ShutdownDrainSeconds lets what is in flight finish. At its default of 0 nothing is waited for, and a session mid-DATA at the moment of the stop is cut: set it on a production server, where Upgrading.md calls 30 a reasonable figure.

    --set-setting: the way in before the API exists (since 6.3.4)

    From schema 6042 the database is the settings store. Every [Settings] key the file holds at the server's first start is taken into the database then, the packaged RestApiPort=0 among them. Afterwards a line edited in the file is reported in the error log as HM5804 and the stored value is used, so an edit to the file brings no listener up, and with the listener off nothing that speaks the API can change it either.

    sudo hmailserver --set-setting RestApiPort=8045
    sudo hmailserver --set-setting RestApiBindAddress=127.0.0.1
    sudo systemctl restart hmailserver
    

    The verb stores the value as the REST API does and prints what it stored. It refuses a name the server's settings loader does not read, a whole number that is not one, a port that is not 0 to 65535, and a RestApiBindAddress that is not an IP address or localhost: the checks --apply-environment makes, in the same words. A secret's value is refused on the command line, where the shell's history, the process list and sudo's log would keep it. Give the name alone, sudo hmailserver --set-setting SRSSecret, and type the value at a prompt that does not echo it, or pipe it in.

    Which sections and keys stay in the file rather than the database, and the file's [SettingsOverride] section, which forces a value over the stored one (HM5807, HM5808), are in Settings: what is not stock, when a save takes effect.

    The stored-secrets key on Linux (since 6.3.4)

    A Linux server has two secret stores. The machine's is the key file <DataFolder>/.hmailserver-secret-key, mode 0600, made by the server on first use: the database password in the configuration and the route and fetch-account passwords are kept under it as LINUX1: envelopes. It travels with the data directory. A secret moved to a machine without it cannot be opened (HM6414), and there is no re-keying command: replacing the file means re-entering every stored password. The installation's is the stored-secrets key, [Security] StoredSecretsKey, under which each account's TOTP second factor and the [Settings] secrets are sealed in the database as HMK1: envelopes, so that every node sharing the database can open them.

    The service never makes it. On a package installation --create-database runs as the service user, cannot write the root-owned file, makes no key and says what to run instead. An upgrade makes none. Until a key exists those secrets are kept as written, and the setup checklist's stored_secrets_key item offers the step. Make the key, export it and restart the service; nothing is sealed until that restart:

    sudo hmailserver --create-stored-secrets-key
    sudo hmailserver --export-stored-secrets-key /root/hmailserver-stored-secrets.key
    sudo systemctl restart hmailserver
    

    Keep the exported file with the database backups, apart from them: a database dump restored without it brings back every second factor and [Settings] secret unopenable. Carrying the key to a standby with --import-stored-secrets-key, what a node without it says (HM7495) and --forget-sealed-secrets for a key lost for good are in Hardening a public mail server.

    The unit, and what it lets the service touch

    The packaged unit runs the server with --foreground as hmailserver, and before every start:

    ExecStartPre=-/usr/bin/hmailserver --apply-new-install-defaults --if-marked
    TimeoutStartSec=300
    

    The unit's hardening: ProtectSystem=strict, which leaves /etc read-only to the service; /usr read-only, which with the single capability below is why the service can neither run the package manager nor stop itself; ProtectHome=yes, which hides /home; ReadWritePaths of /var/lib/hmailserver and /var/log/hmailserver; RuntimeDirectory=hmailserver, which is /run/hmailserver; and one capability, CAP_NET_BIND_SERVICE, which binds the mail ports. CAP_NET_ADMIN is deliberately not granted, so the firewall hook behind AutoBanFirewall cannot act until a drop-in (systemctl edit hmailserver) adds it to AmbientCapabilities and CapabilityBoundingSet; sudo -u hmailserver /usr/lib/hmailserver/autoban-hook check says whether it can. A DataFolder outside ReadWritePaths needs a drop-in too, before the first start:

    sudo systemctl edit hmailserver
    # [Service]
    # ReadWritePaths=/srv/mail
    

    A memory-safety fault is recorded in one line of /var/log/hmailserver/crash-oracle.log; core dumps are off by default.

    The first start secures a new installation. On a database --create-database made, the ExecStartPre line gives the server a self-signed certificate, STARTTLS on 25, 587, 110 and 143, and TLS required for authentication on the Internet IP range; mail clients warn about the certificate until ACME (Let's Encrypt certificates) or your own replaces it. It acts only on a database marked within a day of its clock and still as the create script left it; an older mark is kept for a run by hand, sudo -u hmailserver hmailserver --apply-new-install-defaults with the server stopped, and an upgraded or attached database is never changed. The mark, the certificate and the checklist item that follows up are in Hardening a public mail server.

    The root helper hmailserver-update (since 6.3.4)

    A live update is applied outside the server's unit. The server writes a one-file request into /run/hmailserver; hmailserver-update.path, a root path unit the package enables, takes it and runs /usr/lib/hmailserver/hmailserver-update, a shell script readable end to end. The script:

    • checks every line of the request against root's own configuration;
    • verifies the package, and the rollback image, again as root against their Sigstore bundles, with hmailserver --verify-update: the check the server made, made by a process the server could not have influenced;
    • refuses anything that is not a genuine upgrade: the package's own version is compared with what dpkg or rpm says is installed, so a signed but superseded release cannot be put back;
    • stops the unit, installs with apt-get/dpkg or dnf/rpm, starts the unit, and waits for the server to stay up, and for /readyz when the metrics listener is on;
    • reinstalls the previous version if it does not, and writes one line to <DataFolder>/Updates/last-apply.txt, which the server reports at its next check and the Control Deck shows.

    A refused request is explained in journalctl -u hmailserver-update and nowhere else, on purpose.

    sudo /usr/lib/hmailserver/hmailserver-update check
    

    names the installer it would use, whether the path unit is active and whether the running unit has the runtime directory the request needs. The Debian and RPM packages enable and start the path unit; Arch does not enable units from a package, so there sudo systemctl enable --now hmailserver-update.path is yours to run. Nothing happens unless the update check is on and the install is asked for, from the Control Deck or over the API, and only for a release signed by a signer the server trusts, which 6.3.4 is not.

    hmctl and the PowerShell module

    The other command line is hmctl (/usr/bin/hmctl, one Python 3 file), with the HmailServer PowerShell module beside it in the repository. Both speak the REST API, so both administer a Windows or a Linux server, here or on another machine. They cannot turn the REST listener on, set the administrator password, or make or carry the stored-secrets key. They have a topic of their own: hmctl and the PowerShell module.

    Logs and the journal

    The server's own logs are in /var/log/hmailserver. The journal (journalctl -u hmailserver -f) carries the startup line, standard error and the operational events: WindowsEventLogEnabled=1 is a Windows inheritance in name only, and on Linux means syslog. The logrotate rule uses copytruncate, because the server does not reopen its log on a signal.

    Where to read more

    • On the wiki: Installing on Linux, and Command Line for hmctl.
    • CommandLine.md, SecretsAtRest.md, SecureDefaults.md, Profiles.md and MessageStore.md.
    • The documentation page: 35.2 Supported platforms and packages, 35.7 Command-line reference, which lists none of the verbs new in 6.3.4, and 35.8 The systemd service.
    • On this forum: hMailServer on Linux, First install on Linux, Upgrading to 6.3.4 and The Control Deck; Databases on Linux for --create-database and the schema upgrade; the update check and the live update for what the root helper is asked to apply; and message storage for what the store verbs change.
    1 Reply Last reply
    0

    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
    Reply
    • Reply as topic
    Log in to reply
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes


    hMailServer Community

    The community support forum for hMailServer — the free, open-source mail server for Windows and Linux — maintained by Progressive Robot Ltd. The software is AGPL-3.0 and stays that way; this is where it is discussed, debugged and documented.

    The software

    • Documentation
    • Downloads
    • hMailServer 6.3
    • Source on GitLab

    Getting help

    • Forum rules
    • About this forum
    • Support plans
    • Pay monthly support
    • Talk to Progressive Robot

    Legal

    • Privacy policy
    • Terms and conditions
    • Cookie policy

    Progressive Robot Ltd · 220 Chester Business Park, Heronsway, Chester, Cheshire CH4 9GB, United Kingdom · +44 (0)1244 911212 · [email protected] · VAT 506152326

    Powered by NodeBB

    • Login

    • Don't have an account? Register

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Popular
    • Tags
    • Users
    • Groups
    • Documentation
    • Downloads
    • Report a bug
    • GitHub mirror
    • Paid support