Skip to content

Peers

Peers live in the database; the hub reconciler puts every unblocked peer on wg0. Change them with the CLI (cerberd peer ..., over the local socket) or the REST API. Both run the same checks.

A peer’s IPs are what it reserves, and exactly its AllowedIPs on wg0:

  • one or more overlay /32s inside hub.overlay. The first is primary (REST URL, pings, lookups). More than one is the exception.
  • at most one LAN /24 inside hub.lan_space and outside the overlay. cerberd routes it to wg0 unless a hub.routes entry already covers it.

Anything else, or host bits set (10.20.23.5/24), is rejected. No address is held by two peers, blocked peers included, so unblocking always works. The hub’s own address and the overlay’s network and broadcast addresses belong to the hub.

Terminal window
cerberd overlay free 10.99.23.0/24 # 10.99.23.31/32 (not reserved)
cerberd conflicts --ip 10.99.23.31/32 --ip 10.20.23.0/24 --name office-9 # dry run
cerberd peer add office-9 --ip 10.99.23.31/32 --ip 10.20.23.0/24 \
--label 'Office 9' --tag offices --routeros

Keys: without key flags cerberd generates a key pair and keeps the private key, so peer config prints a complete client config. With --public-key K the spoke keeps its own private key (a MikroTik that generated it). --private-key-file F imports a given private key.

Names are DNS labels (they appear in URLs); --label takes free text.

Terminal window
cerberd peer config office-9 # wg-quick
cerberd peer config office-9 --format routeros # RouterOS script

The config has the peer’s private key (if cerberd has it), preshared key, overlay addresses, the client: settings with the peer’s overrides, and the hub’s public key and endpoint. The RouterOS script is idempotent: it only adds what is missing and stops if the interface exists with another key.

Terminal window
cerberd peer set office-9 --name office-09 --label 'Office 9 (2nd floor)'
cerberd peer set office-09 --ip 10.99.23.31/32 --ip 10.20.24.0/24 # replaces all IPs
cerberd peer set office-09 --keepalive 25 # hub-side persistent keepalive
cerberd peer set office-09 --routeros --router-url https://10.99.23.31
cerberd peer set office-09 --no-routeros # remove the router binding

Renaming a node or changing its IPs or router binding first takes its direct links down; run cerberd link up again afterwards.

A router whose WireGuard interface isn’t routeros.defaults.wg_interface (say wg1 instead of wg0) needs no setting: once the node is online, cerberd asks the router which interface has the peer’s public key and stores that name in the binding (router-interface event). It checks again whenever the binding changes or cerberd restarts.

Notes, preshared key, static endpoint and client overrides (allowed_ips, dns, mtu, keepalive) are set through the API (PATCH /v1/peers/{name}).

Terminal window
cerberd peer block office-9 # off wg0 with its routes; record, keys, IPs kept
cerberd peer unblock office-9 # back with the same key and IPs
cerberd peer rm office-9 # block first, then delete record, keys, IPs

Block and remove first take the peer’s direct links down. If a router that must be reached for that is unreachable, they stop (HTTP 503); --force goes ahead anyway.

Terminal window
cerberd peer rotate office-9 # new key pair, generated
cerberd peer rotate office-9 --public-key K # the spoke generated a new key
cerberd peer config office-9 # hand out the new config

The old key leaves wg0 at once; the client is cut off until it uses the new config.

Terminal window
cerberd conflicts 10.99.0.0/28 10.20.0.0/16
# 10.99.0.0/28: 1 peers
# office-1: 10.99.0.2/32

Blocked peers are included.

Peers on wg0 that the database doesn’t know (added by hand with wg set) are foreign. With hub.foreign_peers: keep (default) they stay and are counted in cerberd status; with remove the reconciler removes them. Rotated and deleted keys are always removed.