Network Configuration Guide

Define your virtual WireGuard networks in YAML to easily manage peering, subnets, and routing.

🎓 New to WireGuard?

If you are unfamiliar with concepts like public keys, endpoints, or AllowedIPs, we highly recommend reading the WG Tutorial first to see how it all works under the hood.

A single cloud server acting as a gateway to its internal Docker network, and a laptop that can access it from anywhere.
basic-cloud.yml
version: 2
contact_email: "admin@example.com"

physical_networks:
  - network: "wan"
    priority: 1

wireguard_networks:
  - network: "vpn"

nodes:
  - name: "server"
    public_key: "SERVER_PUB_KEY="
    subnets: ["172.17.0.0/16"] # Expose Docker network
    physical:
      - network: "wan"
        address: "203.0.113.1"
    wireguard:
      - network: "vpn"
        address: "10.0.0.1"

  - name: "client"
    public_key: "CLIENT_PUB_KEY="
    physical: ["wan"] # Roaming node (no address)
    wireguard:
      - network: "vpn"
        address: "10.0.0.2"

1. Global Settings

Configuration that applies to the entire network or the Control Plane itself.

  • version: (Required) Must be 2.
  • contact_email: (Optional) Administrative contact.
  • admin_tokens: (Optional) List of tokens for full read/write protection.
  • write_tokens: (Optional) List of tokens for write-only protection.
  • interface_name: (Optional) Default interface name for generated deployment scripts (e.g., wg0).
version: 2
contact_email: "admin@example.com"
interface_name: "wg-corp"

2. Physical Networks (Dual-Stack / IPv6)

Underlying infrastructure paths (e.g., LAN, WAN). Nodes connect via the highest priority shared path.

IPv6 Support: Physical endpoints fully support IPv6. Define separate IPv4 and IPv6 physical networks to create a prioritized dual-stack mesh.

Supported Properties:

  • network: (Required) The name identifier for this physical path (e.g., "wan", "office-lan").
  • priority: (Required) Integer determining path preference. Higher numbers are preferred over lower numbers.
  • disabled: (Optional) Set to true to temporarily disable this physical path globally.
physical_networks:
  - network: "wan-v6"
    priority: 10        # Prefer IPv6 if both peers support it
  - network: "wan-v4"
    priority: 1         # Fallback to IPv4

3. WireGuard Networks

Isolated virtual networks. Shared membership creates automatic peering. Nodes can attach to multiple networks to bridge them.

Note: Virtual internal networks do not currently support IPv6. All virtual addresses must be IPv4.

Supported Properties:

  • network: (Required) The name identifier for this virtual switch (e.g., "production").
  • mtu: (Optional) Default MTU for all nodes on this network.
  • persistent_keepalive: (Optional) Default keepalive interval in seconds.
  • disabled: (Optional) Set to true to temporarily disable this virtual network globally.
  • dns: (Optional) List of static DNS servers to assign to clients.

DNS Automation (See Section 9):

  • upstream_dns: (Optional) List of upstream servers for CoreDNS to forward public queries to.
  • dns_ttl: (Optional) Global TTL for auto-generated DNS records.
  • custom_dns: (Optional) List of manual DNS records to inject into the zone.
wireguard_networks:
  - network: "production"
    persistent_keepalive: 25 # (Optional) Default for everyone on this network
    dns: ["1.1.1.1"]         # (Optional) Default DNS for this network
  - network: "management"
    mtu: 1280                # (Optional) Default MTU for this network

4. Nodes & Attachments

Nodes "attach" to networks. A node can have multiple physical and virtual identities.

  • listen_port: (Optional) Local UDP port WireGuard binds to (default: 51888).
  • physical: (Optional) Reachability. Defines an address for servers, or a list of networks for roaming nodes. Defaults to ["wan"].
  • wireguard: Virtual connectivity. Requires a network name and a virtual address.
  • dns: (Optional) List of DNS servers.
  • subnets: (Optional) Expose local internal networks (like Docker container networks or local VMs) to the WireGuard mesh.
nodes:
  - name: "gateway"
    public_key: "..."
    listen_port: 51888
    dns: ["8.8.8.8"]
    physical:
      - network: "wan"
        address: "vpn.example.com" # Peer Endpoint
    wireguard:
      - network: "production"
        address: "10.0.1.1"       # Virtual IP

5. Inheritance & Overrides

Settings apply hierarchically, resolving in this order:

  1. Attachment Level: Specific to one connection (e.g., nodes[0].wireguard[0]). (Highest priority)
  2. Node Level: Applies to all connections for a specific hardware node.
  3. Network Level: Applies to everyone attached to this virtual or physical network.

Supported Properties

  • mtu: Resolves bottom-up. The most specific definition wins. If unset, it defaults to 1420. (Note: Changing this triggers a brief interface restart/disruption on agents.)
  • dns: Merges and deduplicates across all levels. (Note: Changing this triggers a brief interface restart/disruption on agents.)
  • persistent_keepalive: Resolves bottom-up. The most specific definition wins. If unset, defaults to 25 only when the node itself is roaming (has no endpoint) on the physical network path used to reach the peer.
  • disabled: true: Cascades top-down. Disabling a parent (like a Network or a Node) instantly takes it offline for everyone, regardless of attachment-level settings.

6. Security & Concurrency

Optional top-level security keys:

  • admin_tokens: A list of strings. If set, the UI and API will require an Authorization: Bearer <token> header for ALL access.
  • write_tokens: A list of strings. If set, tokens are required only for mutations (Save/Delete). Read access remains public if you have the Network ID.
  • write_barrier: Integer counter to prevent concurrent overwrites.
admin_tokens: ["secret123"]
write_tokens: ["save-only-secret"]
write_barrier: 42

7. Roaming Nodes

Nodes without a static IP can list accessible physical networks instead (e.g., ["office-lan", "wan"]). They will automatically use the best available path.

nodes:
  - name: "laptop"
    physical: ["office-lan", "wan"] # Roams between LAN and WAN
    wireguard:
      - network: "production"
        address: "10.0.1.50"

8. Strict Isolation (Peers)

By default, nodes in the same virtual network form a Full Mesh. You can override this with an explicit peers list to create Hub-and-Spoke or other custom topologies.

  • peers: (Optional) List of name or public_key values to peer with. If omitted, peers with everyone in the network.
nodes:
  - name: "spoke-node"
    wireguard:
      - network: "production"
        address: "10.0.1.50"
        peers: ["hub-router"] # Only peers with the Hub

9. Name Resolution (DNS Automation)

The WG-CP agent can automatically provision a lightweight CoreDNS server to provide seamless name resolution without OS port conflicts.

Network-Level DNS Policy

Configure forwarding, TTL, and custom static records on the virtual network.

wireguard_networks:
  - network: "vpn"
    upstream_dns: ["1.1.1.1", "1.0.0.1"] # Forward external queries
    dns_ttl: 300                         # Global TTL
    custom_dns:
      - name: "printer.vpn"
        address: "192.168.1.50"          # Infers 'A' record
      - name: "mail.vpn"
        type: "MX"
        value: "10 mail-server.vpn"

Node-Level DNS Hosting

Flag a node to host the DNS service. Other clients automatically receive DNS = <node-ip> in their configurations.

Redundancy: You can enable host_dns: true on multiple nodes. Clients will receive all of their IPs in their DNS configuration, providing automatic failover.

Physical Binding: By default, DNS binds to virtual networks. You can explicitly bind it to a physical network by providing a list (e.g., host_dns: ["office-lan"]). If you do this, ensure the node's physical IP is stable (static IP or DHCP reservation), or CoreDNS will fail to bind if the IP changes.

nodes:
  - name: "gateway-1"
    host_dns: true # Binds to all attached virtual networks
    wireguard:
      - network: "vpn"
        address: "10.0.0.1/32"
        
  - name: "gateway-2"
    host_dns: ["office-lan"] # Explicit binding to a physical network
    physical:
      - network: "office-lan"
        address: "192.168.1.100" # MUST be a static IP
    wireguard:
      - network: "vpn"
        address: "10.0.0.2/32"