feat: serve multiple domains with per-domain keys, ports and databases
This commit is contained in:
parent
931933c423
commit
dfb57b265c
8 changed files with 891 additions and 120 deletions
42
README.md
42
README.md
|
|
@ -34,10 +34,50 @@ Add bunshin as a flake input and import the module:
|
|||
}
|
||||
```
|
||||
|
||||
`services.bunshin` also takes `host`, `port`, `dataDir`, `maxEnvelope`, `quota`, `requestsQuota`, `retentionDays`, `requestsRetentionDays`, `maxTokens`, `rateConnections`, `rateSends` and `rateTokens`; see `flake.nix` for defaults. The module renders a `systemd` unit that runs `bunshin serve` under `DynamicUser`; it does not generate a key.
|
||||
`services.bunshin` also takes `host`, `port`, `dataDir`, `maxEnvelope`, `quota`, `requestsQuota`, `retentionDays`, `requestsRetentionDays`, `maxTokens`, `rateConnections`, `rateSends`, `rateTokens` and `domains`; see `flake.nix` for defaults. The module renders a `systemd` unit that runs `bunshin serve` under `DynamicUser`; it does not generate a key.
|
||||
|
||||
For the RNS carrier, build `packages.rns`, set `services.bunshin.package` to it, and enable `services.bunshin.rns` with its `keyFile`; see [RNS.md](RNS.md) for the protocol and the remaining options.
|
||||
|
||||
## Multiple domains
|
||||
|
||||
One process can serve several logical servers, each with its own static key, port and mailbox database. bunshin routes by port — the wire protocol has no domain field, and each domain's clients simply pin `user@host → host:port, public key`. How a `user@domain` address resolves to that `host:port` (published addresses, DNS SRV records, a proxy) is outside the server.
|
||||
|
||||
The agreed discovery convention is a DNS SRV record: `_smolmail._tcp.<domain>. SRV 0 1 <port> <host>`, lowest priority wins, and no record falls back to the default port 1961. SRV is discovery only — a lying record lands the client on a server with the wrong static key and the handshake aborts, so the pin stays out of band. Client-side only: `fumi` implements the lookup (rev `1468f3c`), pinning by `host:port` with the default port inheriting the bare-host pin and other ports trust-on-first-use; bunshin serves ports and pins keys, and needs nothing for it.
|
||||
|
||||
`serve --config <file>` takes a TOML file: one `[defaults]` table inherited by every `[domains.<name>]` table (names are 1-63 bytes of `[a-z0-9._-]`). Per domain, `key` and `port` are required; `db` defaults to `mail-<name>.db`, and any of the other settings can be overridden per domain:
|
||||
|
||||
```toml
|
||||
[defaults]
|
||||
host = "127.0.0.1"
|
||||
quota = 67108864
|
||||
|
||||
[domains.example_org]
|
||||
key = "/var/lib/bunshin/example_org.key"
|
||||
port = 11961
|
||||
|
||||
[domains.example_net]
|
||||
key = "/var/lib/bunshin/example_net.key"
|
||||
port = 11962
|
||||
invite_token_file = "/run/secrets/example_net-invite"
|
||||
```
|
||||
|
||||
Every knob settable on the command line is settable in either table; unknown settings are rejected, not silently defaulted. `--config` cannot be combined with the single-domain flags or the `--rns-*` flags — the RNS carrier is single-domain, so it stays on the legacy flags. All keys are read and all ports bound before any domain serves, so a missing key or a taken port fails the process at startup.
|
||||
|
||||
On NixOS, set `services.bunshin.domains` instead; the module renders the TOML, gives each domain a database under `dataDir`, opens each domain's port with `openFirewall`, and loads per-domain invite token files via `LoadCredential`. The existing flat options keep serving the single-domain case unchanged.
|
||||
|
||||
```nix
|
||||
services.bunshin = {
|
||||
enable = true;
|
||||
domains = {
|
||||
example_org.keyFile = "/var/lib/bunshin/example_org.key";
|
||||
example_org.port = 11961;
|
||||
example_net.keyFile = "/var/lib/bunshin/example_net.key";
|
||||
example_net.port = 11962;
|
||||
example_net.inviteTokenFile = "/run/keys/example_net-invite";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Before the first deploy, generate the server's static key once (from a dev shell or `nix run`) and place it at the configured `keyFile`:
|
||||
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue