Files
inbuxa-server/tools/fork/cutover-rehearsal/README.md
T
jcoffey-dev 966241070e
ci / fork-checks (pull_request) Skipped
ci / build (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 6m29s
Name Coffey Labs LLC as the copyright holder
Coffey Labs is now Coffey Labs LLC, an Arizona limited liability company. Copyright lines and SPDX-FileCopyrightText headers naming Coffey Labs or John Coffey now name Coffey Labs LLC. Upstream copyright notices are unchanged.
2026-10-05 23:33:00 -07:00

2.6 KiB

The synthetic cutover rehearsal

docs/spec/cutover.md as a script, against data this makes up rather than INBUXA's. It rehearses the sequence — stop, copy, start the fork beside it, check, roll back — not the data, which is what the compat tests cover (docs/spec/compat-tests.md).

Nothing here touches INBUXA's production server. Two containers stand in for the two installs, both unprivileged with CAP_NET_BIND_SERVICE so the mail ports are bound the way the systemd unit binds them:

binary stands for
cutover-old target/debug/stalwart the Enterprise install running today
cutover-new target/debug/inbuxa what it is cut over to

Running it

Needs target/debug/stalwart and target/debug/inbuxa, and Docker.

tools/fork/cutover-rehearsal/phase1.py   # build the old install, record before.json
tools/fork/cutover-rehearsal/phase2.py   # the cutover sequence, and its checks
tools/fork/cutover-rehearsal/phase3.py   # the rollback, and the reverse-compat probe

Phase 1 destroys anything from an earlier run, so the three are repeatable from nothing. State lives under target/cutover/; the containers are named cutover-old, cutover-new and cutover-reverse.

What it covers, and what it does not

Covered, and observed rather than assumed:

  • the fork opens and serves a store the previous build wrote;
  • every account signs in with the password it had, over JMAP and over IMAP;
  • mail is byte-for-byte the same set, and an alias still delivers;
  • a tenant administrator sees exactly its own accounts and domains, and still cannot read listeners — the thing tenant_compat could not check, because tenantAdmins was empty on the real run;
  • ports 25, 465 and 993 bound by an unprivileged process;
  • the STALWART_* → INBUXA_* fallback warnings of SPEC.md §2.5;
  • the rollback, timed, including what it leaves behind.

Not covered. The rehearsal is containers, not the host:

  • systemd. inbuxa.service, AmbientCapabilities, and above all systemctl disable stalwart — the step that stops a reboot putting two servers on one set of ports — have no analogue here.
  • ACME and certificate renewal. This runs with requestTlsCertificate: false, so the certificate on 443 and 993 is a self-signed fallback. Renewal remains the open question it was.
  • Load. One message at a time, not INBUXA's traffic.
  • The front ends. INBUXA Admin and ihasmail are not started.
  • INBUXA's own data. That is compat-tests.md, and a rehearsal on a real snapshot is still owed.