⚡ Funded by the Human Rights Foundation — Bitcoin Development Fund

MULTI-PROTOCOL ALERTING · WORKS WHEN THE INTERNET DOESN'T

Alerts don't stop at the edge of the network.

When your monitoring stack has something to say, OpenAlert makes sure it gets said — over REST, Nostr, Bluetooth mesh, LoRa radio, Wi-Fi or SMS — and can ring your actual phone through py-phone-caller if nothing else gets through. No cloud vendor, no single relay, no missed page.

PURE RUST · v0.2.0 · SINGLE STATIC BINARY · 100+ TESTS

openalertd · routing panel 6 inbound transports → 5 outbound destinations
REST inbound webhook SMS GSM / LTE modem NOSTR NIP-17/44 gift wraps LORA 868 MHz sub-GHz radio BITCHAT BLE mesh SOS PORTAL Wi-Fi captive portal openalertd Rust control plane PY-PHONE-CALLER voice + SMS dispatch NOSTR RELAYS DMs + public broadcast BITCHAT MESH public BLE escalation MULTI-HOP RF edge-to-gateway hops IT OPS PagerDuty · Grafana

When the network fails

OpenAlert isn't built for the best-case scenario. It's built for these:

Your ISP goes down → Nostr keeps relaying over any path still reachable — VPN, LTE, satellite.
A government throttles or blocks the internet → BitChat carries the alert over local Bluetooth mesh. No ISP, no tower, no server to seize.
Nobody's watching the dashboard at 3 AM → py-phone-caller rings an actual phone until someone answers.
A single cloud vendor has an outage → Nothing in OpenAlert depends on one relay, one server, or one provider.
Nobody nearby has the right app installed → Anyone can join the node's Wi-Fi and a captive portal opens. No app, no account.
There's no cell, Wi-Fi or Bluetooth in range → LoRa radio hops the alert from node to node until it reaches a gateway.
01

Core architecture

OpenAlert standardizes every incoming alert into the Prometheus Alertmanager schema, then relays it across whichever transports are still alive — from enterprise tooling to Bluetooth, radio and SMS.

Speaks the language you already run

Outbound payloads follow the standard Alertmanager JSON schema, so it can trigger py-phone-caller directly or plug into Grafana, PagerDuty, or any dashboard that already speaks that language.

One binary, zero dependencies

openalertd is a single static Rust executable with its web dashboard built in. It runs on a datacenter server or a solar-powered ARM board, and a SQLite spool keeps queued alerts safe through power loss.

Built to run unattended

Circuit breakers back off failing links, a watchdog resets hung USB radios and modems, and radio traffic respects the 1% ETSI airtime limit. Field-certified on ARM64 boards with LoRa hardware.

Ships with turnkey profiles

edge-sensor for off-grid SOS nodes, mesh-repeater for hilltop relays, and central-gateway for your operations center.


02

Supported transports

Six ways in, five ways out, one daemon in the middle. Colors follow Web of Trust distance: green is direct and local, yellow is relayed, red is third-party infrastructure.

IT infrastructure

REST

Receives JSON payloads from watchdogs and webhooks, compatible with the monitoring you already run.

In: JSON webhook  ·  Out: Alertmanager schema
Decentralized network

Nostr

Encrypted gift-wrapped DMs (NIP-17/44) and public broadcast, through relays or a built-in relay on port 8088. Works with 0xChat, with acknowledgments.

In: relay event  ·  Out: signed Nostr event
Local mesh

BitChat

Peer-to-peer over Bluetooth Low Energy, with no ISP or cell tower involved. Direct messages use a Noise XX handshake, and private emergencies escalate to the public mesh.

In: BLE mesh packet  ·  Out: mesh escalation
Local Wi-Fi

SOS portal

Phones join the node's Wi-Fi and a captive portal opens at /sos. No app to install, and an offline CAPTCHA keeps spam out.

In: web form  ·  Out: mesh, radio, phone
Long-range radio

LoRa

Sub-GHz radio links field nodes hop by hop, with routing that steers around weak links and built-in airtime limits.

In: RF frame  ·  Out: multi-hop forward
Cellular

SMS

A GSM/LTE modem sends and receives texts over AT commands. Sender allow-lists stop strangers from injecting alerts.

In: inbound SMS  ·  Out: SMS dispatch
$ openalertd status
[rest] payload from local watchdog ······ ok
[nostr] gift wrap received, unwrapped ····· signed
[lora] frame via mesh-repeater ·········· hop 2
[bitchat] BLE packet decoded ·············· Noise ok
[sos] /sos form verified ··············· CAPTCHA ok
→ normalizing to Alertmanager schema · dispatching to configured destinations

03

Use cases

Not hypotheticals — the situations OpenAlert is actually built to survive.

A

3 AM, and your node just went dark

Your Lightning node stops syncing and Alertmanager fires — right as your home ISP drops too. OpenAlert already relayed the alert over Nostr and dialed your phone through py-phone-caller. You're awake before anything force-closes.

B

The state cuts the internet mid-protest

Webhooks and push notifications die the moment a government throttles or blackholes traffic. OpenAlert keeps moving alerts over Bluetooth mesh and LoRa radio, and people without the app can still send an SOS through the node's Wi-Fi portal. No ISP, no cell tower, no server to seize.

C

Your homelab has no one on call

Prometheus fires into a channel nobody checks after hours. Point the same alert at OpenAlert instead: it broadcasts to Nostr for anyone watching a relay, and triggers a real call or SMS through py-phone-caller — no alerting vendor, no monthly seat.


Get it running

Compiles with standard Rust tooling into one static executable.

# clone and build
git clone https://github.com/jcfdeb/py-phone-caller.git
cd py-phone-caller/src/openalert
cargo build --release
# install as a systemd service (optional Wi-Fi SOS portal for ARM field nodes)
sudo ./packaging/install.sh --with-wifi-ap

04

Support the project

OpenAlert is free, open-source, and grant-funded — grants run out, uptime doesn't. If it's useful to you or your team, keep it running.