Using a Docker container for a Wireguard VPN server

I've been using Wireguard for a while when away from my house for a couple of reasons:

  1. Access to my home network's servers, services, and resources.

  2. Security, when accessing the internet via insecure wifi.

  3. Ability to use my PiHole (DNS sinkhole).

It's been working great, but as with everything else, I wanted to put it in a Docker container.

The wireguard.yaml file:

---
version: "2.1"
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:1.0.20210914
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    networks:
      net192:
        ipv4_address: 192.168.1.100
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/Denver
    volumes:
      - /home/tom/.configs/wireguard/:/config
      - /lib/modules:/lib/modules
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped
networks:
  macvlan_net:
    external: true
---

The macvlan_net is, as the name would suggest, a Docker MACVLAN network, so the Docker container will be able to get an IP on my local network (192.168.1.x).

docker-compose -f wireguard.yaml up -d

This Docker container is configured to use /config/ as the directory to store configuration information in, and not the default /etc/wireguard/.

From within the Docker container, generate the private and public keys:

wg genkey | tee /config/privatekey | wg pubkey | tee /config/publickey

The /config/wg0.conf file is similar to our previous Wireguard config file, with a few exceptions:

  1. There are no ufw commands, as ufw isn't installed in the container.
  2. This container uses eth0 as it's public-facing interface.
  3. I'm using a non-default listen port (default for Wireguard is 51820).
[Interface]
Address = 10.0.0.1/24
SaveConfig = true
ListenPort = 51111
PrivateKey = +BfzlVJ6o1n8hRvW4nGhpbhsiyWsCKgIEja6F8alsVg=
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

I edited the wg0.conf file from the Docker host, not from the Docker container, as vim (or vi) is installed.

Once the server's wg0.conf file was created, it was a matter of bringing up the tunnel on the server, and adding peers (clients).

wg-quick up wg0
wg set wg0 peer 4uP7u9NxLSJbHnaYBwQXhF6iXIIzeOjr/U6lQ0kCH3A= allowed-ips 10.0.0.2
wg-quick save wg0

Once the server is set up and running, adding the tunnel on the client side is the same as a non-Docker Wireguard setup.

References

Docker Hub - linuxserver/wireguard https://hub.docker.com/r/linuxserver/wireguard