Last updated Jul 4, 2023

How To Setup Your Own WireGuard VPN Server on Debian 11

# Introduction

Online privacy and security are increasingly important in today’s world, where cyber threats and data breaches are on the rise. Virtual private networks (VPNs) are a popular solution for protecting internet connections and safeguarding sensitive data. WireGuard, a new VPN protocol, offers a faster and more secure VPN option for Linux users. If you’re looking to set up a WireGuard VPN server on a Linux machine, this guide is for you. In this blog post, we’ll walk you through the steps to get started with WireGuard, including installing the software, generating key pairs, creating a configuration file, starting the VPN server, and configuring your firewall on a Debian 11 system. Follow these simple steps to enhance your online security and privacy with WireGuard.

# WireGuard VPN Characteristics:

    • Simplicity – WireGuard has been designed to be a simpler VPN solution than other protocols, with fewer lines of code and a streamlined configuration process.
    • Speed – WireGuard is known for its speed and performance, thanks to its minimal cryptographic overhead and efficient design.
    • Security – WireGuard offers robust encryption and authentication, using the most advanced cryptography available.
    • Cross-platform compatibility – WireGuard can run on various operating systems, including Linux, Windows, macOS, Android, and iOS.
    • Flexibility – WireGuard supports multiple network configurations, making it suitable for various use cases, including remote access, site-to-site connectivity, and virtual private clouds.
    • Automatic reconnection – WireGuard can automatically reconnect VPN sessions if the connection drops, ensuring uninterrupted connectivity.
    • Lower power consumption – WireGuard is designed to be more power-efficient than other VPN protocols, making it ideal for use on mobile devices.

# Prerequisites

For you to follow along with this tutorial, you will need:

    • One Debian 11 server setup with a sudo user and a firewall enabled (I personally use iptables but feel free to use other firewall utilities such as ufw or firewalld). To see how to setup a Debian server, you can follow my How To Setup Debian 11 Server tutorial. This server will be referred to as WireGuard server throughout this tutorial.
    • A computing system acting as a client machine which you will use to connect to your WireGuard server. It will be referred to as WireGuard Peer in this guide. Your WireGuard Peer can either be your local machine, a remote server from Contabo for instance, or even a mobile phone if that’s the way you prefer.

For this tutorial, I will use a VPS Debian server setup on Contabo (My favorite VPS server provider).

# Step 1 – Installing WireGuard on Your Debian 11 Server

We will start this tutorial off with installing the WireGuard package on our Debian server. Let’s first update our Debian server’s package index and then install WireGuard by entering the following commands. If you are prompted to enter your password, enter your sudo user’s password:

sudo apt update
sudo apt install wireguard wireguard-tools

# Step 2 – Generating Private/Public Key Pair

Once WireGuard has been installed successfully on our server, our next step will be to create a private and public keypair for our server. In order to achieve that, we will use the built-in utilities wg genkey and wg pubkey to create our keys. Once created, we will add these to the WireGuard server’s configuration file.

We will also have to modify the permissions on the created key files by using the chmod command, since those files will have read permissions to any user on the system by default.

Enter the following commands to create your WireGuard server’s private key and set the proper permissions:

wg genkey | sudo tee /etc/wireguard/server-private.key
sudo chmod go= /etc/wireguard/server-private.key

Notice how we used the chmod command with go= to remove any permissions for the group and other users which ensures only root will have permissions on the private key file.

The output will look as follow:

This is your WireGuard VPN server’s private key, which is now also stored in /etc/wireguard/server-private.key (thanks to the tee command). Make sure you write down the private key output since we will need it later when setting up the WireGuard server configuration file.

To create the corresponding public key, which is derived from the private key, we will enter the following command:

sudo cat /etc/wireguard/server-private.key | wg pubkey | \
sudo tee /etc/wireguard/server-public.key

The output you will get from this command is your public key, which you should also copy and keep close by for the next steps in this tutorial. The public key can also be found in /etc/wireguard/server-public.key file in case you didn’t write it down! Here is the output:

The public key will be needed to setup any peer that needs to connect to the server, which we will talk about further in this guide.

# Step 3 – Defining The IPv4 Range

In the preceding steps, we covered the WireGuard installation process, including the generation of a key pair for secure traffic transmission to and from the server. In this section and further down, we will define private IPv4 addresses to be used with both the WireGuard Server and peers, and delve further into the configuration of the server, creating a configuration file, and automating the startup process for WireGuard upon server reboot. To choose our IPv4 addresses range which will be used by our WireGuard server and clients for creating a VPN tunnel, we can use the following IP address blocks that are reserved for private networks:
    • to (Class A)
    • to (Class B)
    • to (Class C)
In this tutorial, we will use the IP address block for our first range of reserved IP addresses. This range will enable a total of 255 different peer connections. However, it’s important to choose an IP range that suits your current network configuration and doesn’t conflict with other hosts. Here are some tips to help you optimize your IP address configuration:
    • Use a subnet calculator to determine the appropriate IP address range for your network.
    • Avoid using IP addresses that are already in use by other hosts on your network.
    • Use a consistent naming convention for your hosts and IP addresses to make them easier to manage.
Our WireGuard server will be using one of the IP addresses from the range to create its private tunnel. Here we will use the address, but once again, you can decide to use another address in the range from to or from a completely different range. Write down the IP address you will use for your server since we will use it in the configuration file at Step 4 – Setting Up The WireGuard Server Configuration.

# Step 4 – Setting Up The WireGuard Server Configuration

In order to setup our WireGuard server’s configuration, we will require the following information:

When those elements are gathered, we can finally create a new configuration file by using vim (text editor), or any editor of your choice with the following command:

sudo vim /etc/wireguard/wg0.conf

We can now enter the following lines in this file, while making sure you replace the PrivateKey value with your own server’s private key. In vim, press “i” on your keyboard to enter “Insert mode” and start typing your text, or copying it from below by substituting with your own values:

PrivateKey = uM4RVCS9fRI4D+jm5Uv74+ty/4KIHFz3xMkQVQWuymU=
Address =
ListenPort = 51820
Once you are done, you can save and close the file. In vim, press first on ESC on your keyboard to exit “Insert Mode” and then use the keyboard combination :wq! followed by Enter. This will save the file and quit the text editor. We can now set proper permissions on all WireGuard files as follow:
sudo chmod 600 -R /etc/wireguard/

This way, only root will have permissions on those files which is a better security practice since our private key is in clear text. Our initial WireGuard VPN configuration is now ready and we can continue to our next step.

# Step 5 – Modifying The Network Configuration Of The WireGuard Server

Since we want to route all WireGuard Peer’s Internet traffic to our VPN server, we will now setup IP forwarding on the WireGuard server.

To enable IP forwarding on a Linux system, we will open /etc/sysctl.conf file with vim, but you can also use your favorite text editor like nano if you wish:

sudo vi /etc/sysctl.conf

Simply uncomment the following line by removing the # sign on the left-hand side and save the file:

If the line doesn’t exist yet in your file, insert it manually at the bottom of the file → net.ipv4.ip_forward=1. Once you saved and closed the file, we can enter the following command to read and load the new values from it:

sudo sysctl -p

You will get the following output:

From now on, our WireGuard Server will have the ability to forward incoming traffic from the VPN ethernet interface to others on the server (for example eth0), which will then be forwarded further to the Internet. By using this type of configuration, we will allow our WireGuard Peer to route all web traffic through our WireGuard server’s IP address, which will result in hiding our client’s public IP address.

Before we can route web traffic via our VPN server, we will need to setup several firewall rules using iptables, a Linux utility that allows us to configure IP packet filtering rules of the Linux kernel firewall. This way, we can ensure that all traffic between our WireGuard Server and Peers will function correctly.

# Step 6 – Setting Up The Firewall For The WireGuard Server

As mentioned above, we will have to add firewall rules on our WireGuard’s server to make sure traffic is routed between server and clients properly.

In order to allow WireGuard VPN traffic via our server’s firewall, we will use a method called masquerading, which is the process of translating IP addresses in a covered-up way to correctly route client connections, better known as Network Address Translation (NAT). This way, the source IP of our WireGuard client will be replaced and hidden by the IP of the WireGuard server.

Let’s first start by finding the name of our server’s main network interface as follow:

ip -c a
We can see from the output below that our main network interface is eth0 (public IP address):
Therefore, in order to setup our IP masquerading, we will run the following iptables command:
sudo iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE

Since iptables is case-sensitive, make sure you enter the commands correctly by using caps where needed! Moreover, let’s not forget to allow SSH traffic to our server if you did not do it yet during server initial setup:

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Now we can add the required firewall rules to our WireGuard Server by entering the following commands:

sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
sudo iptables -A INPUT -s -p udp --dport 53 -j ACCEPT
sudo iptables -A INPUT -j DROP
sudo iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wg0 -j ACCEPT
sudo iptables -A FORWARD -j DROP
By adding these rules, we are doing the following:
    • iptables -A INPUT -p udp –dport 51820 -j ACCEPT – This rule opens UDP port 51820 to allow WireGuard Peer connections to our server.
    • iptables -A INPUT -s -p udp –dport 53 -j ACCEPT – With this rule, we tell our firewall to accept DNS requests initiated by our WireGuard peers that are part of the network, since we will setup our clients to send DNS requests to the VPN server in a further step.
    • iptables -A INPUT -j DROP – This rule will then drop any packages that do not meet previous criterias in the iptables INPUT chain. Therefore, make sure you have allowed SSH access before adding that rule or you will be locked out of your server!
    • iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT – This rule will allow our peer’s traffic to be forwarded from our WireGuard interface wg0 to the Internet via eth0.
    • iptables -A FORWARD -i eth0 -o wg0 -j ACCEPT – Vice versa, when traffic from the Internet on eth0 is going back to our WireGuard’s peer on wg0, we need to allow it with this rule.
    • iptables -A FORWARD -j DROP – Lastly, we drop all traffic that does not meet the above criterias.
We can now save our firewall rules permanently to make sure they will be loaded during boot. To do that, we will install the iptables-persistent package, which makes it really easy to save those firewall rules to the proper file automatically. Install the package with the following command:
sudo apt install iptables-persistent

Then save the rules as follow:

sudo iptables-save | sudo tee /etc/iptables/rules.v4

This should get you the following output:

At this point, our WireGuard Server is now properly configured to receive and handle VPN traffic. Thanks to our firewall rules, we can now start the WireGuard service to accept peer connections.

# Step 7 – Installing a DNS Resolver on WireGuard Server

Since we will set the VPN server as the client’s DNS server, the VPN server must be running a DNS resolver. Therefore, let’s install the bind9 DNS server package:

sudo apt install bind9

BIND will automatically start after installation is complete and will also be enabled at boot by default. We can check its status with:

systemctl status bind9

Let’s look at the output:

● named.service - BIND Domain Name Server
Loaded: loaded (/lib/systemd/system/named.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-04-28 14:50:56 UTC; 24min ago
Docs: man:named(8)
Main PID: 545 (named)
Tasks: 5 (limit: 1146)
Memory: 16.4M
CPU: 46ms
CGroup: /system.slice/named.service
└─545 /usr/sbin/named -f -u bind -4

Once we confirmed that BIND is running and is enabled at boot, let’s go ahead and edit its configuration:

sudo vi /etc/bind/named.conf.options

Let’s then add the following parameter in this file to allow VPN clients to send recursive DNS queries:

allow-recursion {;; };

It should look like this:

We can now save and close this file and edit /etc/default/named file, which is used to define BIND configuration options. We will add the following line at the bottom of the file:

OPTIONS="-u bind -4"

With these paramters, we define the user under which the BIND service should run which is bind and we force the BIND service to listen to IPv4 addresses only. Once again, we save and close the file.

BIND enables DNSSEC by default, ensuring that DNS replies are accurate and unaltered. However, due to trust anchor rollover and other factors, it might not function right away. The managed key database can be rebuilt using the following commands to make it function correctly.

sudo rndc managed-keys destroy
sudo rdnc reconfig

Now we need to restart the bind service to make sure those changes are reflected.

sudo systemctl restart bind9

# Step 8 – Launching The WireGuard Server

WireGuard has a built-in wg-quick script that allows us to run our VPN server as a systemd service. This is a better option to setting up a VPN tunnel manually every time, since it is less error prone and easier to run. Therefore, we can use systemctl in order to manage our tunnels, by using the wg-quick script.

Even better, using a systemd service allows us to start WireGuard at boot time so we can connect to our VPN server as long as the server itself is running. Let’s enable the wg-quick service for the tunnel we created in /etc/wireguard/wg0.conf using systemctl:

sudo systemctl enable wg-quick@wg0.service

Now let’s start the service:

sudo systemctl start wg-quick@wg0.service

We can then verify that the service is active with this command:

systemctl status wg-quick@wg0.service

The output should show us that the service is active and enabled:

Now that our WireGuard server is running, we can create our WireGuard Peer’s configuration and finally connect to the server. Exciting right?

# Step 9 – Setting up a WireGuard Peer’s Configuration

Our WireGuard Peer’s configuration is going to be similar to our server. We will need to install the software package, generate a public and private key pair, choose which IP address will be used for the peer and setup its configuration. Then, we will be able to start the tunnel, also by using the wg-quick script.

We can add an unlimited number of peers, as long as our server can handle all connections depending on its resources. Make sure however to keep track of all peer’s private IP addresses to avoid collisions.

Let’s now configure our first WireGuard Peer by installing the WireGuard package using the apt command, since we are installing it on a Linux client in this tutorial. Run the following commands to update the packages index and install WireGuard:

sudo apt update
sudo apt install wireguard
Please note that in order to configure a DNS server, we will also have to install the openresolv package on the VPN client:
sudo apt install openresolv

# WireGuard’s Peer Key Pair Creation

Using the same procedures as on the server, we must now generate the key pair on the peer. Let’s create the peer’s private and public key using the following commands from our local computer or a remote server that will act as the peer:

wg genkey | sudo tee /etc/wireguard/client-private.key | wg pubkey | \
sudo tee /etc/wireguard/client-public.key

# WireGuard’s Peer Configuration File Creation

Having created the peer’s key pair, we can now generate a configuration file for the peer that contains all the data it needs to connect to our WireGuard Server. The configuration file requires the following details:
    • Address: Enter the VPN client’s private IP address.
    • DNS: Enter the VPN server’s address as the DNS server. The resolvconf command will be used to configure it. For redundancy, you can optionally provide additional DNS servers as follows: DNS =
    • PrivateKey: The client’s private key, which is stored on the client computer in the file /etc/wireguard/client-private.key.
    • PublicKey: The server’s public key, which is stored on the server in the file /etc/wireguard/server-public.key.
    • AllowedIPs: refers to the entire Internet, hence all Internet traffic must go through our VPN server.
    • Endpoint: The VPN server’s public IP address and port. Substitute with the actual public IP address of your VPN server.
    • PersistentKeepalive: To maintain the connection, send an authorized empty packet to the peer every 25 seconds. The VPN server might not be able to ping the VPN server if PersistentKeepalive is not enabled.
Once we gathered the above information, let’s create our configuration file by using vi, or any other editor your prefer. Enter the following command on your VPN client:
sudo vi /etc/wireguard/wg-client0.conf

Now let’s insert the following lines in the file (you can copy them and substitute the required data accordingly):

Address =
PrivateKey = 2Ayu/cVBUc2WeKyJNMMT0pv0Vc5OgO7xVjwGGYbOXEo=

PublicKey = mxV+XMNC+J4TBIUOMDzLdYzTlOxz9cSTc+XT1v1TCQw=
AllowedIPs =
Endpoint =
PersistentKeepalive = 25
We can now save and close the file by pressing the Esc key on our keyboard to quit insert mode and by typing :wq! (Will only work if you use vi). Now let’s set proper permissions on all files in the /etc/wireguard directory so only root can read and write those files:
sudo chmod 600 -R /etc/wireguard

# Step 10 – Adding Peers to WireGuard Server Configuration

One of the last steps before we can connect our peer to the server, which is the whole point of this tutorial, is to add the peer’s public key and IP address to the WireGuard server. If you didn’t write down or copy the VPN client’s public key, you can enter the follwowing on the peer’s computer to output the public key:

sudo cat /etc/wireguard/client-public.key

Great let’s copy that value and log into our WireGuard server. Open the file /etc/wireguard/wg0.conf and add the following lines in it (Green text), right under the existing configuration we already added earlier (Written in white):

PrivateKey = uM4RVCS9fRI4D+jm5Uv74+ty/4KIHFz3xMkQVQWuymU=
Address =
ListenPort = 51820

PublicKey = oEw2LSSYZrXaRh1EmbuDBUpIHvXvBBKBQxmuKPIgEFs=
AllowedIPs =

Awesome we can now save and close the file and finally go to the final step which is what this tutorial is all about!

# Step 11 – Starting the WireGuard Tunnel on the Peer

The moment we’ve all been waiting for has finally come!

Now that our server and peer are both configured, let’s connect the peer to the VPN tunnel for the first time. In our case, we will use the wg-quick command to activate the VPN tunnel manually on the peer.

To start WireGuard on the VPN client, we will enter the following command.

sudo systemctl start wg-quick@wg-client0

Now let’s make sure WireGuard gets started automatically at boot time on the VPN client (if that’s the desired behaviour of course).

sudo systemctl enable wg-quick@wg-client0

Let’s quickly make sure that the service is running and enabled.

sudo systemctl status wg-quick@wg-client0
● wg-quick@wg-client0.service - WireGuard via wg-quick(8) for wg/client0
     Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled; vendor preset: enabled)
     Active: active (exited) since Thu 2023-06-22 00:09:27 CEST; 3s ago
       Docs: man:wg-quick(8)
    Process: 81058 ExecStart=/usr/bin/wg-quick up wg-client0 (code=exited, status=0/SUCCESS)
   Main PID: 81058 (code=exited, status=0/SUCCESS)
        CPU: 88ms

Visit the following link to check your public IP address: If everything went according to plan, the public IP address of your VPN server rather than that of your client machine should be displayed.

If that’s the case, congratulations! You just setup your own WireGuard VPN server and are now browsing the web with more privacy and security. If not, keep reading for some troubleshooting instructions.

# Troubleshooting Instructions

If you need to read those instructions, it’s probably because you are having trouble making this whole thing work. Most of the time, it is simply due to a misconfiguration such as you forgot a semi-colon in a configuration file or maybe the firewall that is not allowing the WireGuard port for instance. Let’s take a look at some common issues with WireGuard VPN and how to fix it.

# Unable to browse the Internet

Let’s say your VPN tunnel has been established successfully but you are not able to browse the Internet. Moreover, your IP address is still your VPN client’s public IP address instead of the server’s IP address. This is probably because the masquerading firewall rule is not set properly. Read Step 6 – Setting Up The Firewall For The WireGuard Server and make sure to add the firewall rule properly. By the way, if you need to delete a firewall rule, look at your current firewall rules first and display their numbers as follow:

sudo iptables -L --line-numbers

The –line-numbers option will display the rule number for each firewall rule that are setup. The output will look like this:

Now in our case, we need to check the masquerading rule so we need to add another parameter to our command in order to display the nat table rules:

sudo iptables -L -t nat --line-numbers

Your output should look like this:

In this case, we only have one rule in the POSTROUTING chain of the nat table. Since this is rule number one, we can then delete it as follow:

sudo iptables -t nat -D POSTROUTING 1

If you do not get any error message, it means that the masquerading rule has been deleted successfully. We can now add it again as mentioned above.

# Error messages when pinging

To test if your VPN tunnel is working properly, you can try to ping one of the VPN clients (for example ping If you get the following error message while pinging, you should make sure your AllowedIPs parameter is correct and matches the VPN client’s IP from the tunnel.
ping: sendmsg: Required key not available

Another error message you could receive when trying to ping is:

ping: sendmsg: Destination address required

If that’s the case, make sure your private/public key are correctly set in the configuration files.

# Conclusion

In this lesson, we learned how to set up both the server and client systems with the WireGuard package and tools. On the server, we used the sysctl command to adjust kernel settings to allow packet forwarding and set up firewall rules for WireGuard. In addition to learning how to create private and public WireGuard encryption keys, you also learned how to set up the server and a peer (or peers) to communicate with one another. I hope you enjoyed it and don’t forget to leave a comment! 

Recent Posts

Recent Comments

No comments to show.



Submit a Comment