Skip to content

Migrate from wg-quick / WGDashboard

An existing hub run by wg-quick@wg0, with or without WGDashboard, is imported once and then handed over without tearing wg0 down. Clients stay connected.

All sources are read-only. WGDashboard’s database is never written.

Source Gives
live wg0 hub key, active peers and their AllowedIPs, endpoints: the truth for what is on the hub
/etc/wireguard/wg0.conf Address, ListenPort, MTU, the PostUp route (becomes hub.routes)
WGDashboard SQLite (<install>/src/db/wgdashboard.db) names (transliterated, original kept as label), private and preshared keys, notes, per-peer client settings, restricted peers (become blocked), peer groups (become tags)

Not imported: deleted peers, transfer history, peer jobs, share links. WGDashboard on PostgreSQL or MySQL isn’t supported.

Move the PostUp FORWARD rules and net.ipv4.ip_forward into the host firewall and sysctl.d, so they survive without wg-quick’s hooks.

Freeze edits in WGDashboard, then do a dry run:

Terminal window
cerberd import wg0 --wgdashboard /opt/WGDashboard/src/db/wgdashboard.db --dry-run

It prints peers by status, generated names, tags, keys found, warnings and problems. Problems stop a real import: a peer that breaks the address rules, an address shared by two peers, a peer active in WGDashboard but not on wg0, or wg-quick settings cerberd can’t keep (Table = other than auto/main, a route hook with a table or metric, more than one Address). Fix them, or leave peers out with --skip <name | key | IP>. Warnings don’t stop it.

Without /etc/cerberd/wg0.yaml, import derives a config and prints it. --write-config writes it:

Terminal window
cerberd import wg0 --wgdashboard /opt/WGDashboard/src/db/wgdashboard.db \
--skip '<name>' --write-config

All flags: cerberd import.

Take wg0 away from WGDashboard and wg-quick without running wg-quick down. Stop at the first command that fails.

Terminal window
# WGDashboard: remove wg0 from autostart (wg-dashboard.ini), then stop it
# or leave it running for other interfaces.
# stopping the unit must not run wg-quick down
d=/run/systemd/system/wg-quick@wg0.service.d; mkdir -p $d
printf '[Service]\nExecStop=\nExecStop=/bin/true\n' > $d/handover.conf
systemctl daemon-reload
systemctl show -p ExecStop wg-quick@wg0 | grep -q 'path=/bin/true' # must succeed
systemctl stop wg-quick@wg0 && systemctl disable wg-quick@wg0
rm $d/handover.conf && systemctl daemon-reload
ip link show wg0 && wg show wg0 peers | wc -l # still up, same peers
# WGDashboard only lists *.conf; wg-quick can't find it any more
mv /etc/wireguard/wg0.conf /etc/wireguard/wg0.conf.imported
systemctl enable --now cerberd@wg0 # adopts the live wg0
journalctl -u cerberd@wg0 -n 20

The first reconcile should change nothing. “hub reconciled” lines with peer changes mean the database differs from what was on wg0.

From the console. Deleting wg0 cuts a session that runs through it, so the swap runs as one detached job:

Terminal window
systemctl disable --now cerberd@wg0 # leaves wg0 up
mv /etc/wireguard/wg0.conf.imported /etc/wireguard/wg0.conf
systemd-run --unit cerberd-rollback sh -c 'ip link del wg0; systemctl enable --now wg-quick@wg0'
# then restore WGDashboard's autostart of wg0

Expect a short outage while clients re-handshake. WGDashboard’s database is as it was at import time; changes made in cerberd since are not in it.

Try the migration on a throwaway VM first: set up wg0 the way your hub has it (same wg-quick hooks, WGDashboard version if you use it), connect a test client, and run the import, handover and rollback there. On the real hub, take a copy of wg0.conf and the WGDashboard database before you start.