How to Set Up WireGuard VPN and WireGuard-UI with Docker

Learn how to set up your own WireGuard VPN server and easily manage it via the web-based WireGuard-UI using Docker Compose.

Protecting online privacy and security has become increasingly important in the digital age. A virtual private network (VPN) can help you achieve this by encrypting your internet traffic and routing it through a private network, making it more difficult for anyone to intercept your data.

WireGuard is a relatively new VPN protocol that has gained popularity for its reliability, simplicity, speed, and security. However, setting it up can often be a complicated process. For example, here’s how to do it on Ubuntu.

That’s where WireGuard-UI, a web-based user interface for WireGuard that makes it easier to configure and manage your VPN server, comes in. And to make things even easier, Docker Compose gives you an easy way to integrate both.

This article will explore how to set up a WireGuard VPN and WireGuard-UI with Docker Compose, making it simpler for you to configure and manage your VPN server and clients. By the end of this guide, you’ll have a fully functional VPN running on Docker containers with an easy-to-use web-based management interface.

So without further ado, let’s get to work.

Step 1: Ensure You Have Docker and Docker Compose Installed

Docker is a platform for creating and running applications in lightweight containers, which makes deploying and managing software much more effortless.

At the same time, Docker Compose, which you can think of as an add-on to Docker, is a tool used for defining and running multi-container Docker applications, which is precisely our case.

In other words, we will deploy the WireGuard VPN server and WireGuard-UI, a web-based user interface for WireGuard, “packaged” as a single application using Docker Compose.

The first step is to ensure you have Docker installed on your machine. The easiest way to do this is by running:

docker --version
Verify that Docker is installed.
Verify that Docker is installed.

If you receive a message like the one above, all is well. You have Docker installed on your system.

However, if you get something like “bash: docker: command not foundโ€ฆ” in response, there’s no room for worry. We’ve got you covered, and our detailed guides on installing Docker on Ubuntu, Debian, Linux Mint, Fedora, AlmaLinux, and Rocky Linux will help you get it up and running on your system quickly and easily.

The next step is to ensure that Docker Compose is also installed on your system. Similar to the above example, run:

docker-compose --version
Verify that Docker Compose is installed.
Verify that Docker Compose is installed.

If the command output is similar, congratulations! You have everything you need to install the WireGuard VPN server with the WireGuard-UI web interface by using Docker Compose.

However, if the message is something like “bash: docker-compose: command not foundโ€ฆ” just run the two commands below, and you will have Docker Compose installed on your system in seconds.

sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-composeCode language: JavaScript (javascript)

In addition, if you want an in-depth introduction to Docker Compose, check out our comprehensive guide.

Step 2: Set Up WireGuard VPN Server & WireGuard-UI with Docker Compose

As we already said, Docker Compose allows you to build and run stacks of multiple containers. To use it, you must first create a โ€œdocker-compose.yamlโ€ file that configures the containers for your application.

Create a “wireguard” directory and switch to it.

mkdir wireguard
cd wireguard

Then, using your preferred text editor, create a file named โ€œdocker-compose.yamlโ€:

vim docker-compose.yamlCode language: CSS (css)

Add the following content to it, then save and exit the file.

version: "3"

services:

  # WireGuard VPN service
  wireguard:
    image: linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
      - NET_ADMIN
    volumes:
      - ./config:/config
    ports:
      # Port for WireGuard-UI
      - "5000:5000"
      # Port of the WireGuard VPN server
      - "51820:51820/udp"
    restart: unless-stopped

  # WireGuard-UI service
  wireguard-ui:
    image: ngoduykhanh/wireguard-ui:latest
    container_name: wireguard-ui
    depends_on:
      - wireguard
    cap_add:
      - NET_ADMIN
    # Use the network of the 'wireguard' service
    # This enables to show active clients in the status page
    network_mode: service:wireguard
    environment:
      - SENDGRID_API_KEY
      - EMAIL_FROM_ADDRESS
      - EMAIL_FROM_NAME
      - SESSION_SECRET
      - WGUI_USERNAME=admin
      - WGUI_PASSWORD=password
      - WG_CONF_TEMPLATE
      - WGUI_MANAGE_START=true
      - WGUI_MANAGE_RESTART=true
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: 50m
    volumes:
      - ./db:/app/db
      - ./config:/etc/wireguardCode language: PHP (php)

Remember to change the values of the “WGUI_USERNAME” and “WGUI_PASSWORD” environment variables in the file above to the username and password you will use to access WireGuard-UI.

In addition, it is essential to note that the Docker volumes containing the WireGurard configuration settings (“./db” and “./config “) will be created and made available in the current “wireguard” directory. Modify the YAML file if you decide you want them somewhere else. For example, “/srv/my-wireguard-conf:/etc/wireguard.”

However, if you do this, change the Docker volumes in both the “wireguard” and “wireguard-ui” service parts. This is a must, as the WireGuard-UI must have access to the WireGuard VPN server configurations to manage it.

Step 3: Run the Containers with Docker Compose

Finally, we are ready to run WireGuard VPN Server and WireGuard-UI using Docker Compose. To do this, execute the below-given command from the current โ€œwireguardโ€ directory where the โ€œdocker-compose.yamlโ€ file is located.

Start and run the containers in the background:

docker-compose up -d

The images will start downloading, and Docker Compose will begin to make its magic. The entire procedure will take less than a minute. In the end, you should see a screen similar to the one below, informing you that all containers have been successfully created and started.

Running WireGuard VPN Server & WireGuard-UI with Docker Compose.
Running WireGuard VPN Server & WireGuard-UI with Docker Compose.

Of course, the initial delay before the start of the WireGuard and WireGuard-UI containers will be a one-off, as Docker needs to download the images from the internet first.

All subsequent runs will take seconds since the required Docker images will already be available locally on your Linux system.

Step 4: Configure the WireGuard VPN Server Using WireGuard-UI

You can now open your browser and navigate to “http://server-ip-address.” The WireGuard-UI login page will greet you.

Enter the username and password you set in the “docker-compose.yaml” file via the “WGUI_USERNAME” and “WGUI_PASSWORD” environment variables, then hit the “Sign In” button.

WireGuard-UI login page.
WireGuard-UI login page.

And here is the moment to provide an essential, if not critical, clarification. This guide uses an unencrypted HTTP connection to access the WireGuard-UI. We only do this because it is a virtual machine in our testing lab that we created exclusively for this tutorial for demonstration purposes, after which we will delete it.

Always use only a secured HTTPS connection in your production environment to access the WireGuard-UI management interface. You can ensure this by putting a reverse proxy service in front of the WireGuard-UI with the ability to automatically generate for you free Let’s Encrypt SSL certificates, such as Caddy.

On top of that, if you want to make things even more “techy,” you can bet on using Traefik, an open-source container-focused reverse proxy service that also automatically issues SSL certificates. We use it frequently in our production systems and can confidently say it performs flawlessly.

Step 5: Configure the WireGuard VPN Server

The fun begins here, but don’t worry; we’ll walk you through it smoothly.

To start, switch to the “Wireguard Server” tab. Then in the “Post Up Script” field, put:

iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

And respectively in “Post Down Script“:

iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

In short, this enables packets to and from your WireGuard server to be routed using Network Address Translation (NAT) inside the Docker’s WireGuard container. We won’t go into detail about it because it is outside the scope of this guide.

Then click the “Save” button to save your changes, and finally, hit “Apply Config” to apply them to the WireGuard VPN server.

Configure the WireGuard VPN Server via WireGuard-UI.
Configure the WireGuard VPN Server via WireGuard-UI.

You will be asked if you want the changes to be applied and the WireGuard server restarted. Confirm by clicking the “Apply” button.

Applying settings to the WireGuard VPN Server.
Applying settings to the WireGuard VPN Server.

Go to the “Global Settings” tab and carefully review the information. Your public IP address should be entered in the “Endpoint Address” section. WireGuard-UI will try to find it and fill it in automatically. However, if it fails, you must enter the correct one.

If you need help figuring out your public IP address, our guide on the subject will greatly help.

By default, the system sets the DNS server to โ€œ1.1.1.1,โ€ which works great. However, change it in the โ€œDNS Serverโ€ field if you want to use a different one.

Set the WireGuard VPN Server global settings.
Set the WireGuard VPN Server global settings.

Of course, if you make any changes, remember to apply them by clicking on the “Save” button and then hitting “Apply Config.”

Step 6: Create a New WireGuard Client

To create a new client that will connect to the WireGuard server to establish a VPN connection, click on the “New Client” button in the upper right corner of the WireGuard-UI.

This opens a modal window, where I recommend you enter only the client name and email and leave the other options as they are by default. Iโ€™m convinced you understand what youโ€™re doing if you change them.

Finally, click the “Submit” button to add the client to the WireGuard VPN server.

Add a new WireGuard client.
Add a new WireGuard client.

The WireGuard-UI will do all of the work in the background to generate the necessary public and private keys to enable the VPN connection for the client, as well as automatically set some options related to routing its traffic, the DNS server used, and the internal private IP address it will receive when connecting to the WireGuard server.

If you’re nevertheless curious about what things look like “from the source,” you can look at the final result, which is stored as a JSON file in the “clients” directory of the Docker “db” volume.

WireGuard's client configuration.
WireGuard’s client configuration.

Attention! Never edit this file directly; only through the WireGuard-UI interface provided.

Finally, we want to emphasize something significant. It is essential to remember that whatever changes you make to users, always complete the operations with the “Apply Config” button. Otherwise, your changes will be saved but not applied to the WireGuard VPN server, which may lead you to believe that things aren’t working correctly.

Step 7: Setting Up WireGuard Client

We come to the most exciting part, where we will see the results of our efforts so far โ€“ configuring the client part and connecting it to the WireGuard VPN server.

Switch to the “Wireguard Clients” to see currently available ones.

View WireGuard's clients.
View WireGuard’s clients.

From here on, the approach is now specific as to whether we will make an encrypted VPN connection to the server from a mobile device such as a phone or tablet or a desktop workstation, laptop, etc. We will consider both cases.

Connecting to WireGuard from Linux PC using Network Manager

To get the client’s WireGuard configuration file, click the “Download” button on the respective profile. This action will download a file with the name you assigned to the account through WireGuard-UI and the extension “.conf.”

Download the client's WireGuard config file.
Download the client’s WireGuard config file.

Rename the file to a short and recognizable name without spaces or special characters in it. For example, “vpn-home.conf.” Then import it using nmcli, a NetworkManager CLI tool, by running the following:

nmcli connection import type wireguard file vpn-home.confCode language: JavaScript (javascript)
Importing Network Manager WireGuard profile.
Importing Network Manager WireGuard profile.

If you now go and look at the available network connections on your Linux system, you will see that our new WireGuard VPN connection is added and ready to use.

Network Manager connections.
Network Manager connections.

Click on it to activate it.

The WireGuard VPN connection is up and running.
The WireGuard VPN connection is up and running.

Send a ping from your desktop (WireGuard client) machine to the WireGuard serverโ€™s private network address to ensure everything works properly.

ping -c 3 10.252.1.0Code language: CSS (css)
Test connectivity to the WireGuard VPN server.
Test connectivity to the WireGuard VPN server.

And this is where you have every reason to congratulate yourself because your WireGuard VPN tunnel works as expected!

If you return to the WureGuard-UI and select the “Status” tab, you should see your current active VPN connection there.

List the WireGuard's connected peers.
List the WireGuard’s connected peers.

Connecting to WireGuard from Mobile Device

Things are considerably easier when you need to connect your mobile device to the WireGuard VPN server. Then, you need to download the official WireGuard client for your operating system: iOS users should go to Apple’s App Store, while Android users should go to Google’s Play Store.

After installing the app on your mobile device, from the WireGuard-UI, click on the corresponding user’s “QR Code” button, which will display the QR code containing all of the information required to import the WireGuard’s VPN profile.

Preview WireGuard's QR profile code.
Preview WireGuard’s QR profile code.

Next, open the WireGuard app on your mobile device, choose “Add a tunnel,” then “Create from QR code,” scan the code from the monitor screen, and that’s it. The profile will be imported automatically.

Import WireGuard's VPN profile on a mobile device.
Import WireGuard’s VPN profile on a mobile device.

Then, switch on the profile, and your device will connect to the WireGuard VPN server.

Conclusion

With its modern cryptography, simplicity, and high-performance capabilities, WireGuard has quickly become a popular choice for VPN solutions. Learning how to set up your own WireGuard VPN server and easily manage it via the web-based WireGuard-UI using Docker Compose can benefit individuals and businesses.

First, this can improve your online security and privacy by adding an extra layer of protection when browsing the internet. On top of that, this way, you can also access geographically restricted content and protect your personal and confidential information from potential hackers and cybercriminals.

Setting up may initially seem daunting, but following our detailed guide makes the process smooth and hassle-free. Thank you for using it! Any opinions and comments are most welcome in the section below.

Bobby Borisov

Bobby Borisov

Bobby, an editor-in-chief at Linuxiac, is a Linux professional with over 20 years of experience. With a strong focus on Linux and open-source software, he has worked as a Senior Linux System Administrator, Software Developer, and DevOps Engineer for small and large multinational companies.

Think You're an Ubuntu Expert? Let's Find Out!

Put your knowledge to the test in our lightning-fast Ubuntu quiz!
Ten questions to challenge yourself to see if you're a Linux legend or just a penguin in the making.

1 / 10

Ubuntu is an ancient African word that means:

2 / 10

Who is the Ubuntu's founder?

3 / 10

What year was the first official Ubuntu release?

4 / 10

What does the Ubuntu logo symbolize?

5 / 10

What package format does Ubuntu use for installing software?

6 / 10

When are Ubuntu's LTS versions released?

7 / 10

What is Unity?

8 / 10

What are Ubuntu versions named after?

9 / 10

What's Ubuntu Core?

10 / 10

Which Ubuntu version is Snap introduced?

The average score is 68%