fix: update the readmes to be more clear

This commit is contained in:
Jet 2026-03-16 23:42:34 -07:00
parent dc7b8cbadd
commit 574a3a103e
No known key found for this signature in database
6 changed files with 216 additions and 147 deletions

View file

@ -1,39 +1,41 @@
# noisebell
# Pi
Monitors a GPIO pin on a Raspberry Pi to detect door open/close events. State changes get POSTed to a webhook endpoint. Current state is available over HTTP.
Rust service and NixOS config for the Raspberry Pi at Noisebridge. Reads a magnetic door sensor via GPIO, serves the current state over HTTP, and pushes changes to the cache service.
Runs on NixOS with Tailscale for networking and agenix for secrets.
Runs NixOS with Tailscale for remote access and agenix for secrets.
## How it works
The service watches a GPIO pin for rising/falling edges with a configurable debounce. When the door state changes, it:
1. Updates in-memory state (atomics)
2. POSTs `{"status": "open", "timestamp": ...}` to the cache service with a Bearer token
3. Retries with exponential backoff on failure
On startup it also syncs the initial state.
## Setup
### 1. Bootstrap
Build the SD image, flash it, and boot the Pi:
### 1. Flash the SD card
```sh
nix build .#nixosConfigurations.bootstrap.config.system.build.sdImage
dd if=result/sd-image/*.img of=/dev/sdX bs=4M status=progress
```
Insert the SD card into the Pi and power it on. It will connect to the Noisebridge WiFi network automatically.
Boot the Pi. It connects to the Noisebridge WiFi automatically.
### 2. Find the Pi
Once booted, find the Pi on the network:
```sh
# Scan the local subnet
nmap -sn 192.168.1.0/24
# Or check ARP table
# or
arp -a
# Or check your router's DHCP leases
```
### 3. Get SSH host key
### 3. SSH host key
Grab the Pi's ed25519 host key and put it in `secrets/secrets.nix`:
Grab the key and add it to `secrets/secrets.nix`:
```sh
ssh-keyscan <pi-ip> | grep ed25519
@ -42,7 +44,7 @@ ssh-keyscan <pi-ip> | grep ed25519
```nix
# secrets/secrets.nix
let
pi = "ssh-ed25519 AAAA..."; # paste the key here
pi = "ssh-ed25519 AAAA...";
in
{
"api-key.age".publicKeys = [ pi ];
@ -51,20 +53,18 @@ in
}
```
### 4. Secrets
Create the encrypted secret files:
### 4. Create secrets
```sh
cd secrets
agenix -e api-key.age # paste API key for the cache endpoint
agenix -e inbound-api-key.age # paste API key that the cache uses to poll the Pi
agenix -e tailscale-auth-key.age # paste Tailscale auth key
agenix -e api-key.age # key for POSTing to the cache
agenix -e inbound-api-key.age # key the cache uses to poll us
agenix -e tailscale-auth-key.age # tailscale auth key
```
### 5. Add SSH key
### 5. SSH access
Add your SSH public key to `configuration.nix`:
Add your public key to `configuration.nix`:
```nix
users.users.root.openssh.authorizedKeys.keys = [
@ -84,29 +84,31 @@ Options under `services.noisebell` in `flake.nix`:
| Option | Default | Description |
|---|---|---|
| `endpointUrl` | — | Webhook endpoint URL to POST state changes to |
| `apiKeyFile` | — | Path to file containing outbound API key (agenix secret) |
| `inboundApiKeyFile` | — | Path to file containing inbound API key for GET endpoint auth (agenix secret) |
| `gpioPin` | 17 | GPIO pin to monitor |
| `debounceSecs` | 5 | Debounce delay |
| `port` | 8080 | HTTP status port |
| `retryAttempts` | 3 | Webhook retry count |
| `retryBaseDelaySecs` | 1 | Base delay for exponential backoff |
| `httpTimeoutSecs` | 10 | Timeout for outbound webhook requests |
| `bindAddress` | `0.0.0.0` | Address to bind the HTTP server to |
| `activeLow` | `true` | Whether low GPIO level means open (depends on wiring) |
| `restartDelaySecs` | 5 | Seconds before systemd restarts on failure |
| `watchdogSecs` | 30 | Watchdog timeout — service is restarted if unresponsive |
| `endpointUrl` | required | Webhook URL to POST state changes to |
| `apiKeyFile` | required | Outbound API key file (agenix secret) |
| `inboundApiKeyFile` | required | Inbound API key file for GET auth |
| `gpioPin` | `17` | GPIO pin number |
| `debounceSecs` | `5` | Debounce delay in seconds |
| `port` | `8080` | HTTP server port |
| `retryAttempts` | `3` | Webhook retry count |
| `retryBaseDelaySecs` | `1` | Exponential backoff base delay |
| `httpTimeoutSecs` | `10` | Outbound request timeout |
| `bindAddress` | `0.0.0.0` | HTTP bind address |
| `activeLow` | `true` | Low GPIO = door open (depends on wiring) |
| `restartDelaySecs` | `5` | systemd restart delay on failure |
| `watchdogSecs` | `30` | systemd watchdog timeout |
## API
`GET /` — current door state:
All endpoints require `Authorization: Bearer <token>`.
**`GET /`** — door state
```json
{"status": "open", "timestamp": 1710000000}
```
`GET /info` — system health and GPIO config:
**`GET /info`** — system health + GPIO config
```json
{
@ -129,5 +131,3 @@ Options under `services.noisebell` in `flake.nix`:
}
}
```
State changes (and initial state on startup) are POSTed to the configured endpoint in the same format as `GET /`, with an `Authorization: Bearer <api-key>` header.