No description
Find a file
2026-03-16 23:32:07 -07:00
pi feat: add remote, with rss, cache, discord, and zulip 2026-03-10 15:45:42 -07:00
remote feat: reorganize with remote 2026-03-16 23:32:07 -07:00
.gitignore feat: reorganize with remote 2026-03-16 23:32:07 -07:00
README.md feat: reorganize with remote 2026-03-16 23:32:07 -07:00

Noisebell

Door status monitor for Noisebridge. A Raspberry Pi watches a door sensor and reports open/closed state; remote services cache the data and fan it out to Discord and an Atom feed.

Architecture

Pi (door sensor) ──webhook──▸ Cache Service ──webhook──▸ Discord Bot
                                   │                        │
                        polls Pi ◂──┘            Atom feed ◂──┘
                                                  RSS Service

The Pi runs a small HTTP service that reads GPIO and exposes GET / (status) and GET /info. It also pushes state changes to the cache service via webhook.

The Cache Service is the central hub. It polls the Pi for status and info, stores everything in SQLite, and forwards state changes to downstream webhooks (Discord, etc.). It exposes a read API for consumers.

The Discord Bot receives webhooks from the cache service and posts embeds to a Discord channel.

The RSS Service fetches history from the cache service and serves an Atom feed of door events from the last 7 days.

Services

Service Crate Default Port Description
Cache noisebell-cache 3000 Polls Pi, caches state in SQLite, forwards webhooks
Discord noisebell-discord 3001 Posts door status embeds to Discord
RSS noisebell-rss 3002 Serves Atom feed of recent door events

Cache API

Method Path Auth Description
GET /status None Current door status (status, timestamp, last_seen)
GET /info None Pi system info (JSON blob)
GET /history None Last 100 state changes
POST /webhook Bearer token Inbound webhook from Pi
GET /health None Returns 200 OK

Building

All remote services live in a Cargo workspace under remote/.

cd remote
cargo build --release

Or with Nix:

cd remote
nix build .#noisebell-cache
nix build .#noisebell-discord
nix build .#noisebell-rss

NixOS Configuration

The flake at remote/flake.nix exports NixOS modules. Example configuration:

{
  inputs.noisebell.url = "git+https://git.extremist.software/jet/noisebell?dir=remote";

  outputs = { self, nixpkgs, noisebell, ... }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        noisebell.nixosModules.default
        ({ ... }: {
          services.noisebell-cache = {
            enable = true;
            domain = "cache.noisebell.example.com";
            piAddress = "http://noisebell-pi:80";
            piApiKeyFile = "/run/secrets/noisebell-pi-api-key";
            inboundApiKeyFile = "/run/secrets/noisebell-inbound-api-key";
            outboundWebhooks = [
              {
                url = "http://localhost:3001/webhook";
                secretFile = "/run/secrets/noisebell-discord-webhook-secret";
              }
            ];
          };

          services.noisebell-discord = {
            enable = true;
            domain = "discord.noisebell.example.com";
            discordTokenFile = "/run/secrets/noisebell-discord-token";
            channelId = "123456789012345678";
            webhookSecretFile = "/run/secrets/noisebell-discord-webhook-secret";
          };

          services.noisebell-rss = {
            enable = true;
            domain = "rss.noisebell.example.com";
            cacheUrl = "http://localhost:3000";
          };
        })
      ];
    };
  };
}

Secrets

Secret Used by Description
piApiKeyFile Cache Bearer token for authenticating to Pi GET endpoints
inboundApiKeyFile Cache Bearer token the Pi uses when POSTing to /webhook
outboundWebhooks[].secretFile Cache Bearer token sent with outbound webhook POSTs
discordTokenFile Discord Discord bot token
webhookSecretFile Discord Must match the cache's outbound webhook secret