67 lines
3.2 KiB
Markdown
67 lines
3.2 KiB
Markdown
# 分身 bunshin
|
|
|
|
A Rust implementation of the [Smol Mail](https://code.randogoth.com/randogoth/smolmail) server: a minimalist, end-to-end encrypted mail protocol over a Noise-secured TCP connection. `bunshin` implements the server side only — receiving, storing and serving sealed mail — not the client.
|
|
|
|
The server never sees plaintext, sender identities or any private key. It learns only which mailbox an envelope is for, its size, and when it arrived.
|
|
|
|
The flake's main purpose is turnkey deployment on a NixOS host: import `nixosModules.default`, point it at a key, and `nixos-rebuild switch`.
|
|
|
|
## Deploying on NixOS
|
|
|
|
Add bunshin as a flake input and import the module:
|
|
|
|
```nix
|
|
{
|
|
inputs.bunshin.url = "https://code.randogoth.com/randogoth/bunshin";
|
|
|
|
outputs = { self, nixpkgs, bunshin, ... }: {
|
|
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
|
|
modules = [
|
|
bunshin.nixosModules.default
|
|
{
|
|
services.bunshin = {
|
|
enable = true;
|
|
keyFile = "/var/lib/bunshin/server.key"; # provisioned out of band, see below
|
|
openFirewall = true;
|
|
inviteTokenFile = "/run/secrets/bunshin-invite"; # or inviteToken directly
|
|
};
|
|
}
|
|
];
|
|
};
|
|
};
|
|
}
|
|
```
|
|
|
|
`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.
|
|
|
|
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`:
|
|
|
|
```
|
|
nix run "https://code.randogoth.com/randogoth/bunshin" -- keygen --key server.key
|
|
```
|
|
|
|
`keygen` writes the server's static X25519 key (used for the Noise handshake, distinct from any user's Ed25519 identity) and prints its public key in base32. Publish that public key through a trusted channel — clients pin it, and a mismatch aborts the handshake.
|
|
|
|
## Building
|
|
|
|
Requires a Rust toolchain (stable, edition 2021) and a C compiler — `rusqlite`'s `bundled` feature compiles SQLite from source rather than linking a system copy, so no separate SQLite install is needed.
|
|
|
|
```
|
|
cargo build --release
|
|
cargo test
|
|
```
|
|
|
|
The binary lands at `target/release/bunshin`. With Nix, skip the toolchain setup entirely: `nix build` produces the same binary at `./result/bin/bunshin`.
|
|
|
|
Running directly, outside the NixOS module:
|
|
|
|
```
|
|
bunshin keygen --key server.key
|
|
bunshin serve --key server.key --db mail.db --host 0.0.0.0 --port 1961
|
|
```
|
|
|
|
`serve` accepts `--max-envelope`, `--quota`, `--requests-quota`, `--retention-days`, `--requests-retention-days`, `--max-tokens`, `--invite-token`, `--rate-connections`, `--rate-sends` and `--rate-tokens` to control size limits, the mailbox's two quota tiers, their retention, the accept-token cap, registration gating and abuse control. Run `bunshin serve --help` for defaults.
|
|
|
|
## Status
|
|
|
|
Implements SPEC.md version 1.1 in full: `AUTH`, `RESOLVE`, `SEND`, `FETCH`, `DELETE` and `REGISTER`, including accept tokens and the main/requests tier split, fetch cursors, 32-byte message ids, `REGISTER` proof of possession, and dual-signed key rotation chains.
|