Remote bells and webhooks¶
School Bell supports three different remote-control paths. Choose the smallest one that matches the installation:
Feature |
Purpose |
|---|---|
Top-level |
Copy every scheduled signal to another Linux bell over SSH. |
|
Start best-effort SSH commands or webhooks when the physical button is pressed. |
Top-level |
Accept authenticated requests that ring this node locally. |
Remote connectivity is optional. A failed remote action is logged but does not make a correctly configured local bell dependent on a central service.
Prepare SSH access¶
SSH actions must work non-interactively as the School Bell service user. On the sending Pi, create a dedicated key and copy its public key to the receiving Pi:
$ ssh-keygen -t ed25519 -C school-bell -f /home/pi/.ssh/id_school_bell
$ ssh-copy-id -i /home/pi/.ssh/id_school_bell.pub pi@pibell-yard.local
Protect the private key and do not commit it. A service cannot answer a key passphrase prompt, so use a deliberately protected service key and restrict the receiving account and network access appropriately.
Create /home/pi/.ssh/config on the sender:
Host pibell-yard
HostName pibell-yard.local
User pi
IdentityFile /home/pi/.ssh/id_school_bell
IdentitiesOnly yes
PreferredAuthentications publickey
Connect once and verify the host identity before unattended operation:
$ ssh pibell-yard /usr/bin/aplay --help
Run this test as the same account used by school-bell.service. It must
complete without asking for a password, passphrase or host confirmation.
Warning
The current built-in SSH command disables strict host-key checking for compatibility with unattended installations. Register and verify the host yourself, restrict the dedicated key on the receiving Pi, and only use SSH triggering over a trusted management network. Host-key pinning should be added before treating an untrusted network as safe.
Mirror scheduled signals over SSH¶
The legacy top-level trigger mapping sends every scheduled signal to each
listed host. Its value is the WAVE directory on that remote host:
{
"trigger": {
"pibell-yard": "/home/pi/samples"
}
}
The remote directory must contain the same WAVE filenames selected by the
local wav mapping, and /usr/bin/aplay must be available remotely. Test
every destination before adding it to a production schedule.
Expose a bell webhook¶
Enable the authenticated endpoint on the receiving node:
{
"webhook": {
"enabled": true,
"host": "127.0.0.1",
"port": 8081,
"token": "replace-with-a-long-random-token",
"rate_limit": 10,
"rate_window": 60
}
}
The built-in server provides plain HTTP. Keep it on 127.0.0.1 and expose
it through a TLS reverse proxy such as nginx, Caddy or Apache. Configure
certificate validation, request-size limits and trusted-network access at the
proxy. Never expose the built-in port directly to an untrusted network.
Local HTTPS with Caddy¶
Caddy can provide HTTPS without a public domain or internet-facing service. It
creates a local certificate authority (CA), issues and renews the server
certificate, and proxies requests to School Bell over loopback. Install Caddy
using the official installation instructions, then create or extend
/etc/caddy/Caddyfile on the receiving node:
pibell-yard.local {
tls internal
request_body {
max_size 4KB
}
reverse_proxy 127.0.0.1:8081
}
Use a hostname that resolves to the receiving node from every sending node.
Local DNS or mDNS can provide this; a controlled /etc/hosts entry is also
sufficient. The hostname in the webhook URL must match the hostname in the
Caddyfile.
Validate and load the configuration:
$ sudo caddy validate --config /etc/caddy/Caddyfile
$ sudo systemctl reload caddy
When Caddy runs as a systemd service, its local root certificate is normally stored at:
/var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt
Install a copy of this public root certificate in the trust store of every sending node. Do not copy any private key from Caddy’s data directory. On a Debian or Raspberry Pi OS sender, copy the certificate securely to the node and run:
$ sudo install -m 0644 root.crt \
/usr/local/share/ca-certificates/school-bell-caddy.crt
$ sudo update-ca-certificates
The bearer token remains required after enabling HTTPS. Test the complete path from a sending node, without disabling certificate verification:
$ curl -X POST https://pibell-yard.local/bell \
-H 'Authorization: Bearer replace-with-a-long-random-token' \
-H 'Content-Type: application/json' \
--data '{"wav_key":"lesson"}'
Keep Caddy’s data directory persistent because it contains the local CA. Back up and protect it like other private key material. All proxied requests reach the built-in rate limiter from the loopback address, so its limit is shared by all clients using this proxy.
Send exactly one configured WAVE key:
$ curl -X POST https://bell.example.com/bell \
-H 'Authorization: Bearer replace-with-a-long-random-token' \
-H 'Content-Type: application/json' \
--data '{"wav_key":"lesson"}'
HTTP status |
Meaning |
|---|---|
|
The local signal was accepted for background execution. |
|
The JSON or |
|
Bearer authentication failed. |
|
The request path is not |
|
The endpoint only accepts |
|
Another signal is already active. |
|
The per-client rate limit was exceeded. |
|
Background execution could not be started. |
Responses contain keys and status information, never sample paths. Webhook
signals return 202 immediately after atomic acceptance; playback completion
or failure is reported through the webhook_bell_* monitoring events. They
are manual overrides: they do not respect holiday or disable-calendar
suppression and they do not automatically invoke the legacy top-level SSH
trigger destinations.
Verify and diagnose¶
Run
school-bell /home/pi/schema.json --checkon every node.Test local audio and GPIO before adding a remote path.
Test SSH as the systemd service user or test the webhook through its final TLS URL.
Trigger one bell while another signal is active and confirm the expected
409or skipped event.Inspect
journalctland the Graylogmanual_remote_trigger,remote_triggerorwebhook_*events.
See Configuration reference for every field and Networking and time synchronization for firewall and outage behavior.