Choose the Stalwart by the domain somebody signs in with
One ihasmail in front of several Stalwarts, from #238. STALWART_URL stays required and stays the default, so an installation that sets nothing behaves exactly as it always has -- the mapping only adds domains that go elsewhere. An unlisted domain goes to the default. So does a bare username, which Stalwart accepts and which has no domain to map at all. A listed domain never falls back. If its server is unreachable that sign-in fails rather than retrying against the default, because falling back would authenticate somebody against a server their domain was deliberately routed away from -- and if the same account name existed there, they would land in another tenant's mailbox. The fallback is a decision about unmapped domains, taken before any network call, not a recovery path. Smaller than it sounds because only four places read config.stalwartUrl, all in upstream.ts. The upstream session now records which server issued it, since the relative URLs inside it only mean anything against that server, and every route already holding a session gets the right upstream without a second lookup. The client is untouched: it talks to one proxy and never learns there is more than one server behind it, which is exactly why this is small and several-servers-at-once is not. The upstream is derived from the username rather than stored on the session, so a mapping change takes effect on restart instead of being frozen into sessions that outlive it. Validated at boot the way the settings policy is: malformed JSON, a duplicate domain once normalised, a missing file or a value that is not an http(s) URL all stop the server. Domains are lower-cased and stripped of a trailing dot, because that is how one arrives off a username and comparing them any other way means a mapping that silently never matches. The servers themselves are not contacted -- a mapping is a routing table, not a health check, and one customer's outage must not stop ihasmail starting for the other four. Eight tests on the routing, two on the shipped example, and the four refusals checked by hand against a real config load.
This commit is contained in:
@@ -117,6 +117,47 @@ nowhere to live across a restart. Removing it means moving the session upstream
|
||||
into a token Stalwart itself issues and can revoke, which is what the OAuth work
|
||||
in [ROADMAP.md](ROADMAP.md) is for.
|
||||
|
||||
### Several Stalwart servers
|
||||
|
||||
One ihasmail can front more than one Stalwart, choosing by the domain somebody
|
||||
signs in with. **`STALWART_URL` stays required and stays the default**, so an
|
||||
installation that sets nothing else behaves exactly as it always has.
|
||||
|
||||
```bash
|
||||
-e STALWART_SERVERS_FILE=/etc/ihasmail/servers.json \
|
||||
-v /srv/ihasmail/servers.json:/etc/ihasmail/servers.json:ro
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"example.com": "https://mail.example.com",
|
||||
"customer-b.test": "https://jmap.customer-b.test"
|
||||
}
|
||||
```
|
||||
|
||||
[`stalwart-servers.example.json`](stalwart-servers.example.json) is that file
|
||||
with the rules written in it.
|
||||
|
||||
A domain nobody listed — and a bare username, which Stalwart accepts and which
|
||||
has no domain at all — goes to `STALWART_URL`. **A listed domain never falls
|
||||
back.** If its server is unreachable that sign-in fails rather than retrying
|
||||
against the default, because falling back would authenticate somebody against a
|
||||
server their domain was deliberately routed away from; if the same account name
|
||||
existed there they would land in another tenant's mailbox.
|
||||
|
||||
Read once at startup, so editing it means restarting the container. Malformed
|
||||
JSON, a duplicate domain once lower-cased, or a value that is not an `http(s)`
|
||||
URL stops the server rather than failing quietly at somebody's sign-in. The
|
||||
servers themselves are not contacted at boot — a mapping is a routing table,
|
||||
not a health check, and one customer's outage must not stop ihasmail starting
|
||||
for everybody else.
|
||||
|
||||
This is one server per *person*, chosen at sign-in. Several servers at once for
|
||||
one person, with unified or cross-account views, is not supported: JMAP account
|
||||
ids are only unique within a server, so it would mean namespacing ids through
|
||||
the proxy. Reading somebody else's mail, calendars or files on the *same* server
|
||||
already works through JMAP sharing.
|
||||
|
||||
### Settings the installation decides
|
||||
|
||||
A deployment can seed and lock user settings, which is what a school wanting
|
||||
|
||||
Reference in New Issue
Block a user