feat: add container deploy path (Containerfile, self-provisioning entrypoint, Forgejo registry push)
This commit is contained in:
parent
fd847d035f
commit
50e5e444bc
5 changed files with 100 additions and 3 deletions
13
.dockerignore
Normal file
13
.dockerignore
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
/target
|
||||||
|
/result
|
||||||
|
/result-*
|
||||||
|
/cache
|
||||||
|
/config
|
||||||
|
/fumi.rns
|
||||||
|
.git
|
||||||
|
.jj
|
||||||
|
.env
|
||||||
|
*.db
|
||||||
|
*.db-wal
|
||||||
|
*.db-shm
|
||||||
|
server.key
|
||||||
22
Containerfile
Normal file
22
Containerfile
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Default (non-rns) build only: microReticulum's cmake/C++ build isn't set
|
||||||
|
# up for the musl toolchain alpine gives us, mirroring packages.static in
|
||||||
|
# flake.nix. Use the Nix flake if you need the rns feature.
|
||||||
|
FROM rust:1-alpine AS builder
|
||||||
|
RUN apk add --no-cache musl-dev gcc
|
||||||
|
WORKDIR /usr/src/bunshin
|
||||||
|
COPY Cargo.toml Cargo.lock build.rs ./
|
||||||
|
COPY src ./src
|
||||||
|
RUN cargo build --release --locked
|
||||||
|
|
||||||
|
FROM alpine:3.20
|
||||||
|
RUN apk add --no-cache ca-certificates \
|
||||||
|
&& adduser -D -h /data -u 10000 bunshin
|
||||||
|
COPY --from=builder /usr/src/bunshin/target/release/bunshin /usr/local/bin/bunshin
|
||||||
|
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||||
|
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||||
|
USER bunshin
|
||||||
|
WORKDIR /data
|
||||||
|
VOLUME /data
|
||||||
|
EXPOSE 1961/tcp
|
||||||
|
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||||
|
CMD ["serve", "--key", "/data/server.key", "--db", "/data/mail.db", "--host", "0.0.0.0", "--port", "1961"]
|
||||||
24
README.md
24
README.md
|
|
@ -6,11 +6,29 @@ A Rust implementation of the [Smol Mail](https://code.randogoth.com/randogoth/sm
|
||||||
|
|
||||||
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 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`.
|
The quickest way to run it is the container image below. For a NixOS host, the flake also provides turnkey deployment as a special case: import `nixosModules.default`, point it at a key, and `nixos-rebuild switch`.
|
||||||
|
|
||||||
|
## Deploying with a container
|
||||||
|
|
||||||
|
Pull the published image and bring up a server in one command:
|
||||||
|
|
||||||
|
```
|
||||||
|
podman run -d --name bunshin -p 1961:1961 -v bunshin-data:/data code.randogoth.com/randogoth/bunshin
|
||||||
|
```
|
||||||
|
|
||||||
|
`docker` works the same way — the image is a standard OCI image either way. The entrypoint generates `/data/server.key` on first run if it's missing, then runs `serve` against `/data/server.key` and `/data/mail.db` on `0.0.0.0:1961`; `podman logs bunshin` prints the generated public key to publish to clients. A key already in the volume is left alone, so restarts and upgrades keep the same identity.
|
||||||
|
|
||||||
|
Pass your own arguments to run `keygen` or a customized `serve` instead of the default — they take the same flags as a bare-metal install, e.g. `podman run --rm -v bunshin-data:/data code.randogoth.com/randogoth/bunshin keygen --key /data/server.key --force`.
|
||||||
|
|
||||||
|
To build the image locally instead of pulling (same non-`rns` build as the release image, see the `Containerfile` header comment):
|
||||||
|
|
||||||
|
```
|
||||||
|
podman build -t bunshin -f Containerfile .
|
||||||
|
```
|
||||||
|
|
||||||
## Deploying on NixOS
|
## Deploying on NixOS
|
||||||
|
|
||||||
Add bunshin as a flake input and import the module:
|
For a NixOS host that already manages the rest of its config with Nix, import the module instead of running the container:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
{
|
{
|
||||||
|
|
@ -34,7 +52,7 @@ 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`, `rateTokens`, `maxConnections` 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.
|
`services.bunshin` also takes `host`, `port`, `dataDir`, `maxEnvelope`, `quota`, `requestsQuota`, `retentionDays`, `requestsRetentionDays`, `maxTokens`, `rateConnections`, `rateSends`, `rateTokens`, `maxConnections` and `domains`; see `flake.nix` for defaults. The module renders a `systemd` unit that runs `bunshin serve` under `DynamicUser`; unlike the container entrypoint, 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.
|
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.
|
||||||
|
|
||||||
|
|
|
||||||
12
docker-entrypoint.sh
Normal file
12
docker-entrypoint.sh
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Generates the server key on first run so a bare `docker run` against an
|
||||||
|
# empty volume works; a key already at BUNSHIN_KEY is left untouched.
|
||||||
|
set -e
|
||||||
|
|
||||||
|
: "${BUNSHIN_KEY:=/data/server.key}"
|
||||||
|
|
||||||
|
if [ "$1" = "serve" ] && [ ! -f "$BUNSHIN_KEY" ]; then
|
||||||
|
bunshin keygen --key "$BUNSHIN_KEY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec bunshin "$@"
|
||||||
32
flake.nix
32
flake.nix
|
|
@ -156,6 +156,38 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Builds the Containerfile image (same non-rns build the release
|
||||||
|
# binary is, see its header comment) and pushes it to this repo's
|
||||||
|
# Forgejo container registry, tagged by short commit hash and
|
||||||
|
# `latest`. Needs FORGEJO_TOKEN (a token with write:package scope)
|
||||||
|
# in the environment; run from a checkout so `git rev-parse` and
|
||||||
|
# the Containerfile build context resolve to the right place.
|
||||||
|
apps.release-container = flake-utils.lib.mkApp {
|
||||||
|
drv = pkgs.writeShellApplication {
|
||||||
|
name = "bunshin-release-container";
|
||||||
|
runtimeInputs = [ pkgs.podman pkgs.git ];
|
||||||
|
text = ''
|
||||||
|
if [ -f .env ]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. ./.env
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
: "''${FORGEJO_TOKEN:?set FORGEJO_TOKEN (env or .env) to a Forgejo token with write:package scope}"
|
||||||
|
|
||||||
|
rev=$(git rev-parse --short HEAD)
|
||||||
|
registry="code.randogoth.com/randogoth/bunshin"
|
||||||
|
|
||||||
|
echo "''${FORGEJO_TOKEN}" | podman login code.randogoth.com -u randogoth --password-stdin
|
||||||
|
podman build -f Containerfile -t "$registry:$rev" -t "$registry:latest" .
|
||||||
|
podman push "$registry:$rev"
|
||||||
|
podman push "$registry:latest"
|
||||||
|
|
||||||
|
echo "pushed: https://code.randogoth.com/randogoth/-/packages/container/bunshin"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
packages = with pkgs; [ cargo rustc rustfmt clippy pkg-config gcc sqlite cmake ninja ];
|
packages = with pkgs; [ cargo rustc rustfmt clippy pkg-config gcc sqlite cmake ninja ];
|
||||||
env = rnsSourceEnv;
|
env = rnsSourceEnv;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue