Skip to content

wireguard Module

WireGuard VPN server and peer configuration.

Import

from fscm.modules import wireguard

Requirements

  • WireGuard installed on the system
  • jinja2 package for template rendering

Classes

Server

Dataclass representing a WireGuard server.

from fscm.modules.wireguard import Server

server = Server(
    address="10.0.0.1/24",
    listen_port=51820,
    private_key="server_private_key",
    public_key="server_public_key"
)

Attributes:

Name Type Description
address str Server VPN address with CIDR
listen_port int UDP port to listen on
private_key str Server's private key
public_key str Server's public key
dns str DNS server for clients
post_up str Commands to run after interface up
post_down str Commands to run after interface down

Peer

Dataclass representing a WireGuard peer.

from fscm.modules.wireguard import Peer

peer = Peer(
    name="laptop",
    address="10.0.0.2/32",
    private_key="peer_private_key",
    public_key="peer_public_key",
    allowed_ips="10.0.0.2/32"
)

Attributes:

Name Type Description
name str Peer identifier
address str Peer VPN address
private_key str Peer's private key
public_key str Peer's public key
allowed_ips str IPs the peer can access
endpoint str Peer's public endpoint
persistent_keepalive int Keepalive interval

Functions

server

Create server and peer configurations.

from fscm.modules.wireguard import server, Server, Peer

srv = Server(
    address="10.0.0.1/24",
    listen_port=51820,
    private_key="...",
    public_key="..."
)

peers = [
    Peer(name="laptop", address="10.0.0.2/32", public_key="...", private_key="..."),
    Peer(name="phone", address="10.0.0.3/32", public_key="...", private_key="..."),
]

# Generate configs
server(
    srv,
    peers,
    endpoint="vpn.example.com:51820",
    interface="wg0"
)

This creates: - /etc/wireguard/wg0.conf — Server config - /etc/wireguard/clients/laptop.conf — Client configs


configure_server

Low-level server configuration.

from fscm.modules.wireguard import configure_server

configure_server(
    interface="wg0",
    address="10.0.0.1/24",
    listen_port=51820,
    private_key="...",
    peers=[...]
)

Key Generation

Generate WireGuard keys using the CLI:

# Generate private key
wg genkey > private.key

# Derive public key
wg pubkey < private.key > public.key

Or in Python:

import fscm

# Generate on the server
private_key = fscm.getstdout("wg genkey")
public_key = fscm.getstdout(f"echo '{private_key}' | wg pubkey")

Examples

Complete VPN Setup

#!/usr/bin/env python3
"""Set up a WireGuard VPN server."""

import fscm
from fscm.modules.wireguard import Server, Peer, server

# Server configuration
VPN_NETWORK = "10.100.0.0/24"
VPN_PORT = 51820
VPN_ENDPOINT = "vpn.example.com"

def generate_keys():
    """Generate a keypair."""
    private = fscm.getstdout("wg genkey").strip()
    public = fscm.getstdout(f"echo '{private}' | wg pubkey").strip()
    return private, public

def setup_vpn():
    # Install WireGuard
    fscm.s.pkgs_install("wireguard", "wireguard-tools")

    # Generate server keys
    srv_private, srv_public = generate_keys()

    # Define server
    srv = Server(
        address="10.100.0.1/24",
        listen_port=VPN_PORT,
        private_key=srv_private,
        public_key=srv_public,
        post_up="iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE",
        post_down="iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE"
    )

    # Define peers
    peers = []
    for i, name in enumerate(["laptop", "phone", "tablet"], start=2):
        peer_private, peer_public = generate_keys()
        peers.append(Peer(
            name=name,
            address=f"10.100.0.{i}/32",
            private_key=peer_private,
            public_key=peer_public,
            allowed_ips="0.0.0.0/0"  # Route all traffic
        ))

    # Generate configurations
    server(srv, peers, endpoint=f"{VPN_ENDPOINT}:{VPN_PORT}")

    # Enable IP forwarding
    fscm.lineinfile(
        "/etc/sysctl.conf",
        line="net.ipv4.ip_forward=1",
        regexp=r"^#?net\.ipv4\.ip_forward"
    )
    fscm.run("sysctl -p", sudo=True)

    # Enable and start WireGuard
    fscm.run("systemctl enable wg-quick@wg0", sudo=True)
    fscm.run("systemctl start wg-quick@wg0", sudo=True)

    print("\nClient configs saved to /etc/wireguard/clients/")

if __name__ == "__main__":
    setup_vpn()

Add Peer to Existing Server

import fscm
from fscm.modules.wireguard import Peer

def add_peer(name: str, address: str):
    """Add a new peer to the VPN."""
    # Generate keys
    private = fscm.getstdout("wg genkey").strip()
    public = fscm.getstdout(f"echo '{private}' | wg pubkey").strip()

    # Add to server config
    peer_config = f"""
[Peer]
# {name}
PublicKey = {public}
AllowedIPs = {address}
"""
    fscm.run(f"echo '{peer_config}' >> /etc/wireguard/wg0.conf", sudo=True)

    # Reload WireGuard
    fscm.run("wg syncconf wg0 <(wg-quick strip wg0)", sudo=True)

    # Generate client config
    client_config = f"""[Interface]
PrivateKey = {private}
Address = {address}
DNS = 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
"""
    print(f"\nClient config for {name}:")
    print(client_config)

add_peer("new-device", "10.100.0.10/32")