feat: reorganize with remote
This commit is contained in:
parent
a74e5753fa
commit
dc7b8cbadd
28 changed files with 622 additions and 3024 deletions
114
README.md
Normal file
114
README.md
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
# Noisebell
|
||||
|
||||
Door status monitor for [Noisebridge](https://www.noisebridge.net). 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/`.
|
||||
|
||||
```sh
|
||||
cd remote
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
Or with Nix:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```nix
|
||||
{
|
||||
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 |
|
||||
Loading…
Add table
Add a link
Reference in a new issue