Be sure to have system up to date: dnf update Install kernel headers: dnf install -y kernel-headers.x86_64 kernel-devel Check: ls -l /usr/src/kernels/$(uname -r) Install wireguard kernel module: dnf install -y epel-release elrepo-release -y dnf install -y kmod-wireguard wireguard-tools Create persistent directory for container: mkdir -p /app/persistent_docker/wireguard cd /app/persistent_docker/wireguard Run container: docker run -d \ --name=wireguard \ --cap-add=NET_ADMIN \ --cap-add=SYS_MODULE \ -e TZ=Europe/London \ -e SERVERURL=ssh.databasepro.eu `#optional` \ -e SERVERPORT=51820 `#optional` \ -e PEERS=1 `#optional` \ -e PEERDNS=auto `#optional` \ -e INTERNAL_SUBNET=10.10.10.0 `#optional` \ -e ALLOWEDIPS=0.0.0.0/0 `#optional` \ -p 7006:51820/udp \ -v /app/persistent_docker/wireguard:/config \ -v /lib/modules:/lib/modules \ --sysctl="net.ipv4.conf.all.src_valid_mark=1" \ --restart unless-stopped \ ghcr.io/linuxserver/wireguard At the first run that will create configuration under `/app/persistent_docker/wireguard` In logfiles, we have the QR-code to use clint side. A client configuration ready to use is generated under `/app/persistent_docker/wireguard/peer1` Example configuration server side: [Interface] Address = 10.10.10.1 ListenPort = 51820 PrivateKey = ******************************* PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] # peer1 PublicKey = ******************************* AllowedIPs = 10.10.10.2/32 Example configuration client side: [Interface] PrivateKey = ******************************* ListenPort = 51820 Address = 10.10.10.2/32 DNS = 10.10.10.1 [Peer] PublicKey = ******************************* AllowedIPs = 0.0.0.0/0 Endpoint = ssh.databasepro.eu:41820 In the previous example, the NAT rule has been defined in the router: `ssh.databasepro.eu:41820->(by UDP)->[docker host]:7006`. > I guess it was something special on my system (maybe because the host is also Name Server) but to make it working I modified `coredns/Corefile` as: . { forward . 1.1.1.1 192.168.0.8 } If you want use `docker-compose` to start the container, `docker-compose.yaml`: version: "2.1" services: wireguard: image: ghcr.io/linuxserver/wireguard container_name: wireguard cap_add: - NET_ADMIN - SYS_MODULE environment: - TZ=Europe/London - SERVERURL=ssh.databasepro.eu #optional - SERVERPORT=51820 #optional - PEERS=1 #optional - PEERDNS=auto #optional - INTERNAL_SUBNET=10.10.10.0 #optional - ALLOWEDIPS=0.0.0.0/0 #optional volumes: - /app/persistent_docker/wireguard:/config - /lib/modules:/lib/modules ports: - 7006:51820/udp sysctls: - net.ipv4.conf.all.src_valid_mark=1 restart: unless-stopped Start the container with `docker-compose`: docker-compose up -d Troubleshooting --------------- One time, after a kernel upgrade, wireguard stopped to work with the error message: iptables v1.6.1: can't initialize iptables table `filter': Table does not exist (do you need to insmod?) Perhaps iptables or your kernel needs to be upgraded. Issue solved reloading `iptable_nat` module: modprobe iptable_nat To load automaticly this module on system reboot, create the file `/etc/modules-load.d/iptable_nat.conf` with the following contents: iptable_nat