Overview
cerberd runs on a Linux WireGuard hub. One binary is both the daemon and
its CLI. Spokes (MikroTik routers, laptops, phones) run no cerber code.
┌──────────── hub ────────────┐ CLI ──unix──► │ cerberd ──► wg0.db (SQLite) │ API ──TCP───► │ │ │ │ ├─► wg0 (wgctrl + ip) │ │ └─► RouterOS REST ───────┼──► spokes └─────────────────────────────┘What it does
Section titled “What it does”- Owns the hub interface. It creates
wg0, sets its key, port, MTU and address, and adds and removes peers and their routes. It applies per-peer diffs, never a wholesale replace, and repairs drift every few seconds. - Keeps a peer database. Names, reserved IPs, private and public keys, blocked state, tags and router bindings live in SQLite. The CLI and the HTTP API are the only ways to change them.
- Builds direct links between RouterOS spokes over their REST API, on top
of the hub path. Links are manual for now (
cerberd link up a b); tag-based automatic links come later.
Instances
Section titled “Instances”One instance per hub interface, like wg-quick. The interface name ties everything together:
wg0 instance |
|
|---|---|
| systemd unit | cerberd@wg0 |
| config (YAML) | /etc/cerberd/wg0.yaml |
| database | /var/lib/cerberd/wg0.db |
| API socket | /run/cerberd/wg0.sock |
See Files and paths for the full list.
Guarantees
Section titled “Guarantees”- Forwarding doesn’t depend on cerberd. Stopping, restarting or crashing
the daemon leaves
wg0up with all its peers. On start it adopts the live interface and reconciles; there is no flap. Onlycerberd downdeletes it. - One writer. Only cerberd writes
wg0. Don’t runwg-quick@wg0or WGDashboard on the same interface. - Blast-radius guard. A reconcile that would cut more than
hub.max_removalspeers (or routes) off the hub changes nothing and is reported. A wrong or empty database can’t empty the hub. - Only tagged router objects. On routers cerberd only touches objects it
created (
comment=cerber:...,name=cerber-...). It never modifies the spoke’s hub peer or anything untagged. - Out of scope: IP forwarding, firewall and NAT. They belong in the host
configuration (nftables,
sysctl.d), independent ofwg0.
| Term | Meaning |
|---|---|
| peer | a database record: a name, a key pair (or just the public key), and its IPs |
| overlay address | a peer’s /32 inside hub.overlay. The first one is primary |
| LAN | at most one /24 per peer inside hub.lan_space, routed to that peer |
| blocked | kept in the database with its keys and addresses, but off wg0 |
| node | a peer with a router binding: cerberd may drive its router and build direct links |
| foreign peer | a peer on wg0 that the database doesn’t know |
| direct link | a WireGuard peer between two spokes’ routers, so their traffic skips the hub |
Current limitations
Section titled “Current limitations”- Spokes that get direct links must be RouterOS v7 routers. Any WireGuard client works as a plain peer.
- Direct links are made by hand (
cerberd link up). They aren’t stored in the database: after a restart, cerberd adopts the healthy ones it finds on the routers and removes the rest. - IPv4 only for overlay and LAN addresses.