Cargo workspace with the server-side pieces of Noisebell. Runs on any Linux box.
| Service | Port | What it does |
|---|---|---|
cache-service/ | 3000 | Polls the Pi, stores the latest state in SQLite, fans out webhooks |
rss-service/ | 3002 | Fetches current status from cache and serves RSS/Atom feeds |
discord-bot/ | 3001 | Posts door status to a Discord channel |
zulip-bot/ | 3003 | Posts door status to a Zulip stream |
noisebell-common/ | — | Shared types and helpers |
See each service's README for configuration and API docs.
| 1 | cargo build --release |
Or with Nix:
| 1 | nix build .#noisebell-cache |
| 2 | nix build .#noisebell-rss |
| 3 | nix build .#noisebell-discord |
| 4 | nix build .#noisebell-zulip |
The flake exports a NixOS module for hosted remote machines and a complete nixosConfigurations.noisebell-do host for the small DigitalOcean droplet. The module imports agenix, declares the Noisebell secrets from secrets/*.age, and wires the cache and Discord services together with sensible defaults. Each service runs as a hardened systemd unit behind Caddy.
| 1 | { |
| 2 | inputs.noisebell.url = "git+https://git.extremist.software/jet/noisebell"; |
| 3 | |
| 4 | outputs = { self, nixpkgs, noisebell, ... }: { |
| 5 | nixosConfigurations.myhost = nixpkgs.lib.nixosSystem { |
| 6 | system = "x86_64-linux"; |
| 7 | modules = [ |
| 8 | noisebell.nixosModules.default |
| 9 | ({ ... }: { |
| 10 | services.noisebell-cache = { |
| 11 | enable = true; |
| 12 | domain = "cache.noisebell.example.com"; |
| 13 | piAddress = "http://noisebell-pi:80"; |
| 14 | }; |
| 15 | services.noisebell-rss = { |
| 16 | enable = true; |
| 17 | domain = "rss.noisebell.example.com"; |
| 18 | }; |
| 19 | services.noisebell-discord = { |
| 20 | enable = true; |
| 21 | domain = "discord.noisebell.example.com"; |
| 22 | channelId = "123456789012345678"; |
| 23 | }; |
| 24 | }) |
| 25 | ]; |
| 26 | }; |
| 27 | }; |
| 28 | } |
The production DigitalOcean host in this repo enables the cache, Discord, and RSS services on the existing public domains:
noisebell.extremist.softwarediscord.noisebell.extremist.softwarerss-noisebell.extremist.softwareAfter installation, authenticate Tailscale interactively on the host with:
| 1 | sudo tailscale up --hostname=noisebell-do |
Redeploy later with:
| 1 | scripts/deploy-do jet@noisebell-do |
nixosModules.default handles these secrets automatically:
| Secret file | Deployed on | Used for |
|---|---|---|
secrets/pi-to-cache-key.age | Pi + remote | Pi authenticates to cache /webhook |
secrets/cache-to-pi-key.age | Pi + remote | cache authenticates to Pi GET endpoints |
secrets/discord-webhook-secret.age | remote | cache authenticates to Discord bot /webhook |
secrets/relay-webhook-secret.age | Pi + remote | cache authenticates to the Pi relay /webhook |
secrets/zulip-webhook-secret.age | remote | cache authenticates to Zulip bridge /webhook |
secrets/discord-token.age | remote | Discord bot login |
secrets/zulip-api-key.age | remote | Zulip bot API authentication |
When extremist-software builds a system using the Noisebell flake input, Nix uses the checked-out flake source for that input. The module points agenix at encrypted files inside that Noisebell source tree, such as ${inputs.noisebell}/secrets/discord-token.age. At activation time agenix decrypts them locally on the target host into runtime paths like /run/agenix/noisebell-discord-token. The service modules then read those local decrypted files when systemd starts them.