Flotilla Agent

Flotilla Agent

Plugin from Livin Mathew

Overview

Flotilla Agent sends the notifications from your Unraid server to your iPhone. The plugin installs as an Unraid notify agent. It does not add its own monitor function. It sends the notifications that Unraid makes. These include parity checks, disk errors, SMART warnings and array events. Your User Scripts can also send notifications with the notify command. The plugin sends a heartbeat signal at regular intervals. Then your phone can show the difference between a correct server and a server that is not on the network. The plugin encrypts the content of each event on your server with ChaCha20-Poly1305. The encryption occurs before the data goes out of your local network. The key is in two locations only: the configuration file on your server, and the keychain on the paired phone. The relay that sends the push message receives ciphertext only. The relay cannot read the text of your notifications. The plugin does not send your Unraid API key, your host name, or other local secrets. The plugin is free and open source. The push messages go to Flotilla, an iOS app for Unraid and Proxmox. The push function needs the Pro option in that app, which costs USD 4.99 one time. The settings page is at Settings, then Flotilla Agent. You pair the phone with a QR code.

flotilla-agent

Server-side companions for Flotilla Push — the optional, paid push notification feature of Flotilla, an iOS Unraid/Proxmox homelab client app. This repo is everything that runs on your server; the counterpart Cloudflare Worker that everything here talks to is flotilla-relay. The wire format both repos (and the iOS app) agree on is documented in PROTOCOL.md.

Three components, one job each:

  • The Unraid plugin (plugin/) — hooks into Unraid's own notification system (notify agent) and a heartbeat cron job, and adds a settings page under Unraid's Settings tab for pairing and configuration.
  • flotilla-beacon (cmd/flotilla-beacon) — the equivalent for Proxmox VE: a small daemon that receives Proxmox's native webhook locally and forwards it, since Proxmox has no plugin system to hook into directly.
  • flotilla-seal (cmd/flotilla-seal) — the shared encryption CLI (internal/sealbox, ChaCha20-Poly1305) both senders shell out to, so the sealing logic is implemented exactly once.

MIT-licensed, no runtime dependency on anything besides Go's standard library and golang.org/x/crypto (used only by the Go binaries — the Unraid plugin is plain PHP/bash and needs no runtime dependency at all beyond what Unraid already ships: bash, curl, jq).

What it does, and does not, see

  • Event content is sealed (ChaCha20-Poly1305) locally, before it ever reaches the relay. Both senders in this repo — send-event.sh (the Unraid plugin) and flotilla-beacon (Proxmox) — encrypt with a key (K) that exists only in this server's config file and the paired iPhone's Keychain. Neither this repo's code, the relay, nor Apple's push infrastructure can read a sealed event's real subject/description; the relay only ever forwards ciphertext.
  • Your server's credentials never leave your LAN. Nothing in this repo ever sends your Unraid API key, Proxmox API token, hostname, or any server-local secret to the relay. The only things that go out are: the pairing ID, the bearer auth secret (S, used only to authenticate — never logged or displayed), sealed event ciphertext, and (for flotilla-beacon) a periodic heartbeat.
  • The one exception: the beacon-less Proxmox webhook path. If you point Proxmox's native webhook straight at the relay's POST /v1/pve instead of installing flotilla-beacon, there is no local encryption step — the relay (and therefore Apple, downstream) sees that event's title, message, and severity in plaintext. flotilla-beacon exists specifically to close this gap; see PROTOCOL.md for exactly which path each sender takes.
  • No telemetry. Nothing in this repo phones home anywhere except the relay URL you've configured, and only for the pairing/heartbeat/event traffic described above.

Install

Unraid plugin

From Unraid's Plugins → Install Plugin, paste the .plg URL:

https://raw.githubusercontent.com/Livin21/flotilla-agent/main/plugin/flotilla-agent.plg

This installs the settings page under Settings → Flotilla Agent, where you pair with the Flotilla iOS app (scan a QR code) and configure which notification categories/severities get forwarded. "Reset pairing" there revokes the old pairing at the relay (see below) and generates a new one.

Proxmox VE (flotilla-beacon)

The iOS app renders the exact install command during pairing (also documented in PROTOCOL.md) — the script itself is fetched straight from this repo's GitHub raw URL, not from the relay:

curl -fsSL https://raw.githubusercontent.com/Livin21/flotilla-agent/main/beacon/beacon-install.sh | FLOTILLA_SECRET=<s> FLOTILLA_KEY=<k> bash -s -- <relay> <pairingID>

This installs flotilla-beacon as a systemd service listening on 127.0.0.1:8799 by default (override with FLOTILLA_LISTEN=host:port), writes /etc/flotilla-beacon.conf (mode 600), and then creates the two pieces of Proxmox notification config the beacon needs:

  • a webhook target named flotilla, pointed at the beacon's listen address, carrying Authorization: Bearer <S> and the body template {"severity":{{ json severity }},"title":{{ json title }},"message":{{ json message }}};
  • a matcher of the same name routing severities warning and error to that target.

Both are required — PVE delivers nothing with only one of them — and both are additive: PVE's stock default-matcher (everything → mail-to-root) is left alone. Re-running the install command is safe (it rewrites config, binary and unit, restarts the service, and recreates the target/matcher) — useful after a re-pair, which rotates S and would otherwise leave the old target 401ing.

If the node isn't a Proxmox host, or pvesh fails, the install still finishes and prints the exact values to enter by hand instead. Pass FLOTILLA_SKIP_PVE=1 to always configure it yourself. The full table of values is in PROTOCOL.md, along with the pvesh commands.

Once configured, confirm the whole chain with pvesh create /cluster/notifications/targets/flotilla/test. If nothing arrives, journalctl -u flotilla-beacon will say whether the webhook was rejected for a missing or wrong Authorization header.

The binary is downloaded from this repo's GitHub releases, which requires a published release and this repo to be public — already a launch requirement (the Unraid CA and Proxmox community-scripts both mandate open source). The systemd unit is embedded in the installer rather than fetched, so the install has exactly one network dependency. For testing against an unpublished build — e.g. before this repo has ever cut a release — set FLOTILLA_BEACON_BIN=/path/to/a/locally-built flotilla-beacon (a binary you built yourself, e.g. via GOOS=linux go build -o flotilla-beacon ./cmd/flotilla-beacon): the script installs that file directly instead of downloading one. Everything else about the install (config file, unit, systemd enable/restart, PVE notification target) is unchanged.

flotilla-seal (standalone)

go build -o flotilla-seal ./cmd/flotilla-seal
./flotilla-seal keygen                       # 32 random bytes, base64url
echo '{"hello":"world"}' | ./flotilla-seal seal --key <b64url-key>

Reset / revoke

Resetting the pairing (Unraid's "Reset pairing" button, or re-running beacon-install.sh for Proxmox after re-pairing) sends DELETE /v1/pairing to the relay with the old pairing's secret before generating new pairing values, so the relay-side state (device tokens, heartbeat/alarm state) for the old pairing is actually wiped rather than silently orphaned. This is best-effort: a relay that's unreachable at that moment never blocks the local reset (plugin/src/scripts/revoke.sh always exits 0, bounded to a 5s timeout).

Self-hosting

Every sender's relay URL is a config value, not a hardcoded constant: the Unraid plugin's settings page (RELAY), flotilla-beacon's conf file (relay=), and the iOS app's own settings all point at a URL you control. To point this repo's agents at your own relay you only need to change that URL — nothing else in this repo is tied to a specific deployment. (Whether a self-hosted relay can itself deliver push for the official App Store build of Flotilla is a constraint of flotilla-relay, not of anything here — see that repo's README.)

Development

go build ./...
go test ./...                 # cmd/flotilla-seal, cmd/flotilla-beacon, internal/sealbox
php test/*.php                # settings.php unit tests (CSRF, cfg escaping, entity fixup, ...)
bash test/agent_test.sh       # send-event.sh/heartbeat.sh/revoke.sh against a local capture relay
bash plugin/build.sh <version> # rebuilds plugin/flotilla-agent-<version>.txz from plugin/src

test/agent_test.sh needs jq, python3, and go on PATH; it spins up test/capture_server.py as a fake relay and drives the real shell scripts against it end-to-end (including timeout/black-hole behavior against an unreachable relay).

License

MIT — see LICENSE.

Install Flotilla Agent on Unraid in a few clicks.

Find Flotilla Agent in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for Flotilla Agent Review the template variables and paths Click Install

Download Statistics

3
Total Downloads
8
This Month
1
Avg / Month

Downloads by Month

Loading chart...

Related apps

Explore more like this

Explore all

Details

Repository
https://raw.githubusercontent.com/Livin21/flotilla-agent/main/plugin/flotilla-agent.plg
Last Updated2026-08-23
First Seen2026-08-18