docs
Try the demo Get started
Esc
↑↓ moveEnter openEsc close

Install it · 5 of 8

Coming from Stalwart

Bring a Stalwart 0.16 server over to inbuxa: export its store, import it into a new one, keep the old install standing, and roll back if a check fails.

6 min read

On this page

inbuxa started as a fork of Stalwart, but from 27.1 its store's layout is its own. Stalwart is a migration source like any other mail server. What inbuxa keeps is the ability to read one Stalwart format in full: the one Stalwart 0.16.27 exports.

So moving over is an export and an import. Stalwart writes its store out with its own binary, and inbuxa reads that into a new, empty store. The old server isn't touched, so it stays standing as the rollback.

This page describes 27.1

27.1 ships in January 2027, and its release candidates are out now. The route below is checked against every candidate with a real 0.16.27 store before it's tagged. See Versions and upgrades.

Stalwart 0.16.27 only

An older 0.16 server upgrades to 0.16.27 with Stalwart first, and is checked working, before any of this. stalwart-migrator does that upgrade. Stalwart 1.0 and later changed their own layout and can't be read this way. An importer for them is planned for inbuxa-migrate.

To move only some accounts, or into an inbuxa server that's already running, use inbuxa-migrate instead.

What comes across

Everything that defines the server lives in its store, so the import carries all of it:

  • accounts, with their passwords, descriptions, aliases, quotas, groups and roles, custom roles included;
  • groups and their shared mailboxes, and mailboxes shared between accounts;
  • tenants, their domains and their accounts;
  • domains and their DKIM keys;
  • mail, with its folders, flags, threads and attachments;
  • calendars and events, and address books and contacts;
  • Sieve scripts and the vacation response;
  • the server's settings, the queue, and the reports and tasks in flight.

Nobody is asked to change a password. The few things that change are below.

What changes

  • Search is rebuilt. The export doesn't carry the search index. Each account is reindexed during the first five minutes after start, so older mail can be missing from search results until then. New mail is indexed as it arrives.
  • JMAP takes tokens, not passwords. A JMAP client that signs in with a password must move to OAuth. IMAP, POP3, SMTP, CalDAV and CardDAV keep passwords. Setting INBUXA_HTTP_BASIC_AUTH=all allows passwords on JMAP again while clients move.
  • Stalwart's own web interface is switched off. Its record is kept, and the server's log says so. To keep serving it at /admin, switch the application back on in the console, and it stays on. Use the console instead if you can.
  • Roles gain permissions. inbuxa adds its Compliance Officer role. The built-in administrator roles gain inbuxa's own permissions, for account locks, the audit log, legal holds and the like. Nothing is taken away.
  • Some names change. Environment variables are INBUXA_*, and a STALWART_* one stops the server at startup, naming the variable to rename. SQL stores default to a database and user named inbuxa, so set database and authUsername if yours relied on the old default.
  • JMAP clients that manage the server ask for urn:inbuxa:jmap:registry instead of urn:stalwart:jmap. Standard JMAP mail, contacts and calendars are unaffected. stalwart-cli can't manage an inbuxa server: use inbuxa-cli or the console.
  • CalDAV and CardDAV clients resync once: their sync tokens were issued under the old name.

Sieve scripts that require "vnd.stalwart.expressions" or "vnd.stalwart.while" keep running, and can still be edited and saved.

The shape of it

Side by side. The old install is stopped but left standing, and inbuxa goes in at its own path with a new store. Stalwart's store is read by Stalwart's own export, and never written to.

# 1. With Stalwart stopped, export with its own binary.
stalwart --config <stalwart's config.json> --export /srv/export

# 2. Import into the new, empty inbuxa store its config names.
inbuxa --config /etc/inbuxa/config.json --import /srv/export

An export goes from any backend to any other, so a RocksDB store can become a PostgreSQL one, or the other way round.

Paths the old install remembers

The import keeps every setting as it was, and some settings name a place on disk. After the import those still point at the old install's directories, such as /var/lib/stalwart in Stalwart's image:

  • Settings › Storage: a Blob Store kept on the file system, and any other store that is a RocksDB or SQLite file.
  • Settings › Monitoring › Tracers: the directory log files go to.
  • Any secret or certificate the server reads from a file.

Note each one during preflight, while the old install is still running. Then, after the import and before the first real start:

  1. Start the server once in recovery mode. It opens the store but none of its listeners and none of its log files, so no mail moves and nothing is written to the old paths.
  2. In the console, change each path to its new place, then restart the server normally.

Don't start on the old paths while the old install is on the same machine

A blob store or a log directory that still names the old install's directory is written to, and that is the install you are keeping for a rollback.

The phases, and which ones cost you

  1. Preflight, with nothing stopped: the source is 0.16.27 and working, disk for the export and a second store, the target path, the ports, the front ends' plan, and a snapshot you confirm exists. Anything wrong here costs no downtime at all. Read the existing unit (systemctl cat) before touching anything. Our own move found a network namespace nothing in the plan knew about, and missing it would have cost outbound mail.
  2. Configure inbuxa and its unit, with its config.json naming a new, empty store. Nothing is running yet, so this costs no downtime either.
  3. Stop the mail server, then the webmail. Disable the unit as well as stopping it, so a reboot can't put two servers on one set of ports.
  4. Export the store, then import it into the new one.
  5. Move the paths the old install remembers, in recovery mode.
  6. Start it, and wait for it to answer.
  7. Front ends: inbuxa Admin and the webmail, installed as on the console and the webmail pages. Their OAuth clients came across in the import, so reuse them rather than registering new ones.
  8. Verify. This is a gate, not a formality.

Downtime is phases 3 to 8. The export and import are inside it, and their time grows with the amount of mail. Try both on a copy of the source first, with the old server still running, and you'll know how long the real window will be.

Verification, before mail flows again

Work down this list yourself:

  • it answers on every listener the source had, with the certificate the source was serving;
  • an account signs in over IMAP and both front ends, with the password it already had;
  • a message arrives from outside, and one leaves;
  • aliases still receive, and Sieve filters still file mail;
  • a tenant administrator sees its own accounts and domains, and no others;
  • the queue drains, and the task queue gains no permanent failures;
  • search finds older mail once the first five minutes are up;
  • nothing but inbuxa is listening on those ports.

A failed check is a failed migration. Roll back rather than leaving yourself a half-migrated server to reason about at 2am. That is what keeping the old install standing is for, and why it is stopped but not removed.

Rolling back

The old store was never written to, so rolling back is starting the old install again. Mail that arrived at inbuxa in between stays in the new store, so roll back early rather than late.

Keep the old install until you have watched real mail flow through the new one for longer than you think you need to.

Afterwards

A migration that passes its own verification has proved the server works. Pointing a stock, unmodified ihasmail at the migrated server proves something else: that a client which knows nothing about inbuxa still gets a working mailbox, which is what keeps the protocol surface honest.


Stalwart is a trademark of Stalwart Labs LLC. inbuxa is not affiliated with or endorsed by Stalwart Labs.