Configuration
One YAML file per instance: /etc/cerberd/wg0.yaml configures the hub
interface wg0. The file name is the interface, like
/etc/wireguard/wg0.conf for wg-quick. YAML holds configuration only;
peers, keys and links are in the database.
Unknown keys are errors. Changes take effect on systemctl restart cerberd@wg0.
The file must be readable by the cerberd group (root:cerberd 0640).
Minimal example
Section titled “Minimal example”hub: overlay: 10.99.0.0/24 endpoint: hub.example.net:51820Full example
Section titled “Full example”hub: overlay: 10.99.0.0/16 # every peer has one or more /32 inside this lan_space: 10.0.0.0/8 # a peer's optional LAN /24 lies inside this (outside overlay) address: 10.99.0.1 # the hub's own overlay address (default: first host) listen_port: 51820 mtu: 1420 # fwmark: 0 public_ip: 203.0.113.10 endpoint: hub.example.net:51820 # written into generated spoke configs foreign_peers: keep # keep | remove max_removals: 10 route_proto: 201 routes: [10.0.0.0/8] # db: /var/lib/cerberd/wg0.db
client: allowed_ips: [10.0.0.0/8] dns: none # or [10.99.0.1, example.net] # mtu: 1420 keepalive: 25
api: # socket: /run/cerberd/wg0.sock listen: 10.99.0.1:7480 token_file: /etc/cerberd/wg0.token # tls_cert: /etc/cerberd/wg0.crt # tls_key: /etc/cerberd/wg0.key
routeros: defaults: url: "http://{overlay_ip}" user: cerber password_file: /etc/cerberd/routeros.pass wg_interface: wg0 opener_ttl: 2 reachable: false
timers: direct_keepalive: 5s router_poll: 3s stall_threshold: 3 reappear_grace: 10s punch_stagger: 2.5s punch_timeout: 25s opener_hold: 1s backoff: [1m, 5m, 15m, 1h] safety_net_after: 45s hub_poll: 1s hub_reconcile: 5s hub_offline_after: 25s rest_timeout: 5s
verify: count: 5 min_gain: 0.1The hub interface cerberd owns.
| Key | Default | Meaning |
|---|---|---|
overlay |
required | IPv4 prefix, /30 or shorter. Every peer has one or more /32s inside |
address |
first host of overlay |
the hub’s own address on the interface |
listen_port |
51820 |
WireGuard UDP port, 1–65535 |
mtu |
1420 |
interface MTU, 1280–9000 |
fwmark |
0 (none) |
WireGuard firewall mark |
public_ip |
the hub’s public address (traceroute / netcheck) | |
endpoint |
host:port written into generated spoke configs. Without it, configs carry a placeholder |
|
lan_space |
10.0.0.0/8 |
IPv4 prefix, /24 or shorter. A peer’s optional LAN /24 lies inside it, outside overlay |
foreign_peers |
keep |
keep or remove: what to do with peers on the interface that the database doesn’t know |
max_removals |
10 |
refuse any reconcile that would cut more peers (or routes) off the hub at once. At least 1 |
route_proto |
201 |
route protocol number marking cerberd’s routes, 5–255 |
routes |
[] |
static IPv4 routes to the interface (the old wg-quick PostUp route). No default route. Per-peer LAN routes they cover are skipped |
db |
/var/lib/cerberd/<interface>.db |
the SQLite database |
client
Section titled “client”Defaults for generated spoke configs. A peer’s client overrides replace
them field by field (API). Set these in
/etc/cerberd/<interface>.yaml and restart the instance before exporting.
They apply to all peers without an override, including existing peers.
client.mtu is independent of hub.mtu; 0 omits the exported MTU.
DNS settings apply to wg-quick exports; RouterOS exports leave router DNS unchanged.
For example, these defaults send 10.0.0.0/8 through the hub on each spoke:
client: allowed_ips: [10.0.0.0/8] mtu: 1420 dns: none keepalive: 25The exported config contains AllowedIPs = 10.0.0.0/8 in the hub’s
[Peer] section. RouterOS exports use the same prefixes for the hub peer’s
allowed-address, and add a route through the tunnel for each of them
except a default route (0.0.0.0/0, ::/0) and prefixes inside the hub
overlay, which is already a connected route. To send all traffic through the
hub, add the default route on the router yourself, with a more specific
route to the hub’s public address via the uplink.
| Key | Default | Meaning |
|---|---|---|
endpoint |
hub.endpoint |
hub address as IP:port or domain:port; bracket IPv6, e.g. [2001:db8::1]:51820 |
allowed_ips |
[10.0.0.0/8] |
the spoke’s AllowedIPs for the hub peer |
dns |
[] |
DNS = entries: addresses or search domains; none or [] omits the line |
mtu |
0 (unset) |
the spoke’s MTU, 1280–9000 |
keepalive |
25 |
the spoke’s PersistentKeepalive, seconds; 0 drops it |
| Key | Default | Meaning |
|---|---|---|
socket |
/run/cerberd/<interface>.sock |
unix socket for the CLI, always on |
listen |
host:port of the optional TCP listener |
|
token_file |
bearer token file; required with listen. Must not be empty |
|
tls_cert, tls_key |
serve TCP over TLS; set both or neither |
See REST API.
routeros
Section titled “routeros”routeros.defaults applies to every peer with a router binding; the binding
in the database overrides any field.
| Key | Default | Meaning |
|---|---|---|
url |
http://{overlay_ip} |
REST base URL, http or https. {overlay_ip} is the peer’s primary overlay address |
user |
REST user | |
password_file |
file with the REST password (root:cerberd 0640) |
|
wg_interface |
wg0 |
the spoke’s WireGuard interface. When it doesn’t carry the peer’s public key, cerberd finds the interface that does and stores it in the peer’s binding |
tls_insecure |
false |
skip certificate verification for https |
opener_ttl |
2 |
punch opener TTL: hops to just past the site’s own NAT. 1 = the MikroTik has the public IP, 2 = behind an ISP router, more behind CGNAT |
reachable |
false |
the router accepts unsolicited WireGuard; prefer it as punch leader |
timers
Section titled “timers”Durations look like 500ms, 2.5s, 1m, 1h. All must be positive. The
defaults suit most networks; change them only with a reason.
| Key | Default | Meaning |
|---|---|---|
direct_keepalive |
5s |
persistent keepalive on direct peers |
router_poll |
3s |
reserved for active-link monitoring; not used yet |
stall_threshold |
3 |
reserved for active-link monitoring; not used yet |
reappear_grace |
10s |
reserved for active-link monitoring; not used yet |
punch_stagger |
2.5s |
delay between staging the leader and the follower |
punch_timeout |
25s |
wait for the direct handshake |
opener_hold |
1s |
openers stay on after the follower stages |
backoff |
[1m, 5m, 15m, 1h] |
reserved for automatic retries; not used yet |
safety_net_after |
45s |
reserved for a router-side safety net; not used yet |
hub_poll |
1s |
hub interface poll (online, endpoint, rx) |
hub_reconcile |
5s |
drift repair on the hub interface |
hub_offline_after |
25s |
no rx from a peer this long = offline at the hub |
rest_timeout |
5s |
per RouterOS REST call |
verify
Section titled “verify”| Key | Default | Meaning |
|---|---|---|
count |
5 |
pings per RTT measurement |
min_gain |
0.1 |
the direct path must be this fraction faster than the hub, in [0, 1) |