Install Wireguard

sudo apt update && sudo apt install wireguard

Generate a public and private key

umask 077 # So only the owner has access to the key
wg genkey | sudo tee /etc/wireguard/private.key # Generate the private key
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key # Generate the public key

Create a config file

sudo nano /etc/wireguard/wg0.conf

Configuration

[Interface]
Address = 192.168.255.1/24
ListenPort = 51820
PrivateKey = <private.key>
SaveConfig = true

Address - Chose an IP from the private ranges, that does not overlap with another network.
PrivateKey - Replace <private.key> with the contents of the file at /etc/wireguard/private.key.

Enabling IP forwarding

echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding=1" | sudo tee -a /etc/sysctl.conf # Optionally also for IPv6
sudo sysctl -p

Allowing NAT on the servers default interface

sudo apt install iptables # Install iptables if you don't have it already
sudo iptables -t nat -A POSTROUTING -s 192.168.255.0/24 -o eth0 -j MASQUERADE
sudo mkdir /etc/iptables
sudo iptables-save | sudo tee /etc/iptables/rules.v4

Bring up the interface

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

sudo wg show # Check the status of the interface

Allowing Wireguard through your firewall

In order to access Wireguard from outside your network, you need to forward port 51820/UDP (or the one you've set for ListenPort in your config) on your firewall. If your public IP changes, you could also setup DDNS using a service like DuckDNS to obtain a static domain for your wireguard.

Connecting the clients

For every client, a public key has to be generated which can be placed in the /etc/wireguard/wg0.conf file. These keys can either be generated on the client, or preferrably on the server and then be transferred to the client.

Generating keys on the server

Generate client keys

Info

For multiple clients you can replace "client" in client_private.key, client_public.key and client.conf with any other string that allows you to easily identify your devices or store the files for each client in a seperate folder.

umask 077 # Only allow to owner to access the private key
wg genkey > client_private.key # Private key
wg pubkey < client_private.key > client_public.key # Public key

Create a config for the client

[Interface]
PrivateKey = <client_private.key>
Address = 192.168.255.2/24
DNS = 8.8.8.8

[Peer]
PublicKey = <public.key>
AllowedIPs = 0.0.0.0/0, ::0
Endpoint = <server_ip>:51820

Address - Chose an IP from the same subnet as the one for your server.
PrivateKey - Replace <client_private.key> with the contents of the clients private key at client_private.key.
DNS - You can also use a local DNS server like pihole here, just enter its local private ip.
PublicKey - Replace <public.key> with the contents of the servers public key at /etc/wireguard/public.key.
Endpoint - Replace <server_ip> with your public IP or DDNS address.

Transfering the configs to clients

To transfer a config to a client the client.conf file can simply be copied to the client. Alternatively, a qr-code containing the config file can be generated for an easy import on mobile devices:

  1. Install qrencode: sudo apt install qrencode
  2. Generate the qr-code: qrencode -t ansiutf8 < client.conf

Adding the Client to the Server Config

You need to add each client as a peer to the server config:

[Peer]
PublicKey = <client_public_key>
AllowedIPs = 192.168.255.2/32

PublicKey - Replace <client_public_key> with the public key of your client
AllowedIPs - Replace this with the IPs you want your client to be able to use. You can just set this to the same IP you used in the clients config, with a subnet mask of 32.

After you have changed the config file, reload the interface with:

sudo systemctl relaod wg-quick@wg0