Relocating an installation to another drive, and moving or renaming a mailbox
-
Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) bears on relocating a Windows installation to another drive.
hMailServer.exe /ProtectFolders, which setup runs at every installation and upgrade, now hardens the program folder,BinandControlPanel: where hMailServer was installed in a folder that took its permissions from the root of a drive, any account that could sign in to the computer could replace the programs the service runs (CVE-2026-107571); the default folder under Program Files was never affected. The procedure below copies the tree and re-registers it without running setup, and a folder below a drive's root takes the permissions the root hands down, so an installation relocated there is hardened by the upgrade to 6.3.7, or on 6.3.7 by runninghMailServer.exe /ProtectFoldersas an administrator, not by the move (on 6.3.6 or earlier follow the icacls steps inServiceAccount.md, since those versions' /ProtectFolders leaves the three program folders as they are); before upgrading an installation at a drive's root, follow the steps "Before upgrading an installation at a drive's root" inServiceAccount.md. Where accounts that are not administrators could sign in to the computer while the installation was in such a folder, the release says to reinstall the programs into a new folder that only the administrators may change, not over the installation, with setup given the new folder by/DIR=: over an installation setup installs into the folder it finds, and a 32-bit installation's uninstall entry overrides/DIR=until it is taken away, which the "re-run the installer" repair below meets. See the 6.3.7 announcement. hMailServer 6.3.8 (2 November 2026) has setup make or harden the program folder,BinandControlPanelbefore it copies a file or runs a program of the installation. One of them that another account could change, as a folder below a drive's root can be, setup hardens and then refuses, with exit code 7, until Windows has restarted; and a folder or a link on the way to them, or a program, library, script or settings file in them, that another account than SYSTEM, the Administrators and TrustedInstaller controls, it refuses with exit code 7, naming theicaclsthat deals with it and a restart of Windows before setup runs again. On Windows 6.3.8 may also refuse, with HM7534 or HM7536,TlsCaFile,PostgreSQLSslRootCert, a TLS certificate or private key file,OAuth2PublicKeyFileorAcmeCertificateDirectorywhere its path holds characters outside ASCII, so give the new root, and the folders above it, an ASCII name. See the 6.3.8 announcement.This guide covers two different moves. The first is relocating a configured installation to another directory or drive on the same machine, for example from
C:\Program Files (x86)\hMailServertoC:\Program Files\hMailServer. The second is renaming a mailbox or moving it to another domain, which is an operation of its own since 6.3.4. Moving to new hardware is a third thing, and Moving to new hardware, and why Windows to Linux is a rebuild covers it. The one thing to know first: relocating is not one change. The installation path is recorded in the registry, in the service, in the COM registration, inhMailServer.iniand in a handful of database columns, and since 6.3.4 a[Settings]path edited in the file is ignored in favour of the value stored in the database.The relocation runbook is written in Windows terms: the registry, the service and the COM registration. The documents used here give no separate procedure for a Linux installation. Installing somewhere new is a different, solved problem:
/DIR="<path>"on the installer puts a fresh installation wherever you want.The good news first
The mail store itself is already relocatable. Message rows hold a bare
{guid}.emlwith no directory, and the path is rebuilt at every read against the data directory. Moving the data directory and pointingDataFolderat its new home moves every message with it. The exception is a database that predates hMailServer 5.4, where the column can hold a full path.Before you touch anything
- Take a backup and verify it restores (Backup and restore). Everything below is reversible only while the old tree and a good backup both exist.
- Ask the server whether its message rows are relative. In the Control Panel, Monitoring & troubleshooting → Diagnostics → Test message file locations. If it reports
ERROR: Full paths are stored in the database, the move is still possible, but converting the paths becomes mandatory rather than optional. - Write down what you are about to strand. The same Diagnostics page has an Installation paths section that lists the registry root, every
[Directories]key and every path-shaped setting the running server holds, with the ones that do not exist marked. It changes nothing.
The inventory
Where What Repaired by Bin\hMailServer.ini,[Directories]ProgramFolder,DataFolder,DatabaseFolder,LogFolder,TempFolder,EventFolderEditing the file Bin\hMailServer.ini,[Database]PostgreSQLSslRootCertandTlsCaFileEditing the file. Leave the connection keys alone: they name a server, not a path The settings store ( hm_inisettings)ArchiveDir,AcmeCertificateDirectory,OAuth2PublicKeyFile,UpdateTrustRootsFile,UpdateLogPublicKeyFile, and the certificate and private key files of the REST API, metrics and web services listenersStoring the new value, not editing the file (since 6.3.4) Registry, HKLM\SOFTWARE\hMailServerin the 32-bit viewInstallLocationBy hand Registry: the service's ImagePath,LocalServer32(79 keys),InprocServer32(15), the TypeLib valueshMailServer.exe /RegisterRegistry, HKLM\...\Uninstall\hMailServer_is1InstallLocation,UninstallString,DisplayIconNothing; re-run the installer The database Certificate and key files, DKIM key files, the client-certificate CA bundle, backupdestination, the ClamWin and custom scanner paths, rule actionsEach on its own page What breaks when a key is left behind. With a stale
DataFolderthe store appears empty. With a staleLogFolderlogs are written to the old tree, silently. With a staleEventFolderevent scripts are not found and events stop running.The 32-bit view is not optional. The server reads
InstallLocationthroughKEY_WOW64_32KEY, and the installer writes it there. Writing the 64-bit view changes nothing and looks like it worked.The procedure
- Stop the service, and confirm it is stopped. Nothing here may run against a live server.
- Copy the tree. Copy, do not move: the old tree is the rollback. Include
Bin\hMailServerApiKeys.iniif it exists, since the REST API key store lives there and no installer manifest mentions it. Grant the service account access to the new tree as 6.3.8's RelocatingAnInstallation.md does: a copy takes the permissions of the folder it lands in (under Program Files every user's Read on the newData,Logs,Temp,Database,EventsandhMailServer.INI) and not the old tree's entries forNT SERVICE\hMailServer, so the document makes the new root with the permissions setup gives a program folder before the copy, runshMailServer.exe /ProtectFoldersfrom the newBinafter step 5's/Register, and grants a service that runs as anything but LocalSystem its folders again with/GrantServiceAccess. A server that cannot write its log directory starts and then says nothing. - Rewrite the file keys in
<new root>\Bin\hMailServer.iniwhose value was under the old root: the[Directories]folders, and[Database]PostgreSQLSslRootCertandTlsCaFile, the second named beside the first by 6.3.8's document, since withTlsMode=verify-fulla CA file left in the old tree stops the server reaching its database once that tree is deleted (HM7531). Nothing else, and not a folder that was outside the old tree and has not moved: aDataFolderpointed at an empty directory makes the store appear empty. - Repoint the registry root, from an elevated prompt:
reg add "HKLM\SOFTWARE\hMailServer" /v InstallLocation /t REG_SZ /d "<new root>" /reg:32 /f./reg:32is the whole of the point. - Re-register the server, from an elevated prompt, from the new
Bin:hMailServer.exe /Register. It registers the path of the executable that runs it. - Start it, and check what it read. Read the application log, and since 6.3.4 the ERROR log too. Confirm that the Diagnostics page's Installation paths shows the new paths (6.3.8's document names it; the Control Panel has no Settings → Directories page), that your domains are listed, and that the log file you are reading is under the new log directory.
- Convert full message paths, only if the diagnostic found any: run the Data Directory Synchronizer, in its import mode, on the old installation before step 2 copies anything, as step 0 of 6.3.8's RelocatingAnInstallation.md has it, not against the new data directory after the move: it converts only a row whose full path is where the file is found, so after the move it would import every such message a second time, and its other mode would delete the copies. A hand-written
UPDATE hm_messages SET ...is not a supported converter. - Store the
[Settings]paths and fix the database-borne paths (both below). - Verify before deleting anything: send and receive a message; complete a TLS handshake on every port that has a certificate; run a backup to completion; run an event script, if you use them; check the log directory is being written.
- Keep the old tree, unreachable by the service, for at least one full backup cycle. Do not make it unreachable until the
[Settings]paths are stored and a reinitialise has picked up the new certificate and ACME paths.
The failure this prevents. A server whose anchors are stale reports
Runningand serves an empty configuration. That failure is silent.The
[Settings]paths: 6.3.3 and earlier, and since 6.3.4On 6.3.3 and earlier these are
[Settings]keys ofhMailServer.inilike any other, and editing the file moves them. Since 6.3.4 it does not: the stored value is used, the edit is named in the error log asHM5804, and, where the service can write the file, the line is put back to the old path. RelocatingAnInstallation.md and the wiki page between them give three ways to store the new values. The first is the document's own, and the one to use:When How Where it is described After the moved server is running In the Control Panel under Settings, with Settings.SetIniSettingover COM,PUT /api/v1/settings/ini/{name}, orhmctl ini set <name> <value>RelocatingAnInstallation.md, step 9, and the wiki Before stopping the old server The same four ways, as the last thing before the service is stopped. A save applies ArchiveDir,OAuth2PublicKeyFile,UpdateTrustRootsFileandUpdateLogPublicKeyFileat once, not at the next start as the wiki page has it, so the running old server turns to a tree not yet copied: archiving stops, and token validation and update verification refuse. The database then holds the new paths, so going back to the old tree means storing the old values againThe wiki, corrected by SettingsApply.md At the first start, if the service is already stopped A [SettingsOverride]section in the newhMailServer.ini, named in the error log as HM5807; then store the same values and remove the section before the next restartThe wiki A save applies every one of these paths at once except the listeners' certificate paths and the ACME certificate directory, which are bound when the servers start and wait for a reinitialise (Apply now, or
POST /api/v1/server/reinitialize). Until then the server runs on the old paths, which still resolve because the tree was copied rather than moved.PasswordPepperis the exception to all of this: it lives in the file only, is not a path, and comes across with the copied file.The database-borne paths
- SSL certificates. Since 6.3.7 the Control Panel's SSL certificates page has Edit…, which changes a certificate's name and files and keeps its id, so every port that presents it keeps it and reads the new files at the next reinitialise; deleting a certificate and adding it again, as the document had it until 6.3.8, leaves each port that presented it with none, and such a port does not start (HM5113). It can also be set over COM.
- DKIM keys. Domain → DKIM, the primary and, if used, the secondary. A domain whose key rotation manages its keys refuses that edit.
- Client-certificate CA bundle, per port. A port set to require a client certificate refuses every client when its bundle cannot be loaded.
- Archive index.
hm_archiveindex.archivepathis matched on the exact string by retention, legal hold and the address eraser. Do not bulk-rewrite it. If the archive directory moved, move the archive back, or accept that the rows written before the move point at the old location; there is no supported converter for this column.
What stays broken, and why
- Add/Remove Programs still points at the old
unins000.exe. Do not editunins000.dat. The supported repair is to re-run the installer at the new root. - Start-menu shortcuts hold absolute targets and nothing repairs them.
- Message content. The old path appears inside messages the server itself wrote, such as a delivery report. Never rewrite message content.
Renaming a mailbox, or moving it to another domain
New in 6.3.4 (schema 6056, whose table
hm_mailboxmovesis the move's journal).new_addresscarries the domain, so renaming and moving are the same operation:[email protected]to[email protected]is a rename,[email protected]to[email protected]is a move. A move keeps the account's row, so everything keyed on the account id follows without being touched: rules, folders with their subscriptions and access-control entries, application passwords, the second factor, contacts, calendars and the role assignment. Copying the mail into a second account loses all of it.Interface How Control Deck The Move or rename card in the account editor hmctlhmctl mailbox status [email protected], thenhmctl mailbox move [email protected] [email protected]REST POST /api/v1/accounts/ann%40example.com/movewith{"new_address": "[email protected]", "keep_alias": true};GETon the same path says whether anything holds the mailboxPowerShell Move-HmMailbox -Address [email protected] -NewAddress [email protected]Control Panel (Windows) Move or rename… on the account's General tab COM (Windows) Account.MoveTo(NewAddress, KeepOldAddressAsAlias)orUtilities.MoveMailbox(Address, NewAddress, KeepOldAddressAsAlias)The old address is kept as an alias by default, pointing at the new address. Turn it off (
keep_aliasfalse,--drop-alias) only when the address is to stop working: mail to it is then refused atRCPT TO.What moves: the message store directory
<data>/<domain>/<local part>; the Sieve tree; aliases in any domain that point at the account; distribution list memberships; recipients of mail still in the delivery queue; and quarantined mail, up to a ceiling of 200,000 rows.What does not move, on purpose. The archive and the message trace stay under the old address, as a record of the past. Erasure works by address, so erasing the new address will not reach the archive written under the old one: erase both (Compliance: personal data and erasure). The domains a role reaches are not rewritten either, so check a role after a cross-domain move (Administrator roles end to end).
What is refused, before the first byte is moved:
- a domain this server does not hold, or one that is not active;
- a destination domain at its maximum number of accounts, or that would exceed its maximum total size;
- an account, an alias or a distribution list already at the new address;
- a mailbox encrypted at rest moving to another domain (
409); a rename inside the domain is not refused; - an installation whose message file names are still full paths;
- a credential that may not administer accounts in both domains;
- a mailbox in use.
In use means a POP3 session, or an IMAP session with one of the account's folders selected. What is not counted: an IMAP session that has selected nothing, a webmail request in flight, a ManageSieve session and an SMTP delivery to the mailbox in flight. A message that arrives during the copy is written under the old directory, and the old directory is swept once afterwards; anything that could not be carried is
HM6948. That is why a move of a large busy mailbox belongs out of hours.When a move fails or is interrupted
There is no transaction across a filesystem and four database backends, so the order is chosen to make each step undoable: the store, then the account row, then the references, then the alias. A journal row is opened before the first step and closed after the last, and an interrupted move is said once per start as
HM6947in the application log, naming both addresses and the stage it stopped at.Stage What it means startedNothing has been changed moving the storeThe copy was under way; look at both directories. The database has not been touched store movedThe directories are at the new address. While the account row says the old one, the account authenticates and its mail is unreadable account writtenThe store and the account row agree; the references have not all been rewritten references rewrittenEverything but the alias completeThe move finished rolled backA step failed and everything before it was put back rollback failedSomething could not be put back; HM6940is in the application logTo finish a move interrupted at
moving the storeorstore moved, ask for the move again, naming the address the directories now have. Read the journal withhmctl mailbox statusorGET /api/v1/accounts/<address>/move. The journal is not in the backup.Code Meaning HM6941The move succeeded but the alias for the old address could not be created HM6942Aliases pointing at the account could not be re-pointed HM6943Distribution list memberships could not be moved HM6944Messages in the delivery queue still name the old address HM6945Quarantined messages still name the old address HM6946The move could not be journalled. It still happened, and is on the audit trail Who may.
manage_accounts, in both domains. The server administrator and a domain administrator of both domains have it; the help-desk role and the auditor do not.view_accountsis enough to read the journal. A move is one entry on the audit trail: object typeaccount, actionmoved.What it does not do
- The relocation runbook does not repair the uninstall entry or the shortcuts, and it has no converter for the archive index.
- A mailbox move does not wait for a delivery in flight; nothing in the server records one.
- Setting
Account.Addressand saving goes through the same implementation, but leaves no alias, does not refuse while the mailbox is in use, and cannot cross domains. - A domain rename (
Domain.NameandSave()) is a different thing again, and keeps the path it has always taken.
Where to read more
- Wiki: Relocating an Installation.
- Documents: RelocatingAnInstallation.md and MailboxMove.md.
- The public documentation: 33.1, the installation on disk.
- On this forum: Moving to new hardware, and why Windows to Linux is a rebuild, Upgrading to 6.3.4, and how the settings store works and when a save takes effect in Settings: what is not stock, when a save takes effect, and the three levels.
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