VPN
WireGuard — in‑kernel, fast, simple
WireGuard is the VPN on Akadata Linux. It runs inside the kernel: no userspace VPN daemon, no per-packet copy between kernel and userspace, and a short configuration language. A WireGuard peer is a few lines of config. Throughput is bounded by the kernel packet-forwarding path and the cost of the AEAD cipher.
The WireGuard kernel module is enabled in the Akadata kernel build. The wg and wg-quick tools are installed with the wireguard-tools package. There is no dedicated init script in Saphira; use wg-quick or create your own OpenRC service.
Key generation
Create your keys
Every WireGuard peer has a private key and a public key. The private key stays on the machine that owns it. The public key is shared with every peer that connects to it.
# Create the key directory with restricted permissions
umask 077
mkdir -p /etc/wireguard
chmod 700 /etc/wireguard
# Generate keys for the server
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key
chmod 644 /etc/wireguard/server_public.key
# Generate keys for a client — do this on the client machine
wg genkey | tee client_private.key | wg pubkey > client_public.key
chmod 600 client_private.key
chmod 644 client_public.key
# Or generate client keys on the server and transfer them securely
wg genkey | tee /etc/wireguard/alice_private.key | wg pubkey > /etc/wireguard/alice_public.key
chmod 600 /etc/wireguard/alice_private.key
chmod 644 /etc/wireguard/alice_public.keyNever share private keys. The public key is the only thing that should leave the machine that owns the private key.
Server configuration
Road‑warrior VPN server
Create /etc/wireguard/wg0.conf:
# /etc/wireguard/wg0.conf — server
[Interface]
Address = 10.99.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY_HERE
# Enable IP forwarding while the tunnel is up
PostUp = sysctl -w net.ipv4.ip_forward=1
PostDown = sysctl -w net.ipv4.ip_forward=0
# Alice\'s laptop
[Peer]
PublicKey = ALICE_PUBLIC_KEY_HERE
AllowedIPs = 10.99.0.2/32
# Bob\'s laptop
[Peer]
PublicKey = BOB_PUBLIC_KEY_HERE
AllowedIPs = 10.99.0.3/32Restrict the configuration file: chmod 600 /etc/wireguard/wg0.conf. To keep forwarding enabled after reboot, persist it: echo net.ipv4.ip_forward=1 > /etc/sysctl.d/99-wireguard.conf. The firewall rules that let the tunnel forward and NAT traffic live in /etc/nftables.conf (see below).
Bring up the interface
wg-quick up wg0
wg show
# Verify the interface is running
ip addr show wg0
ping 10.99.0.1wg-quick up creates the interface, assigns the address, sets the private key, adds peers, and runs the PostUp commands. wg-quick down wg0 tears everything down.
Persist across reboots
#!/sbin/openrc-run
description="WireGuard VPN"
depend() {
need net
}
start() {
ebegin "Starting WireGuard"
wg-quick up wg0
eend $?
}
stop() {
ebegin "Stopping WireGuard"
wg-quick down wg0
eend $?
}Save this as /etc/init.d/wireguard, make it executable, and enable it:
chmod 755 /etc/init.d/wireguard
rc-update add wireguard defaultClient configuration
Connect a client
# /etc/wireguard/wg0.conf — Alice's laptop
[Interface]
Address = 10.99.0.2/32
PrivateKey = ALICE_PRIVATE_KEY_HERE
# Route only VPN traffic through the tunnel (split tunnel)
# DNS = 10.99.0.1 # Optional: use the server as DNS resolver
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
Endpoint = vpn.akadata.ltd:51820
AllowedIPs = 10.99.0.0/24
PersistentKeepalive = 25Split tunnel: AllowedIPs = 10.99.0.0/24 routes only VPN subnet traffic through the tunnel. Your regular internet traffic goes through your local connection.
Full tunnel — route all traffic through the VPN
# On the client:
[Peer]
...
AllowedIPs = 0.0.0.0/0
# For IPv6 tunnels, also configure an IPv6 ULA (e.g. fd00:99::/64) on the
# interface, enable net.ipv6.conf.all.forwarding=1, and add an ip6 NAT rule.
# The server NATs client traffic to the internet. This lives in /etc/nftables.conf
# (see the firewall section); the relevant rule is:
# ip saddr 10.99.0.0/24 oifname "eth0" masqueradeWith a full tunnel the server becomes the client's default gateway. The server must forward and NAT the client's traffic to the internet.
Connect the client
wg-quick up wg0
ping 10.99.0.1
curl http://10.99.0.1
wg showSite‑to‑site
Connect two networks
When two sites each have a private subnet and need to route between them transparently:
Site A — 10.0.0.0/24
# /etc/wireguard/wg0.conf — Site A
[Interface]
Address = 10.99.0.1/24
ListenPort = 51820
PrivateKey = SITE_A_PRIVATE_KEY
PostUp = sysctl -w net.ipv4.ip_forward=1
[Peer]
# Site B
PublicKey = SITE_B_PUBLIC_KEY
Endpoint = site-b.akadata.ltd:51820
AllowedIPs = 10.99.0.2/32, 10.0.1.0/24
PersistentKeepalive = 25Site B — 10.0.1.0/24
# /etc/wireguard/wg0.conf — Site B
[Interface]
Address = 10.99.0.2/24
ListenPort = 51820
PrivateKey = SITE_B_PRIVATE_KEY
PostUp = sysctl -w net.ipv4.ip_forward=1
[Peer]
# Site A
PublicKey = SITE_A_PUBLIC_KEY
Endpoint = site-a.akadata.ltd:51820
AllowedIPs = 10.99.0.1/32, 10.0.0.0/24
PersistentKeepalive = 25AllowedIPs includes both the peer's tunnel address and the subnet behind it. The kernel routes packets destined for 10.0.1.0/24 through the WireGuard tunnel to Site B automatically.
Verify site‑to‑site routing
# On Site A:
ping 10.0.1.1 # Ping a host on Site B's subnet
wg show
# On Site B:
ping 10.0.0.1 # Ping a host on Site A's subnetManagement
Monitoring and debugging
# Show interface and peer details
wg show
# Show just the interface
wg show wg0
# Show transfer statistics per peer
wg show wg0 transfer
# Show the latest handshake for each peer
wg show wg0 latest-handshakes
# Add a peer without restarting the interface
wg set wg0 peer NEW_PEER_PUBLIC_KEY allowed-ips 10.99.0.4/32
# Remove a peer live
wg set wg0 peer PEER_PUBLIC_KEY remove
# Bring the interface down
wg-quick down wg0Firewall — restrict what the VPN can reach
WireGuard is silent when there is nothing to send; if a peer is unreachable, packets are dropped. Use PersistentKeepalive = 25 on a client behind NAT to keep the tunnel alive through stateful firewalls. The rules below restrict what VPN clients may reach on the server and how their traffic is forwarded and NATed. Save them as /etc/nftables.conf and load with nft -f /etc/nftables.conf; enable persistence with rc-update add nftables.
#!/usr/sbin/nft -f
# Akadata Linux WireGuard firewall
# Restrict traffic arriving from the tunnel to the web server only.
# Other interfaces are unaffected because the input policy stays accept.
table inet akadata_filter {
chain input {
type filter hook input priority 0; policy accept;
ct state established,related accept
iifname "wg0" tcp dport { 80, 443 } accept
iifname "wg0" drop
}
# Allow tunnel clients to reach the internet through eth0,
# and let their replies back in.
chain forward {
type filter hook forward priority 0; policy drop;
ct state established,related accept
iifname "wg0" oifname "eth0" accept
}
}
# NAT full-tunnel client traffic out via eth0.
table ip akadata_nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.99.0.0/24 oifname "eth0" masquerade
}
}Man pages: man wg, man wg-quick. Full reference: wireguard.com.
