Last updated: 24. September 2026 to reflect the current implementation.
My OpenVPN installations are aging a bit and every time I go from one major operating system version on the server to the next, it takes some effort to adapt the installation. As I am coming closer to such a point again, I was wondering if I should rather spend my time on a different approach. In recent years, an interesting alternative has gained popularity: Wireguard. Now that Ubuntu 24.04 Desktop comes with built-in Wireguard client support, I thought I’d have another look and see how much effort would be required setting up a Wireguard VPN server.
After looking around a bit I decided to go for ‘wg-easy’, a Docker encapsulated Wireguard server that comes with a built-in web-based client certificate management front-end. Also, the project supplies a docker-compose.yml file, so getting an instance up and running in a VM is as easy as adapting a few lines in the yml file and starting the container.
WG-Easy Config in a Nutshell
To get started one can run with the supplied docker-compose.yml file. I chose to modify the location at which where configuration data is stored outside the container, as I prefer to store it in a local directory where the docker compose file is located:
volumes:
- ./etc_wireguard:/etc/wireguard
And that’s it, a ‘docker compose up -d‘ then starts the server. The http web interface on port 51821 can then be used to generate individual configuration files for users. These can then be directly imported on the client devices. I tried with Ubuntu 26.04 and 24.04, and it worked out of the box.
Web-UI Security
You might have noticed that the project itself (only) offers a non-encrypted http based web interface for creating user profiles that requires a reverse proxy frontend. I didn’t want to have a reverse proxy in the VM for encryption, as I’m behind a NAT and can’t route port 80 for the automatic TLS certificate update to the VM. Therefore, I chose to limit TCP port 51821 to localhost. This makes the web interface only accessible directly from the host and via SSH port forwarding, but not directly over the network. Here’s how to do this in the yml file:
ports:
- "51820:51820/udp"
- "127.0.0.1:51821:51821/tcp"
To access the web interface over the network, I use an ssh connection with port forwarding to my notebook. Here’s the command for my admin notebook:
ssh -L 51821:localhost:51821 HOSTNAME
In my local browser on the notebook I can then access the remote server as follows:
http://localhost:51821/
All data to and from the the Wireguard admin-ui thus flows over the ssh connection and is secure. Even better, the http port is not even exposed to the outside world.
Docker and Host Security
There is one other security topic you should be aware of: As Wireguard is a kernel feature, the Docker container it runs in must be allowed to make changes to the network and kernel configuration. In the yml file, this is enabled as follows:
cap_add:
- NET_ADMIN
- SYS_MODULE
Particularly the SYS_MODULE capability gives the Wireguard container a lot of rights outside the container on the physical or virtual host, and it is hence no longer limited to changes that only affect the container itself. Therefore, I chose to run my containerized Wireguard VPN server in dedicated VM rather than on the VM that is the home of the containers of most of my other projects.
And there we go, a few adaptations in the template configuration file and that Wireguard VPN server is up and running. Need another one somewhere else? Just take your yml file, change the password and the IP/domain name in the config file, and you’ve got another instance with a simple ‘docker compose up -d’. Really nice!
So much for now. In a number of follow up posts, I’ll have a look of how to use the VPN server with clients on Ubuntu 22.04, 24.04 and Android.