WireGuard Server: Raspbian Buster
In this tutorial, we setup a WireGuard server on a Raspberry Pi running Raspbian Buster (which is 99% Debian Buster).
At the end of this tutorial, the device will have a virtual network interface
living on private network
The device will be ready to add WireGuard clients.
In this example, I’m using a Raspberry Pi 2 Model B v1.1. This will not work on Raspberry Pi versions prior to 2.
- Follow the installation instructions
- Set a non-default password for user
- Update the base install with
sudo apt update && sudo apt upgrade
Configure the Local Area Network
Ensure that UDP port
51820 on the Raspberry Pi is available to the public internet via a stable IP address.
In this example, the device is connected to a local area network behind a WiFi/NAT router.
The NAT router has public, static IP address
and acts as default gateway for local area network
The NAT router is configured to always assign
to the Raspberry Pi device via DHCP reservation.
TODO take new screenshots
The NAT router is configured to forward incoming network traffic to UDP port
51820 to the Raspberry Pi device.
TODO take new screenshots
For the the rest of this tutorial, we’ll interact with Raspbian via command line interface. Open a terminal as an unprivileged user via the console, the Terminal GUI app, or SSH.
By default, Raspbian doesn’t trust the Debian package repository. Add Debian’s public keys to the trusted set of keys.
$ sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 04EE7237B7D453EC 648ACFD622F3D138 Executing: /tmp/apt-key-gpghome.p9XKvbbATY/gpg.1.sh --keyserver hkp://pool.sks-keyservers.net:80 --recv-keys 04EE7237B7D453EC 648ACFD622F3D138 gpg: key DC30D7C23CBBABEE: public key "Debian Archive Automatic Signing Key (10/buster) <email@example.com>" imported gpg: key E0B11894F66AEC98: public key "Debian Archive Automatic Signing Key (9/stretch) <firstname.lastname@example.org>" imported gpg: Total number processed: 2 gpg: imported: 2
To install the most recent version of WireGuard, we’ll need packages from the Debian unstable release. Add the Debian unstable release, and pin the Debian unstable priority behind Raspbian stable. This allows us to install packages that are not available in Debian stable, while keeping the “stable” versions of everything else.
$ sudo sh -c "echo 'deb http://deb.debian.org/debian/ unstable main' >> /etc/apt/sources.list.d/unstable.list" $ sudo sh -c "printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' >> /etc/apt/preferences.d/limit-unstable"
Update package information from both stable and unstable package repositories.
$ sudo apt update Get:1 http://deb.debian.org/debian unstable InRelease [142 kB] Hit:2 http://archive.raspberrypi.org/debian buster InRelease Hit:3 http://raspbian.raspberrypi.org/raspbian buster InRelease Get:4 http://deb.debian.org/debian unstable/main armhf Packages [7,977 kB] Get:5 http://deb.debian.org/debian unstable/main Translation-en [6,192 kB] Fetched 14.3 MB in 22s (655 kB/s) Reading package lists... Done Building dependency tree Reading state information... Done All packages are up to date.
Install the WireGuard packages.
After this step,
man wg and
man wg-quick will work and the
wg command gets bash completion.
$ sudo apt install wireguard --assume-yes Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: dkms raspberrypi-kernel-headers wireguard-dkms wireguard-tools Suggested packages: python3-apport menu The following NEW packages will be installed: dkms raspberrypi-kernel-headers wireguard wireguard-dkms wireguard-tools 0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded. ... DKMS: install completed. Module build for kernel 4.19.75-v8+ was skipped since the kernel headers for this kernel does not seem to be installed. Setting up wireguard-tools (0.0.20191219-1) ... Setting up wireguard (0.0.20191219-1) ... Processing triggers for man-db (2.8.5-2) ...
In every client/server relationship, each peer has its own private and public keys. Create private and public keys for the WireGuard service. Protect the private key with a file mode creation mask.
$ (umask 077 && wg genkey > wg-private.key) $ wg pubkey < wg-private.key > wg-public.key
Print the private key, we’ll need it soon.
$ cat wg-private.key qPF9uU7qsCbw3uKR1t2Q0gfr2HasTKZGPkCHz2AszUs=
Create the WireGuard Network Device
Create the WireGuard service config file at
(Use a command like
sudo nano /etc/wireguard/wg0.conf.)
# define the WireGuard service [Interface] # contents of file wg-private.key that was recently created PrivateKey = qPF9uU7qsCbw3uKR1t2Q0gfr2HasTKZGPkCHz2AszUs= # UDP service port; 51820 is a common choice for WireGuard ListenPort = 51820
Create the WireGuard network device at
(Use a command like
sudo nano /etc/network/interfaces.d/wg0.)
# indicate that wg0 should be created when the system boots, and on ifup -a auto wg0 # describe wg0 as an IPv4 interface with static address iface wg0 inet static # static IP address address 10.0.2.1/24 # before ifup, create the device with this ip link command pre-up ip link add $IFACE type wireguard # before ifup, set the WireGuard config from earlier pre-up wg setconf $IFACE /etc/wireguard/$IFACE.conf # after ifdown, destroy the wg0 interface post-down ip link del $IFACE
$ sudo ifup wg0
If this fails, then install package
linux-headers-VERSION. It seems that the
Debian WireGuard packages don’t declare that dependency, or it’s just broken in GCP.
$ sudo ifup wg0 RTNETLINK answers: Operation not supported ifup: failed to bring up wg0 $ sudo apt install linux-headers-$(uname -r) Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: ... Fetched 556 kB in 0s (7381 kB/s) Selecting previously unselected package linux-headers-4.19.0-6-cloud-amd64. (Reading database ... 60668 files and directories currently installed.) Preparing to unpack .../linux-headers-4.19.0-6-cloud-amd64_4.19.67-2+deb10u2_amd64.deb ... Unpacking linux-headers-4.19.0-6-cloud-amd64 (4.19.67-2+deb10u2) ... Setting up linux-headers-4.19.0-6-cloud-amd64 (4.19.67-2+deb10u2) ... $ sudo ifup wg0
At any time, verify that the WireGuard configuration for
wg0 is what you expect:
$ sudo wg show wg0 interface: wg0 public key: 2efuG9OYmMPQpbkJ8CVxGlvQflY6p1u+o4wjcgGII0A= private key: (hidden) listening port: 51820
At any time, verify that the
wg0 network interface exists.
$ ip address show dev wg0 7: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 link/none inet 10.0.2.1/24 brd 10.0.2.255 scope global wg0 valid_lft forever preferred_lft forever