Install the suite, for real, in containers

The plan now happens. "inbuxa install --local --domain example.test
--install-deps --yes" on a machine with nothing on it ends with a mail
server, a console and a webmail running, an administrator and a first
mailbox created, and the records the domain needs written out.

The sequence is the one ihasmail-oneshot worked out against a running
server, which is why its JMAP client and its Docker handling came across
nearly whole: bring the server up in bootstrap mode with a credential that
lives in an override file for that step only, complete bootstrap, bring the
rest up without it -- so no recovery credential outlives the setup -- exempt
the front ends from the auto-ban, restart for the settings that need it,
create the first account, and write down the password nothing else holds.

New here: three services rather than two. The console is static files that
learn their server's address at start, and the webmail is given the
first-party OAuth client secret that the server is given too.

Twenty checks in the lab, from a bare Debian 13. The two worth having are
the ones that catch an install that looks fine and is not: nothing in the
running server carries a recovery admin any more, and the account the
installer created can sign in to the webmail it installed.

Two bugs the lab caught, both of which would have shipped:

- the private addresses were worked out on a copy of the stack, so the
  server was told the webmail speaks from "", and refused it.
- the console image rewrites index.html when it starts, so a read-only root
  filesystem left it restarting forever. The webmail keeps read_only; the
  console cannot have it until that rewrite moves.
This commit is contained in:
2026-09-22 18:26:31 -07:00
parent cc77f62c01
commit 7141e565ea
12 changed files with 1765 additions and 7 deletions
+18 -4
View File
@@ -29,10 +29,22 @@ This is early. What is built:
anything is put in place. `install --install-deps` does the same as part of
a run. A missing dependency is an offer, not a refusal.
Not built yet: applying the plan, the terminal interface, `join`, `status`,
- **`install --yes`** -- carries the plan out, for container shapes: writes
the deployment, fetches the images, brings the mail server up in bootstrap
mode with a credential that exists only for that step, completes bootstrap,
brings the rest up without it, exempts the front ends from the auto-ban,
creates the first mailbox, writes `credentials.txt` and `dns.zone`, and
then checks that all three answer.
Not built yet: host installs, the terminal interface, `join`, `status`,
`upgrade`, `uninstall`. The design is in the inbuxa specification (§6.1 and
the installer draft); the phases are there too.
inbuxa install --local --domain example.test --install-deps --yes
is the shortest thing that works today: the whole suite on loopback, with no
DNS and no certificates, on a machine that starts with nothing.
## Building and testing
go build ./cmd/inbuxa
@@ -40,9 +52,11 @@ the installer draft); the phases are there too.
The installer writes units, creates users and takes ports 25 and 443, so it
is tested on a throwaway virtual machine rather than on anybody's desk:
e2e/vm/up.sh a Debian 13 machine, in qemu, as you
e2e/vm/run.sh e2e/cases/survey.sh rewind it, then run a case inside
e2e/vm/down.sh remove it
e2e/vm/up.sh a Debian 13 machine, in qemu, as you
e2e/vm/run.sh e2e/cases/survey.sh what it says about a machine
e2e/vm/run.sh e2e/cases/deps.sh the offer, and taking it
e2e/vm/run.sh e2e/cases/install-local.sh a whole suite, and signing in to it
e2e/vm/down.sh remove it
Each case starts from a copy of the machine taken when it was new, so a run
is free to break it and a failure is the installer's rather than the last