So far I have installed WireGuard "servers" on a few single-board computers including the Raspberry Pi 1 Model B and the Raspberry Pi 3 Model B. I have also installed WireGuard "clients" on a couple of Android tablets, a recent low-end Android phone and on an old portable
computer running Linux Mint 19. After a few false starts, I must admit that installation is not difficult especially as there is good information
available on the Web. In this post I will give details about installing WireGuard on any Raspberry Pi 2 (version 1.2) and above
Table of Contents
- Prerequisites to Installing WireGuard on a Raspberry Pi 2 v1.2 or above
- Installing WireGuard on Raspbian
- Enabling Access to the Local Network
- Configuring WireGuard
- Install the Adrian Mihalko User Management Script
- Generate the Private and Public Server Keys
- Create and Edit the Server Definition File
- Edit the Client Configuration Template
- Edit the Server Configuration Template
- Create an Empty WireGuard Server Configuration File
- Enable Automatic Start of the wg0 Interface at Boot Time
- Start and Stop the WireGuard Interface Manually
- Check on the Status of the Server
- Managing Users
- Using the WireGuard VPN
- Installing WireGuard on Other Devices
I will describe how to install the WireGuard virtual network server on a Raspberry Pi 3 model B running Raspbian
Buster Lite. The first installation was done on the June 2019 version of
Buster but the last installation was done on the February 2020 version. There is no significant change between these two versions with regard to the installation of WireGuard as far as I can ascertain.
Raspbian Buster Lite Minimal image based on Debian Buster Version: June 2019 Release date: 2019-06-20 Kernel version: 4.19 Version: February 2020 Release date: 2020-02-13 Kernel version: 4.19
The latest version of Raspbian is always available from the Raspberry Pi Foundation Raspbian downloads page. Full versions of Raspbian
Buster are also available if that is the preferred OS. Even if the GUI version is installed, it will be necessary to open a terminal to install WireGuard.
If a newer version of Raspbian is used, then WireGuard may already be installed. As promised, WireGuard is now included in the Linux kernel. Indeed, wg was included in Armbian Bionic loaded onto an Orange Pi PC 2 a couple of months ago. Try the following commands.
If the two programs are found, WireGuard is installed so skip the rest of this section and section 3 and move on to Accessing the Local Network and the sections thereafter on configuring WireGuard. Otherwise the following steps must be performed beginning with a system update and the installation of the Linux kernel headers.
This process is lengthy. Note that in the latest version (Feb. 2020) of
Buster it is version 1.20200212-1 of the kernel headers that is installed and that it is considerably bigger package.
That is it for the prerequisites in Raspbian
dirmngr utility, which performs network operations when managing
and downloading certificates from Debian repositories is already installed in
Wireguard can be installed in
Buster following the updated instructions from Adrian Mihalko and Ryan Govostes (Feb 10, 2020).
I believe these instructions should also work if for some reason, installation is tried on Raspbian Strech as long as the utility
dirmngr is in place before getting WireGuard. Note that I cannot confirm this. If you run into problems, you could consult an older post on the subject: Installing WireGuard on Raspbian Stretch and Buster.
The whole point of hosting a virtual private network on a home network is to get secure access to that local network from anywhere on the Internet. Hopefully, that is it is not currently easily done because it would be a very bad idea to have the local network vulnerable to attacks from any bored script kiddie out there in the nasty world.
If you already have access to an IP camera, a home automation system or a self hosted cloud or NAS then you are probably quite familiar with dynamic host names and port forwarding so that you can skim through the next two steps, but do read carefully about IP forwarding.
All the computers and devices connected to your home network (often called LAN for Local Area Network) are assigned an IP address by the DHCP server which is probably the router provided by your Internet Service Provider (ISP). On my system the router has
192.168.1.1 for an IP address and the Raspberry Pi hosting the VPN server has a fixed IP address:
192.168.1.22. If you think about it, there are many thousands of devices spread around the globe with that particular address. There is no hope that my Raspberry Pi can be reached from outside the LAN using
192.168.1.22 as the destination address. That problem has been solved with clever routing algorithms. All my devices connected to the local network that communicate with sites on the Internet send their traffic to the router at
192.168.1.1. The router then passes each packet on to the ISP, changing the source IP address from say
192.168.1.22 to a public IP address assigned to my network by the ISP. That assigned public IP is unique on the whole of the Internet so that sites that receive packets from devices on my LAN, can reliably reply using as the destination IP the public IP address assigned by my ISP. When the router receives these packets of data, it routes them to the appropriate device on the LAN. There's obviously a little bit of magic going on to keep track of which device gets which packets as they come in, but that's another story. The point is that to talk to my Raspberry Pi from outside the LAN, the public IP address assigned by the ISP must be known. That's not difficult to find. Usually the router admin page shows that information and there are plenty of sites on the Web, such as What Is My IP Address and my-ip.com that will show you your public IP address.
If only it were that simple. Unfortunately, the public IP address cannot be trusted because it is dynamically assigned by the ISP and may change from time to time. Any DHCP server can force a client to reconnect at any time and change the assigned IP at that point. Also, when one logs off a network, the DHCP server will reserve the assigned IP for a certain "lease" time should the client connect again. After the lease time is expired, the IP address is returned to the pool of available addresses that the DHCP server can assign to any new client. I have no idea just how long lease time is but it is not very short. Furthermore, devices like smart speakers and phones seem to be calling the mothership often enough to restart the lease so that I sometimes have the same public IP address for days on end. For the duration of this post, let's say that my sticky dynamic public IP address is
18.104.22.168. Indeed, I could get away with using
22.214.171.124 as the public IP address of my network for testing the WireGuard configuration later on.
In practice though, one should avoid using a dynamic IP address. Instead the local network should be reached through a dynamic host name. DNS is the domain name system which translates the name of a website such as
www.google.com into an IP address (
126.96.36.199). Some sites offer a service, often free, that associates a domain name with an IP address. These sites update the IP addresses in their database at regular intervals. So, we will put in the HTML request the domain name obtained from the DNS service. The DNS will translate this name into an IP address that will be updated each time the ISP assigns a different IP address to the home server. There are plenty of sites on the Web that describe how to set up a dynamic domain name with any one of a number of DDNS providers and among them there is a description of how I did it using freedns.afraid.org back in 2018. So get yourself a dynamic host name, and learn how to signal any change in the public IP address assigned to your network to the DDNS service.
In what follows, my dynamic host name is deemed to be
modomo.twilightparadox.com, which I hope is a fictitious name.
Part of the magic behind the routing of data packets across the router is that each packet must be sent through a "port". Ports are not physical entities, they are more like an apartment number added to a street address to ensure that a letter gets to the proper mail box. In the jargon, they are "end points" of a communication link and must be tacked on at the end of an IP address or host name. As an example, FTP control packets sent from the desktop computer to the Raspberry Pi, have as a destination address
192.168.1.22:21. Some port numbers are implicit. All HTTP traffic is usually sent to port 80, while HTTPS traffic is sent to port 443. Try
https://www.google.com:9090 in a browser. This will send the request to port 9090, which is specified after the colon. The search engine does not "listen" to that port, so nothing will be displayed unless you are very patient and then some sort of error message may appear. Try
https://www.google.com:443 and you will see the familiar search page very quickly, but as you don't have to write the port number, it is implicit the HTTPS protocol.
For security reasons, consumer class routers such as the one supplied by an ISP have a built-in firewall that controls incoming and outgoing network traffic. Typically, outgoing traffic can only be sent out if the end point (i.e. port) is for some "well known" use. Typically, incoming traffic is blocked outright unless it is part of an exchange initiated by a device on the LAN. That is why you can use a Web browser from your home computer to read this post! There's an obvious problem for us. How can the Raspberry Pi be reached if the firewall will not let through IP packets destined to the Pi. So a "hole" has to be punched through the firewall. In technical terms, a port forwarding rule has to be established. That rule will instruct the firewall to send any IP packet addressed to the correct port to be sent on to a Pi.
OpenVPN which is a very popular VPN package uses a default destination port, 1194 to be precise, although that can be changed. Furthermore, whichever port OpenVPN uses, it will identify itself when queried with a port scanner. WireGuard does not have a default port nor will it reply if the port it does use is probed. That means that when configuring WireGuard later on, you will have to choose a port number. The latter are 16 bit integers, which means they have a range from 0 to 65435. However, choosing a number between 0 and 1023 is generally a bad idea. Typically, tutorials on the installation of WireGuard use relatively big numbers such as 53133 which are in the dynamic, private or ephemeral range.
It is difficult to give instructions about implementing port forwarding because each router model is different. On mine, there is a
Port Forwarding tab in the
Basic menu, and a button which displays the window shown below when clicked.
As can be seen the router wants to forward a range of ports, so I specified a range of one port. I used the same port number for the public (Internet facing) port and for the private (local network) port. The latter will be appended to the local IP address,
192.168.1.22. In my case, all IP traffic sent to
modomo.twilightparadox.com:53133 will end up at the outward facing edge of my router as traffic sent to
188.8.131.52:53133. The router will then pass it over to the local network as traffic destined to being sent to
192.168.1.22:53133. If everything is set up correctly, WireGuard will know what to do with it.
If you are having trouble setting up the port forwarding rules on your router, there are sites such as PF Network Utilities that have information about many router models. They also offer utilities that perform various including port forwarding, which I cannot endorse because I am much too paranoid to install such software and much too cheap to pay for it in the first place. I must say that the site provided accurate information about my router, but hidden it was hidden behind a lot of advertising for their products.
If access to other LAN resources such as an IP camera or a Web server is needed, then IP forwarding has to be enabled on the computer hosting the WireGuard server. If you do not enable IP forwarding, you will not be taking full advantage of the virtual private network. I repeat, skipping IP forwarding only makes sense if the only device that needs to be reached from outside with the VPN is the WireGuard host machine.
/etc/sysctl.d/99-sysctl.conf is a symbolic link
/etc/sysctl.conf. It will suffice to edit the later to enable
IP packet forwarding.
as instructed in the configuration.file. A reboot will be necessary for the change to take effect.
The following list of steps might look daunting; it is actually rather easy to configure a WireGuard server and to add clients or peers.
One could follow Adrian Mihalko's guide to manually configure WireGuard, but I found his User Management Script very useful as I use Android tablets as clients on a regular basis. So what follows is mostly a copy and paste operation from the GitHub with just a few hints that might be useful for some.
192.168.99.xxx is used on the local area
network, then the value of
_VPN_NET will need to be changed.
_SERVER_PORT is the
UDP port that will
have to be forwarded to the WireGuard sever by the LAN router or gateway.
This can be (perhaps should be) changed. Change
_SERVER_LISTEN to your dynamic domain name (I have a
post about that Creating a dynamic domain name). In my (fictitious) case, that
Do not put the protocol prefix such as
https://, just the
domain name. As I explained above, the public IP address assigned to me by my ISP changes
so rarely that I could get away with an IP address for testing purposes.
Again, this is a fictitious value; sorry if it is your public IP.
$_PRIVATE_KEY in the field
will be changed to the client private key when a user (i.e. client)
is generated. The first IP address in
AllowedIPs is the IP address of
the host of the WireGuard server being set up. The VPN network was set up
_VPN_NET=192.168.99.0/24 in the
So the server will be the first valid address,
in that subnet. The second IP address,
actually a range:
and on up to
192.168.1.255. It will be possible to reach all those
addresses on the WireGuard server network from the client once the VPN tunnel
is established. Change the second allowed IP to correspond to the
real subnet used on your home local area network. It could be
as suggested above,
192.168.0.xxx is often used, but some LANs
use other private IPv4 addresses such as
It is assumed that the name of the network interface used by the
host of the WireGuard server is
eth0. In my case that
is not correct, the Raspberry Pi is connected by Wi-Fi to the LAN, so
it was necessary to edit the sever configuration template.
eth0 interface is replaced by
wlan0 in the
PostDown lines that define changes
to the server
iptables when activating or deactivating the
This is done once only. The user management script will update this file each time it is used to add or delete a user.
This too is only done once, normally.
There will be more information available when peers/clients have been set up. And even more information will be displayed when a client or peer has created a tunnel (i.e. opened a VPN).
Adrian Mihalko discusses setting up a mobile client on IOS. I will show how to set up a client on an Android table, an old Nexus 7, that I often bring along when I am outside the house. The first step is to install the WireGuard client application which is found in the Google Play Store. After that, here is the procedure used to configure the WireGuard server to accept a connection from the Android app.
█████████████████████████████████████████████████████████████ ████ ▄▄▄▄▄ █ ▄▄▄█ ▄ ██▀ █▄█▀▀▄▄██▄ █▀█ ▄ █▄ ▀██ ▄▄▄▄▄ ████ ████ █ █ █ ▀▄▀█ ██ █▄▀▀▀▄▀▄ ▄▀▄ █ █▄▀▄▄█▀ ▀▄▀█ █ █ ████ ████ █▄▄▄█ █▀▄▀█ ▀▀▀▄▄▀▄▀▄ ▀ ▄▄▄ ▄▄ ▄▄▀█▀▀█▀▀ ███ █▄▄▄█ ████ ████▄▄▄▄▄▄▄█▄▀ █▄▀▄█ ▀▄▀ ▀▄▀ █▄█ █ █ █ █▄█ ▀ █▄█▄█▄▄▄▄▄▄▄████ ████ ▄█▀ ▄▄▀▀▀ ▄ ▄█▀ ▄▀▄ ▀ ▄ ▄█▄ ▄▀██ ▀█▄ █ ▀█▄▀ ▄ ████ █████▀▀▄█ ▄ ▄ █▀▀▄▄▀ ▀██▄▄▄▀▄█▀█ ▄▄▀ █▀ ▀▄▀ ▀▄ ██▀▄█▀ ████ ████▄▄▄▀▀▀▄▀█▀▄██▄▀█ ▀█ ▀█▀█ ▀█▀█▀ ▀ █▀▄█▄█▄██ ▀██▀█ █▀▄▀████ ████▄▄▀▄▀ ▄█▀▄ █▄▄ ▀ ▀█ █ ▀ ▀█▄ ██▄ ▀ █▄▄▀█▄▀▄▄ ▄▀▀ █▄ ████ █████▄▄▄▄█▄ ▄▀▄▄▄▀▀▀▀█ █▀ ▄▄ ▄▄▀▄██ ██ █ ▀ █▀▀█ ▄▀█ █▀▀▀████ ████▀▀▀ ▄▄ ▄▄███▄█ ▀█▄▄ █ ▄█▀██ ▀▄▀ ▄█▄ ▄ ▀ ██▀█▄▀▄█▀▄████ █████▀▄▄█ ▄▄▀██▀█▄ ▄ ▀█ █ ██▀▀▄ ▀▀▀ █ ▄▀▄▄▀██▀▀▀▄▀█▀▀▀▄ ████ ████▀▀▀██ ▄█▄█ █▄▀█▄ ▀ █ ▀ ▄▀█▄ ▄▄▀▀▄▀▄▄▀████▀▄ ▀ ▀▄▀▄▄█████ ██████▄▄ ▄▄▄ █▄▀▄ ▄█▄▀▄▀▄▄▀ ▄▄▄ ▄▄ ▄▀█▀ ▄▄ ▄▄▄ ▄▄▄ ▀▄▀████ █████▀█▀ █▄█ ▄███▄ ▀ ▄▄█ ▀▄ █▄█ ▀█▄▀ ▀█▄ ▄ ▄ ██ █▄█ █ █ ████ █████▄▀ ▄▄ ▄█▀▄█▄▀▄▄█▄ ▄▀▄█▄▄▄▄▄█ ▀ ▀▀▄▀ ▄█▄█ ▀▄▄ ▄▀▀ ████ ████▄ ▄▀▄▄▄▀█▀▀██▄ ▄▀▄█▀ █▀▀█ █▄▀▀▄ ▄█▄ █▀▀▀▄ █▀▄ ▀▄▄▄████ ████▀██ ▄▄▄▄█▄▀██▀▀▀▀▀ ▄▀ █ ▀ ▄███▀▄▄████▀▀ ██▄ ▄ ▀▄▄▄▀██████ ████▄█▀ ▀▀▄█▀█▀▄▀██▄█▀ ▀█▄▀▀▀█ ███▀▄█ ▄█▄ ▄▄▀▀▄ █▀██▄█▄████ █████▀ █▄ ▄ ██▀██▄ ▄▄█▀▀▄▀▀▄█▀ ██▄▀ ▀▄▄█▄▄▀▀▀▀ ██ ▀▀█ ████ ████ ▄▄▀█▀▄ █▀▄ ▀█▀ ▀ █▀▀▀▄▀ █▄█ ▀▀█ ▄▄▀█▄ █ ▀██▄█▀ █ ▄████ ████▄▀▄▄▀█▄▀▄▄▄▀ ▄ ▄█▄▀█▀▄▄ ▄▄█▀█▄▄▄█▄▀▀ ▄█▀ ▀▀▄ ███ ▀ █████ ████▄ ▀▄▄▄▄ ▀ ██ █▄▀ ███ ▄█▀ ██▀█ ▄▀ ▀▀█ ▄███ █▄█▀ ▄▀█ ████ ███████▄██▄█▀ ▀▄▄ ▄ █▄ ██▀█ ▄▄▄ ▀█▀ ▀██▀▄▀▀▀██▄ ▄▄▄ ▀ ▀████ ████ ▄▄▄▄▄ █▀▀█ ▀ █▄██▀▀▄▄ █▄█ ▀██▀▀█▀▀▄ ██▄▄▄ █▄█ ▄ █████ ████ █ █ █▄ ██▄ ▀▀▀ █▄ ▄▄▄▄▄ ▄██ ▀▄███ ▀ ▀██▄ ▄▄ ▄▀▀▄████ ████ █▄▄▄█ █▀█▀ ▀▀▀▄█ ▄▀ ▀▄█▄▀▄ ▀█ ▄█▀█▄█▄ ▀▄▀██▀██▄█ ████ ████▄▄▄▄▄▄▄█▄▄▄▄▄▄▄▄▄█▄█▄█▄██▄█▄▄█▄█▄█▄█▄▄███▄▄█▄▄▄▄▄▄█▄█████ █████████████████████████████████████████████████████████████
Don't worry about the QR code, it can be brought up later. In the meantime, here is the content of the user directory just created.
As with the WireGuard server, the client has two keys, private and public. Two client configuration files are created. One or both of these will be used to configure the Android client. It will be easy to do using the two png images which are QR codes containing the information about each of the client configuration files. Here is the content of the client configuration file and the updated server configuration file.
The two client configuration files are identical except for the
AllowdIPs field. Display the user information again. This time
the two configuration files and the two QR codes will be displayed, but it
will be necessary to scroll back to see them.
Now it is time to install the WireGuard Application from Google Play on the Android device. Launch the application.
Click on the blue button as told.
On a newer Android phone, the choices are displayed in a different fashion, but the same three choices are offered. Click on Create from QR code. Aim the camera towards the QR code displayed on the desktop monitor. Once the information is acquired, the following dialog appears.
I named the tunnel "Rpi3-split" and then pressed on the CREATE TUNNEL button. I repeated the steps to add the second tunnel, named "RPi-all", from the second QR code.
The above screen capture done on the older tablet shows the appearance of the Android WireGuard application once the two tunnels were created . When selecting a tunnel, the "public" information is displayed on the right panel. On the newer telephone, only the tunnel names appear on the screen. In other words, only the left half of the image shown above is visible. Click on a tunnel name to display its configuration information. Click on the left arrow at the top to come back to the list of tunnels.
I have not found a simple way to remove a server entry in the WireGuard
app. What I do instead is to
Export tunnels to zip file in the
app menu (the three vertical dots ፧ ). Then I copy the zip file over
to my desktop machine over a USB connection with the tablet. The content of
the zip file can be edited removing any unwanted server. The modified zip
file is copied back to the tablet. I then erase all application settings. In
the older version of Android installed on my tablet, this is done in
Settings, Storage an USB, Applications, WireGuard,
Erase Data. When the WireGuard app is started, all tunnels will
be gone and pressing on the blue + button will bring up the menu already
shown before. Instead of choosing Create from QR Code choose Create from file or archive to
import the modified zip file containing the tunnel definitions.
Imagine the following scenario. I am sitting in a coffee shop, and I want to see the video feed from an IP camera at home. On the local network, I would start VLC and view the stream at the following address:
rtsp://192.168.1.95/11. On my tablet, I can do exactly the same thing as long as I start the WireGuard application and open one of the tunnels to the VPN server at home.
I just slide the wanted tunnel button to the right as shown above. On my Android phone the connection details would not be displayed but opening a tunnel would be done just the same, by sliding to the right the control beside the desired tunnel. As soon as that is done, I have access to all resources on my home network on
192.168.1.xxx just as if my tablet were connected directly to the LAN. I can therefore watch the
rtsp://192.168.1.95/11 video stream as if I were home. So simple and yet secure. Anyone eavesdropping on the Wi-Fi network in the shop or anywhere along the route between my tablet and my home router would see IP packets with encrypted content. Instead of seeing the address
192.168.1.95:554 from which it could be surmised that there is an IP camera on my home network (554 is the typical RTSP port), the visible address will be
184.108.40.206:53133 which is the public IP address of the router and the obscure port used by the
WireGuard interface which encodes everything else end-to-end, including the final destination address.
Note that the client gives very little feedback. A little key icon signifying the VPN is active will be shown at the top of the tablet screen. But that icon is present even if the settings are wrong or if the WireGuard server at home is not online. The only "symptom" that something is wrong will be that all devices on the
192.168.1.xxx subnet are unreachable!
What if I decide to consult the latest stock market indices? I would start a web browser and go to the say Yahoo! Finance in Canada:
https://ca.finance.yahoo.com/. The destination IP,
220.127.116.11, is not on the
192.168.1.xxx subnet so routing of the packets would not go through the WireGuard tunnel. Instead, packets will be routed directly as if WireGuard were not even running.
If I then want to check my bank balance, I can either start a Web browser and establish a secure HTTPS connection with the bank's Web server or use the Google Play Store app provided by the bank. Either way, I am counting on the built-in encryption of the data exchanged to keep my password and the details of my finances private. However, being paranoid, before checking the balance, I usually start the other tunnel that I named
rpi3-all where the
Allowed IPs field is
0.0.0.0/0. That means all traffic in and out of my tablet in the coffee shop is sent to my home network and from there it is routed to its final destination. So my outgoing financial data is double encrypted on the first leg of its journey out of the coffee shop and incoming data is also double encrypted on the last leg. Maybe I should wear a tin foil hat to protect myself from the nefarious 5G network at the same time because for most of the way, the data is transiting all sorts of bridges, routers, backbones and so on with no more and no less encryption than when I consult my bank balance from my desktop computer at home. Still I find it reassuring to use the "universal" WireGuard tunnel at all times when using a public hotspot. I find there is no perceptible slow down even with the extra hop involved.
Once you have thoroughly tested everything, I suggest it is time to look at all ports that were being forwarded at the LAN firewall. I was able to remove all but one hole punched through for the home automation system, for IP cameras and so on. That was the impetus to use Amazon Alexa exclusively for voice activated home automation tasks and thus get rid of IFTTT with which was not very reliable. Now there's a single small black hole in the firewall. Try it and you too may get a warm fuzzy feeling of security. Hopefuly, I will not regret this in the future.
On older Raspberry Pi models it is necessary to compile WireGuard from the source code. Again, I followed Adrian Mihalko detailed instructions to install the software correctly on a Raspberry Pi 1. I was surprised that the VPN performed adequately even when routing all Internet traffic through it in a coffee shop for better security. My bandwidth demands were usually relatively light. Nevertheless, YouTube videos could be streamed simultaneously on a tablet and portable without noticeable degradation. Of course these were not in high-definition, but then I have no need to view 4K videos in coffee shops in the forseeable future.
Not long after installing WireGuard on the older Raspberry Pi, I did the same on an Orange Pi Zero with an older version of Armbian. It was necessary to compile the source code much in the same way as on the older Raspberry Pi, but there was a bit of a struggle to get the prerequisite packages in place. There is no point in pursuing this any further given that the latest version of Armbian
Bionic includes WireGuard.
The fact that WireGuard is now part of the Linux kernel will only hasten its adoption by an ever-growing number of users. In my opinion, that is a good thing as I have found that using it to host a VPN is very reliable, useful and surprisingly seamless. I suspect that soon installation will no longer be a barrier even on Rasbian, and there will be no real argument against at least giving it a try.