Installing WireGuard with Docker on Debian 10

Installing WireGuard with Docker on Debian 10

WireGuard is a secure and painless VPN service that runs on a variety of operating systems, including Android and iOS. New clients can easily connect to the service by simply pointing to a QR code.

In this tutorial we will look into installing WireGuard using Docker on Debian 10.

Starting on Linux kernel version 5.6, WireGuard is shipped as a built-in module, but, at the time of writing this post, the stable Debian 10 (Buster) still uses the Linux kernel version 4.19.

Why run it on Docker though?

You may be asking yourself, why bother using Docker when WireGuard is part of the Linux kernel now? I personally like the portability of Docker, that allows moving of a docker-compose.yml around and turning up services within seconds.

Prerequisites

The Docker image we will be using (linuxserver/wireguard) relies on the WireGuard kernel module available at the host so we need to upgrade the Linux kernel from 4.x to 5.x.

Installing Linux kernel 5.x on Debian 10

The version 5.x of Linux kernel images can't not be found in the main Debian stable repositories. This is where Debian Backports come in. Backports are packages taken from the next Debian release (called "testing"), adjusted and recompiled for usage on Debian stable.

1. Add the backport repositories to apt source lists:

echo "deb http://deb.debian.org/debian buster-backports main" > \
(out)/etc/apt/sources.list.d/backports.list

2. Update the packages list:

apt-get update

3. Install the latest Linux image from backports:

apt -t buster-backports install linux-image-amd64

4. Reboot the system so it boots with the new image:

reboot

5. We can confirm the latest Linux image being used by:

uname -r
(out)5.10.0-0.bpo.8-amd64

Running WireGuard on Docker

1. Let's create a  dedicated folder to keep our new WireGuard container:

mkdir -p /srv/docker/wireguard && cd /srv/docker/wireguard

2. On our docker-compose.yml file, we will create a WireGuard container using the linuxserver/wireguard image that listens on port 51820/udp:

vi docker-compose.yml
(out)services:
(out)  wireguard:
(out)    image: ghcr.io/linuxserver/wireguard
(out)    container_name: wireguard
(out)    cap_add:
(out)      - NET_ADMIN
(out)      - SYS_MODULE
(out)    environment:
(out)      - PUID=1000
(out)      - PGID=1000
(out)      - TZ=America/New_York
(out)      - SERVERURL=myserver.domain
(out)      - PEERS=mylaptop,myphone,myserver
(out)    volumes:
(out)      - ./data/config:/config
(out)      - /lib/modules:/lib/modules
(out)    ports:
(out)      - 51820:51820/udp
(out)    sysctls:
(out)      - net.ipv4.conf.all.src_valid_mark=1
(out)    restart: unless-stopped

There's a lot to digest on this configuration file but I'd like to focus on what's most relevant for our WireGuard service.

  • SERVERURL: Can be set to an external IP or domain name. If set to auto, the container will try to automatically set to the external IP.
  • PEERS: This is where we put our clients (peers); it can be a number or a list of names.
  • ./data/config:/config: This is the location where the configuration files will be stored, along with the QR Codes. If the folder doesn't exist one will be created. You can change it as needed.
  • More details about the other parameters can be found at the official page of the linuxserver/wireguard Docker image.

3. Finally, let's start our new container. When we do this for the first time Docker has to download all the images:

docker-compose up -d
(out)Creating network "wireguard_default" with the default driver
(out)Creating wireguard ... done

And if we edit the docker-compose.yml file, let's say, to add more peers, we can recreate the new configurations by:

docker-compose up -d --force-recreate
(out)Recreating wireguard ... done

Just remember to configure your firewall to allow incoming traffic to port 51820/udp (or port of choice), otherwise peers won't be able to connect.

Connecting new clients

First we need to recover the QR Code created for our peer; those are automatically generated when the container starts based on the PEERS parameters in our docker-compose.yml:

docker exec -it wireguard /app/show-peer myphone
Alternatively, we can find the QR Code and the configuration file in our Docker data folder, e.g., /srv/docker/wireguard/data/config/peer_myphone.

WireGuard Client on Android and iOS

The WireGuard app can be found both on Android and iOS. After installing it:

  • Click on the Add icon
  • Select Scan from QR Code
  • Point your camera to the QR Code shown on the terminal
  • Give the tunnel a name, and finally
  • Enable the WireGuard tunnel by toggling it on.
The first time we use this app it may ask for additional permissions to control your device connection, that's expected.

WireGuard Client on Debian and Ubuntu

1. Install WireGuard package:

apt-get install wireguard

2. On the client, we will create a wg0.client file with the content of the generated peer configuration from the WireGuard server.

vi /etc/wireguard/wg0.conf
(out)[Interface]
(out)Address = ...
(out)PrivateKey = ...
(out)ListenPort = ...
(out)DNS = ...
(out)
(out)[Peer]
(out)PublicKey = ...
(out)Endpoint = ...
(out)AllowedIPs = 0.0.0.0/0, ::/0
If you get an error like /usr/bin/wg-quick: line 32: resolvconf: command not found you may need to apt-get install openresolv.

3. Finally, we bring the tunnel interface up:

wg-quick up wg0

4. Check  the new external IP on MyIP.com.


References