Wireguard in Alpine Linux

2025-03-14 · 6 min read

Setting up Wireguard in an Alpine Linux Container

wireguard

One of the more config-sensitive services in a system container (in this case, an Incus-configured LXC) is networking. And although the networking is a bit unusual on a system with VPN, it's not that tricky.

Here are the steps to get Wireguard installed in an Incus LXC container, reverse-engineered from my currently deployed wireguard container's history.

apk add wireguard-tools-wg-quick libqrencode-tools
mkdir /etc/wireguard
cd /etc/wireguard/
umask 077
wg genkey | tee server.privatekey | wg pubkey > server.publickey
vi wg0.conf

Add the following config to wg0.conf:

[Interface]
Address = <some.ip/24>
PrivateKey = <server.privatekey>
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = <server.publickey>
AllowedIPs = <some.net/24>

The ip and subnet are the transit subnet that allows a vpn to act as a gateway into and out of your network, they sit between public and private networks. Now generate the public and private key pair for the client:

wg genkey | tee mobile-privatekey | wg pubkey > mobile-publickey
vi mobile.conf

Add the following to your mobile.conf:

[Interface]
PrivateKey = <mobile-privatekey>
Address = <some.subnet/24>
DNS = <internal dns servers separated by spaces>

[Peer]
PublicKey = <mobile-publickey>
Endpoint = <host.or.publicip:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

Let's recap:

  • Installed some packages
  • Generated server keys
  • Generated server config
  • Generated mobile client keys
  • Generated mobile client configs

Now we need to:

  • Enable ipv4 forwarding
  • Create an rc-service entry to have the vpn come up after each reboot

Let's add ipv4 forwarding to sysctl:

echo net.ipv4.ip_forward=1 | tee -a /etc/sysctl.conf && sysctl -p

This actually has an issue where it doesn't activate after a reboot unless sysctl -p runs. I know there's an easy fix to this, but for now I'll include the command in the start portion of the wg-quick-wg0 service. Let's generate a qr code of your new mobile.conf config. Create /etc/init.d/wg-quick-wg0 and add the following:

#!/sbin/openrc-run
description="wg-quick wg0"
depend() {
need net
need localmount
}
start() {
sysctl -p
wg-quick up wg0
}
stop() {
wg-quick down wg0
}

Now make the service active and part of the startup routine:

chmod a+x /etc/init.d/wg-quick-wg0
rc-update add wg-quick-wg0
re-service wg-quick-wg0 restart

Generate a qr code for the mobile config:

qrencode -t ansiutf8 < mobile.conf

You should have a nice qr code in your terminal (scan it all you want, it's not a gateway to my network):

qr code

Check that the wireguard interface wg0 is up and running, you should see something like this:

wireguard status

Import the qr code from earlier into your mobile Wireguard client and activate the config. That's it.

*
Jules