While building a network-attached storage (NAS) device based on openmediavault (omv), I wanted to add a virtual private network (VPN) server to provide secure remote access to the NAS and to other resources on the local network. This made sense to me because currently the NAS will be left on at all times. Of course the VPN server will be WireGuard because of my past experience with it. In essence then, I wanted to duplicate what was done with the Raspberry Pi hosting my home automation system on a Intel Core i5-2400 system. Since both Raspberry Pi OS and omv are based on Debian, the procedure to install the VPN is almost identical on both systems as will be shown below.
This is all experimental. In the near future, the local network will be revamped. The plan calls for the addition of a firewall, probably based on pfSense, and the segregation of devices into different VLANs (written, as if I know what I'm talking about!) Clearly, some thought will have to be given to remote access. Time will tell if changes to the VPN servers are required.
Table of Contents
- Re-inventing the Wheel
- Installing WireGuard
- Configuring WireGuard
- Managing Users and Using the VPN
Someone had probably added WireGuard in omv. So I did a quick search and found the beta openmediavault-wireguard plugin. However, development seems to be halted since there has been only one commit in the last 18 months, and that was almost exactly a year ago.
There is also a June 30, 2019 forum discussion [HowTo] WireGuard with omv Super-Easy by henfri with many replies. The discussion starts with an installation script by henfri. I have not used it as it is not as complete as the Adrian Mihalko script which has worked very well on a Raspberry Pi and works just as well in Debian. If the henfri script is used, be aware that it uses UPnP to forward the necessary UDP port at the router. Many recommend disabling UPnP altogether, so perhaps one should forward the port manually or disable UPnP once WireGuard has been installed.
Finally, I will mention the OpenVPN plugin,
openmediavault-openvpn 5.1, found in the usual in the OMV-Extras.org channel. That usually means juggling CA certificates and other complications, but there are advantages to this older VPN, although I will not go into that topic here. I have not tested this plugin.
This was a cursory search and I apologize to everyone whose contribution has been overlooked.
Installing openmediavault on a second generation i5 computer was fairly straightforward following the instructions in the New User Guide - Getting Started with Openmediavault 5. As recommended, all the configuration was done with the omv Web-based administration tool, including defining the host name (
vault in my case), setting up a static IP address, doing system updates and so on. But when I wanted to install a WireGuard VPN, I had to return to the command line and use standard Debian tools.
Version 5.6.1 of omv released February 27, 2021 is based on Debian 10.8 with version 5.10.0 of the Linux kernel. Given that this version of Debian was released on February 6, 2021, it was not too surprising that installing
wireguard was quite straight forward. In what follows, I opened an SSH session as
root from a terminal on my desktop.
Using a terminal from a Linux desktop to the omv machine is very simple: all that is required is to press the hotkey combination (usually AltT) to bring up a terminal emulator and then entering the
ssh command as shown above. Perhaps those using a different desktop operating system might want to use a terminal emulator in a Web browser. There was a plugin called
shellinabox for just that purpose in omv 4. This is no longer available in omv 5 as far as I can determine. There are recommendations to use Dockerized Wetty (weTTY in a Docker) as a replacement for the plugin. I do not have experience with either of these approaches.
Even though a user was added in omv, made a member of the important groups (
sudo etc.), no directory for that user was created in the
home directory. That is why I logged in as
root as shown above which is something I rarely do. In any case, the WireGuard installation requires root privileges, so this will eliminate the need for the
sudo prefix usually needed when installing packages.
Once logged in, I checked that WireGuard was not already present, and then just installed it from the
buster-backports repository. Contrary to past installations in Raspbian and a recent installation in Rasbpberry Pi OS, this was done with a single
Unlike on the Raspberry Pi, the installation was completed in a short time. A quick check verified that the tools were now available. As a further test, the VPN server was started with an empty configuration file.
From there, it is easy enough to check that the WireGuard interface was created and that the VPN server was listening for incoming connections.
Of course, that last command,
wg, did not display much information because no connection was established. Because the Ethernet interface on my system it named
eno1 instead of the classic
eth0, it will be necessary to adapt configuration script later on.
It is necessary to configure Wireguard in order to do anything useful. In the past I used a script by Adrian Mihalko to easily configure WireGuard on the Raspberry Pi. There is nothing in that script that is really Pi centric and it works just as well in the Debian distribution hosting omv. It would be worthwhile to read User management with Wireguard User Management Script written by Adrian Milhalko and return here for more information if needed.
It may be useful to raise a little point here. WireGuard operates a peer-to-peer network. However it is sometimes useful to look at it as a client-server model, such as here where the WireGuard peer running on the omv machine is viewed as a server and the WireGuard peers on various Linux and Android devices are viewed as clients. In the end, peer, server, client and user are all the same thing. Hopefully that will not be a source of confusion.
There are a couple of prerequisites to install:
unzip to extract the script from a downloaded
.zip archive and
qrencode used to generate QR-code images that will make it very easy to configure WireGuard clients on Android and iOS devices.
Next the archive containing the script and supporting files needs to be downloaded and its content has to be extracted to a directory that will be called
wp_config or any other desired name.
In those last two steps a
/root/downloads directory was created and the script archive was moved into it while changing its name to something more meaningful. Instead, it would have been fine to just delete the archive.
WireGuard encrypts the data exchanged over the virtual network. Much like SSH, asymmetric encryption is used to set up the secure session. Both server and client (or peers actually) have private and public keys, but only the latter are exchanged for authentication. Again, like SSH, the private keys have to be shared "out-of-band" beforehand. In this case that means that the keys must be manually copied to each peer configuration file. There is no third party "certificate authority" for SSL certificates as when using HTTPS or OpenVPN.
The first step, which is done only once, is to generate the private and public keys of the WireGuard server on the machine.
These two keys are needed in the next steps. Copy them into a text editor on the desktop or open a second SSH session on the Raspberry Pi for easy access to the keys later.
Normally, one never makes the private key public. So the keys shown above are only for demonstration purposes, and you must replace those values with the one actually generated.
This step, performed once only, creates the
wg.def file which contains data the script will use to make the server and client configuration files.
This is the original content.
And this is how I changed it.
Note the change of the "private" WireGuard subnet from the suggested
192.168.199.0/24. This is because WireGuard is already running on a Raspberry Pi at
_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. And, of course, it is necessary to change
_SERVER_LISTEN to the host name of the Raspberry Pi which, in my (fictitious) case, is:
modomo.twilightparadox.com as explained in 2.2 Public IP Address or Dynamic Host Name. Enter just the domain name without a protocol specifier such as
https://. As I explained above, the public IP address assigned to me by my ISP changes
so rarely that I could get away with the public IP address instead of a host name for testing purposes!
If the CIDR notation
192.168.99.0/24 is not familiar, just think of the trailing integer after the slash as the number of fixed most significant 1 bits in the subnet mask. Well, that's really clear. Perhaps working out the example will help. The subnet mask is 32 bits (or 4 bytes) of which the most significant 24 are 1s and the least significant 8 bits are 0. Hence the mask is 255.255.255.0. So the virtual network peers will have IP addresses in the
192.168.99.xxx block. The server will be at
192.168.99.1, the first client at
192.168.99.2, the second at
192.168.99.3 and so on. The script will handle this sequential allocation of IP addresses automatically.
WireGuardIP addresses at
192.168.99.151on three different single-board computers. Android and Linux clients could connect to each without problems. Nevertheless, this time I chose different subnets altogether to avoid unnecessary complications. Whatever "private" subnet is chosen, care must be taken to avoid IP address collisions with any device already on the local network.
The client configuration template,
client.conf.tpl, used by the script to create each user (or client) configuration file is quite short.
I changed the
Note that the first
192.168.99.1/32) is the address of the Wireguard server on the virtual network and the 32-bit mask means that the client/user will not be able to reach any other IP address on the
192.168.99.xx subnet. The second allowed IP address
192.168.1.0/24, which is the
192.168.1.xxx block of IP addresses corresponding to my home local network. The Raspberry Pi has a static IP address on that network:
192.168.1.22, the ISP supplied cable modem/router is at
192.168.1.1 and its integrated DHCP server allocates IP addresses in the
192.168.1.100-200 range where most of my IoT devices can be found. You will, of course, have to adjust the
AllowedIPs to refer to the correct IP addresses in your particular situation. It could be that your LAN is on subnet
192.168.1.xxx as suggest above, or
192.168.0.xxx, but some LANs use other blocks of private IPv4 addresses such as
In the server configuration template, 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 Ethernet interface is named
eno1 as we saw before, so
it was necessary to edit the sever configuration template.
eth0 interface is replaced by
eno1 in the
PostDown lines that define changes
to the server
iptables when activating or deactivating the
Again, this change needs to be done once only if at all.
When first installing WireGuard and when testing the installation of the server, it is useful to manually start and stop the service. This is done with the
Again when testing, it may be of value to check on the status of the VPN server. This can be done with the
systemd control utility and with the
The above is only an indication of the information that may be displayed. It will depend on the number of peers/clients that have been set up. Even more information will be displayed when a client or peer has created a tunnel (i.e. opened a VPN connection) including the number of bytes transmitted and received through the connection.
Once WireGuard is properly installed, the service should be started automatically. This is done with the usual
This is usually done only once. From then on, whenever the computer is booted,
systemd will start the VPN server. If for some reason the WireGuard service should no longer be automatically started, use the disable command.
It will be possible to enable the service again later. If one thinks about it, a VPN server should really be functioning at all times.
I have already covered in much detail the use of the Mihalko
user.sh script to add or delete users in the WireGuard configuration. In the same post, there are descriptions of how to set up WireGuard clients in Android, Linux and Windows. The post also contains a quick explanation of how to use these clients with the WireGuard VPN. The original file by Adrian Mihalko contains instructions for setting up an iOS client.
There is more to using a self-hosted VPN. Again, my previous post about using WireGuard in Raspberry Pi OS contains information about the need to set up a static IP address for the omv machine (something easily done in omv, by the way), the interest in creating a dynamic host name in order to reach the machine from outside the local network. How to forward the UDP port used by WireGuard at the router is described in the post. Enabling IP forwarding is also described in the post. That is needed if the VPN is used to access resources over the local area network not installed on the omv server.