Wheelhouse docs

WireGuard#

VPN → WireGuard manages the router's own in-kernel WireGuard: interfaces under interfaces wireguard <name> and their peers. Nothing here is a container or a second daemon — a tunnel is an interface with a key and a port, a peer is a public key and the prefixes allowed through it, and both are configuration that stages, diffs, commits and rolls back like any other. The page shows what the configuration declares beside what the router reports about the interfaces, and it is honest about the gap: it has no handshake times and no transfer counters.

Getting to the page#

The WireGuard entry carries the wireguard feature id in the navigation model, so it appears when the feature is switched on in Apps or when interfaces wireguard already exists in the configuration. A router that already runs WireGuard shows the page regardless of the switch — the product does not hide configuration that exists (ui/src/components/nav.ts, agent/catalog.json).

Where the page gets its data#

GET /api/wireguard, re-read every 10 seconds, returns three things (agent/opmode.go handleWireGuard):

KeyFrom
configThe interfaces wireguard subtree, read as a tag node so each tunnel is its own entry rather than one bogus wireguard tunnel.
interfacesThe parsed table of show interfaces wireguard.
rawThat command's text output.

The CLI view is GET /api/config/commands?path=["interfaces","wireguard"], which is the subtree as set commands — and, below the admin role, redacted the same way.

The tunnel cards#

One card per tunnel, titled with the interface name and a badge:

  • up — the interface appears in show interfaces wireguard.
  • not reported — it does not. That is a configured tunnel the router is not reporting, which usually means the interface failed to come up.

Each card lists Address, Listen port, MTU (default when unset), Description and the peer count, and carries two buttons: + Peer, and Delete, which stages delete interfaces wireguard wg0 — the tunnel and every peer on it.

Above the cards are three tiles: the number of tunnels, the number of peers, and the number of interfaces the router reports.

The peer table#

Every peer across every tunnel, in one table.

ColumnFrom
PeerThe peer's name — the tag it is configured under.
TunnelThe interface it belongs to.
Public keyThe first 16 characters of public-key, with an ellipsis. The full value is in the panel.
Endpointaddress:port, or the address alone, or roaming when the peer declares neither.
Allowed IPsEvery allowed-ips value, comma separated.
Keepalivepersistent-keepalive in seconds, or a dash.

Clicking a row opens a panel with the full public key, the endpoint, the allowed prefixes, the keepalive, and one Delete peer button that stages delete interfaces wireguard wg0 peer laptop.

Creating a tunnel#

+ Add tunnel takes four fields and stages up to three operations:

FieldCommand
Interface name (default wg0)the tag in every path below
Listen port (default 51820)set interfaces wireguard wg0 port 51820
Addressset interfaces wireguard wg0 address 10.10.0.1/24
Private keyset interfaces wireguard wg0 private-key <key>
set interfaces wireguard wg0 port 51820
set interfaces wireguard wg0 address 10.10.0.1/24
set interfaces wireguard wg0 private-key <key>

The private key's hint says where to get one: generate it on the router with run generate pki wireguard key-pair. The page does not generate keys, and it does not paste a private key anywhere except into the operation you are staging — which is then visible in the Commit Bar to the operator who typed it, and redacted from a viewer's read of the configuration afterwards.

A tunnel with no address is legal — the field is optional here — but it will not carry routed traffic.

Adding a peer#

+ Peer on a tunnel card asks for six fields. A name and a public key are required; the button stays disabled without them.

FieldCommand
Peer namethe tag: … peer laptop …
Public keyset interfaces wireguard wg0 peer laptop public-key <key>
Allowed IPsone set … allowed-ips <cidr> per comma-separated value
Endpoint addressset … peer laptop address <host> — leave blank for a roaming client
Endpoint portset … peer laptop port <port>
Persistent keepaliveset … peer laptop persistent-keepalive 25

A road-warrior laptop, staged in full:

set interfaces wireguard wg0 peer laptop public-key <peer-public-key>
set interfaces wireguard wg0 peer laptop allowed-ips 10.10.0.2/32
set interfaces wireguard wg0 peer laptop persistent-keepalive 25

The Allowed IPs hint is the sentence people most often need: this is the routing table for the tunnel. A prefix listed here is both what the peer may send from and what the router will route to it. The keepalive hint is the other one: 25 seconds for peers behind NAT.

What this page will not do#

  • No handshake times and no transfer counters. The peer panel says so itself: those need wg show on the router, and the agent does not expose it. What you get is configuration, plus whether the router reports the interface at all (ui/src/pages/WireGuard.tsx).
  • No key generation. run generate pki wireguard key-pair on the router, and paste.
  • No client configuration file or QR code. The peer's side is yours to write.
  • No editing of an existing tunnel or peer. The panels create and delete. Changing a peer's allowed prefixes means staging the set yourself — from the Config tree, the console, or the API — or deleting the peer and adding it back.
  • No firewall rules. A WireGuard interface forwards nothing by itself: traffic out of the tunnel still meets the forward chain's default action. The catalogue entry puts that reminder on the Firewall page as an integration hint, and it is worth repeating here.

Making a tunnel useful#

Three things beyond the tunnel itself, each documented elsewhere:

  1. Let the peers in. The input chain has to accept UDP on the listen port from the uplink — see firewall rules.
  2. Let their traffic through. The forward chain has to accept traffic in and out of the tunnel interface, or from the peers' prefixes.
  3. Give them a route back. The peer's allowed-ips is the routing table for the tunnel; anything not listed there is not routed to that peer.

See also#

Checked against#

ui/src/pages/WireGuard.tsx, ui/src/components/nav.ts, ui/src/lib/api.ts, agent/opmode.go, agent/main.go, agent/security.go, agent/catalog.json.

Updated 2026-09-02 manual wireguard vpn