5.4 KiB
Hosting
Noisebell is hosted with DigitalOcean as the public service and observability hub, the Raspberry Pi on Tailscale, and Cloudflare Tunnel as the only intended public HTTP entry point.
Public Routes
| Hostname | Target | Access |
|---|---|---|
noisebell.extremist.software |
cache public routes | public via Cloudflare Tunnel |
rss-noisebell.extremist.software |
RSS service | public via Cloudflare Tunnel |
grafana-noisebell.extremist.software |
Grafana | public via Cloudflare Tunnel, Grafana login required |
discord.noisebell.extremist.software is not routed through the tunnel. The Discord bot stays local to the DigitalOcean host and receives cache webhooks at 127.0.0.1.
Private Routes
| Route | Purpose |
|---|---|
jet@noisebell-do |
DO administration over Tailscale SSH |
pi@noisebell-pi or pi@100.66.45.36 |
Pi administration over Tailscale SSH |
noisebell-do:3000/webhook |
Pi state-change webhook to cache |
noisebell-pi:80 |
DO cache polling and Pi app metrics |
noisebell-pi:8090 |
cache to Pi Home Assistant relay |
noisebell-pi:9100 |
Pi node exporter metrics |
noisebell-do:3100 |
Pi journal shipping to Loki |
DigitalOcean Firewall
NixOS firewall policy is in hosts/noisebell-do/configuration.nix.
SSH is Tailscale-only because no public TCP SSH port is opened and tailscale0 is trusted. Direct public HTTP and HTTPS stay open while services.noisebell-public-gateway.enable = false so an accidental pre-tunnel deploy does not break the existing site. Once the Cloudflare Tunnel module is enabled, public TCP ports close and all public web access enters through the tunnel.
After the tunnel is verified, mirror that policy in the DigitalOcean cloud firewall: close public inbound 22, 80, and 443; keep outbound open; keep Tailscale UDP reachable as needed.
Cloudflare Tunnel
The tunnel module is hosts/noisebell-do/public-gateway.nix. It defines ingress for the three public hostnames and returns 404 for everything else.
The module reconciles Cloudflare through the API when enabled:
- creates a locally-managed tunnel named
noisebell-doif it does not exist - writes the tunnel credentials JSON to
/var/lib/noisebell-public-gateway/credentials.json - upserts proxied CNAME records for the public hostnames
- starts
cloudflaredwith local Nix-managed ingress rules
Create two age secrets before enabling the module:
cd secrets
agenix -e cloudflare-api-token.age
nix shell nixpkgs#openssl -c openssl rand -base64 32
agenix -e cloudflare-tunnel-secret.age
Paste the generated base64 value into cloudflare-tunnel-secret.age.
Set services.noisebell-public-gateway.accountId and services.noisebell-public-gateway.zoneId in hosts/noisebell-do/configuration.nix, then flip services.noisebell-public-gateway.enable = true.
Required Cloudflare API token scopes:
| Resource | Scope |
|---|---|
| Account | Cloudflare Tunnel:Edit or Cloudflare One Connector: cloudflared:Edit |
| Zone | DNS:Edit for extremist.software |
The token should be restricted to the Noisebell Cloudflare account and the extremist.software zone.
Grafana
Grafana listens on 127.0.0.1:3030 on the DO host. Public access is through https://grafana-noisebell.extremist.software/ and requires the Grafana login form.
The admin user is admin. The password is generated on the DO host at first start and stored in /var/lib/grafana/admin_password.
ssh jet@noisebell-do sudo cat /var/lib/grafana/admin_password
Two dashboards are provisioned from hosts/noisebell-do/observability.nix:
| Dashboard | Audience | Datasources |
|---|---|---|
Noisebell Full Debug |
authenticated operators | Prometheus and Loki |
Noisebell Public |
anyone with the shared link | Prometheus only |
Use Grafana externally shared dashboards for the public-safe view. noisebell-grafana-public-dashboard.service creates or refreshes the public share on boot/deploy with a deterministic token.
The public-safe URL is:
https://grafana-noisebell.extremist.software/public-dashboards/6e6f69736562656c6c7075626c696330
The RSS and Grafana hostnames use one label under extremist.software so they are covered by Cloudflare Universal SSL. Nested names like grafana.noisebell.extremist.software require additional Cloudflare certificate setup.
The helper script scripts/share-grafana-public-dashboard jet@noisebell-do can still be used to repair or print that URL manually. The public dashboard intentionally avoids Loki/raw journal panels and uses stored Prometheus queries only.
Pi Hardening
scripts/deploy-pios-pi.sh configures the Raspberry Pi OS host. It now uses NOISEBELL_ENDPOINT_URL=http://noisebell-do:3000/webhook by default, so state changes go to the cache over Tailscale instead of the public domain.
The deploy script applies a persistent firewall service, noisebell-tailscale-only-firewall.service, that drops non-Tailscale TCP traffic to 22, 80, 8090, and 9100. Existing SSH sessions survive because established connections are allowed. New SSH, app, relay, and node exporter access must use Tailscale.
Deploy the Pi over Tailscale after the first bootstrap:
HOME_ASSISTANT_BASE_URL=http://10.21.0.43:8123 scripts/deploy-pios-pi.sh pi@100.66.45.36
Override the cache webhook only if needed:
NOISEBELL_CACHE_WEBHOOK_URL=http://noisebell-do:3000/webhook scripts/deploy-pios-pi.sh pi@100.66.45.36