one day of code

Wireguard VPN Server on rpi (Alpine Linux)

May 13, 2021

This will be a bit longer tutorial than usual one-liners, but it’ll be as simple as it can be. Basic knowledge of linux is required.


apt add wireguard-tools

Generate keys for server and client

You can repeat key generating process for clients as much users as you need. Store keys somewhere safe. These files don’t have to be on the machine itself, we just need the content of those files.

# Generate server keys
wg genkey | tee privatekey-server | wg pubkey > publickey-server
# Generate keys for 1 client
wg genkey | tee privatekey-user-1 | wg pubkey > publickey-user-1

Server config

Create config file at: /etc/wireguard/wg0.conf, paste this and update values that you want:

Address = # New (non-existing) local LAN subnet or domain IP
ListenPort = 51820 # Connection UDP port
PrivateKey = <privatekey-server> # Private SERVER key string (not file path)
PostUp = /home/pi/ # Script that will run after the VPN server is started
PostDown = /home/pi/ # Script that will run after the VPN server is shut down
PublicKey = <publickey-client-1> # Public CLIENT key string (not file path)
AllowedIPs = # Client IP (defined in CLIENT config). Must end with '/32'.

If you need more clients, then copy and paste the entire [peer] section and update values accordingly.

Create two new files in /home/pi/ named and, make them executable by typing in terminal chmod +x Also, change interface name in both files if you’re using eth0 instead predefined wlan0.

#!/usr/bin/env bash
set -ex
# Traffic forwarding
iptables -A FORWARD -i %i -j ACCEPT
iptables -A FORWARD -o %i -j ACCEPT
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
sysctl -w net.ipv4.ip_forward=1

#!/usr/bin/env bash
set -ex
# Traffic forwarding
iptables -D FORWARD -i %i -j ACCEPT
iptables -D FORWARD -o %i -j ACCEPT
iptables -t nat -D POSTROUTING -o wlan0 -j MASQUERADE
sysctl -w net.ipv4.ip_forward=0

Create service to start wireguard on boot

  1. Go to /etc/init.d directory
  2. Create file with name “wireguard” and content below.
  3. Make file executable chmod +x wireguard
  4. Add to rc-update: rc-update add wireguard default
depend() {
need localmount
need net
start() {
ebegin "Starting wireguard"
/usr/bin/wg-quick up wg0
eend $?
stop() {
ebegin "Stopping wireguard"
/usr/bin/wg-quick down wg0
eend $?

Client Config

Create new config as follows:

Address = # Unique client IP used in server config. Must end with `/32`.
DNS = # DNS (current is set to AdGuard, can be changed to or
ListenPort = 51820 # Port to which we're connecting defined in server config
PrivateKey = <privatekey-user-1> # Private CLIENT key string (not file path)
AllowedIPs = # All trafic goes through VPN
Endpoint = <SERVER-IP>:51820 # DDNS url or IP or Domain name with given port defined in server config
PersistentKeepalive = 25 # Send keepalive every X seconds
PublicKey = <publickey-server> # Public SERVER key string (not file path)

NOTE: Information about client’s [peer] AllowedIPs:

  • - All trafic from client device is gonna go through the VPN server.
  • - VPN will be used only for traffic to/from server. Everything else goes through current network.
  • - (router subnet) all your local network will be available. Everything else is same as above.

You can combine these two last subnets as, This way you’ll have access to your server and your local LAN network at the same time while all other traffic is handled by your current network.

The Conclusion

That’s it. You now have a functional VPN server. The benefit is that all your traffic (Through VPN) will be checked against AdGuard’s DNS server so all the ads will be removed from the responses, that way you get ad-free web experience.


You have entered both subnets as AllowedIPs value. You’re gonna have access to your google home, tv, rpi, NAS, Smart home… That will all go through the VPN and you can mess with the people at home by turning on/of light etc. But now you visit,… and that traffic will not go through the VPN… unless you entered, then everything will go through the VPN and ads will be stripped from the response._

Written by Milan Miljkovic — a tech enthusiast and design system practitioner.