Setting Up WireGuard and DuckDNS on a Raspberry Pi
In this guide, we’ll walk you through setting up WireGuard on a Raspberry Pi, combined with DuckDNS for dynamic DNS management. This will allow you to create a secure VPN server that you can access from anywhere, even when your public IP address changes regularly.
Prerequisites
Raspberry Pi: Any model with Raspberry Pi OS installed.
DuckDNS account: A free dynamic DNS service to handle IP changes.
WireGuard: A lightweight, high-performance VPN.
Publicly accessible IP: Required to expose your Raspberry Pi to the internet, but we’ll cover how DuckDNS helps with this.
CGNAT consideration: If you're behind CGNAT, like some ISPs provide, this guide assumes you’ll have to work around it, possibly with services like Tailscale or reverse proxy solutions.
Step 1: Set Up DuckDNS on Raspberry Pi
Since most ISPs assign dynamic IPs, we need to ensure that your Raspberry Pi's changing public IP can be accessed consistently. DuckDNS provides an easy, free solution for dynamic DNS.
Create a DuckDNS account:
Go to DuckDNS, sign in, and create a subdomain.
You will get a unique token and your chosen subdomain, for example,
myvpn.duckdns.org
.
Install DuckDNS on Raspberry Pi: We’ll create a simple cron job that periodically updates DuckDNS with your current IP.
Open the terminal and type the following commands:
sudo apt update && sudo apt install curl -y
Create a new script to update DuckDNS:
nano ~/duckdns.sh
Inside the script, paste the following (replace
<your_token>
and<your_subdomain>
with your actual token and subdomain):echo url="https://www.duckdns.org/update?domains=<your_subdomain>&token=<your_token>&ip=" | curl -k -o ~/duckdns.log -K -
Save and close the file by pressing
CTRL + X
, thenY
, andEnter
.Set up cron job: We’ll now set a cron job to run this script every 5 minutes.
crontab -e
Add the following line to the file:
*/5 * * * * ~/duckdns.sh >/dev/null 2>&1
This will update DuckDNS every 5 minutes with your current public IP.
Step 2: Install WireGuard on Raspberry Pi
WireGuard is a fast, modern VPN that is simpler to configure and deploy than older protocols.
Install WireGuard: On your Raspberry Pi, install WireGuard using the following commands:
sudo apt update && sudo apt install wireguard -y
Generate Keys: You’ll need a public and private key pair for your server and each peer. Run the following commands to generate them:
wg genkey | tee privatekey | wg pubkey > publickey
This creates two files:
privatekey
contains your server’s private key.publickey
contains your server’s public key.
Make sure to keep the private key safe!
Configure WireGuard: Create a new WireGuard configuration file:
sudo nano /etc/wireguard/wg0.conf
Here’s a basic configuration file:
[Interface] PrivateKey = <your_private_key> Address = 10.13.13.1/24 # This is the VPN subnet ListenPort = 51820 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] PublicKey = <peer_public_key> AllowedIPs = 10.13.13.3/32 # This is the peer’s VPN address
Replace
<your_private_key>
with the private key you generated, and set the peer’s public key in the[Peer]
section.Enable and Start WireGuard:
sudo wg-quick up wg0
To make sure WireGuard starts on boot, enable the service:
sudo systemctl enable wg-quick@wg0
Step 3: Port Forwarding on Your Router
You’ll need to forward the WireGuard port (51820 by default) on your router. If your router is behind CGNAT, this may not be possible directly. In such cases, consider using a service like Tailscale, which doesn’t require port forwarding, or a reverse proxy that supports WireGuard.
Log in to your router’s settings.
Navigate to the port forwarding section and forward UDP port 51820 to your Raspberry Pi’s local IP address.
Test connectivity using
telnet
ornc
to ensure the port is open.
Step 4: Set Up WireGuard Clients
Once your Raspberry Pi VPN server is set up, you can connect clients like laptops, phones, or tablets.
Generate client keys (on the Raspberry Pi or client device):
wg genkey | tee client_privatekey | wg pubkey > client_publickey
Add the client configuration: Edit the
wg0.conf
file on your Raspberry Pi and add a new[Peer]
section for each client:[Peer] PublicKey = <client_public_key> AllowedIPs = 10.13.13.3/32 # Client VPN IP
Client Configuration: On your client device, create a configuration file. Here’s an example for iOS or Android using the WireGuard app:
[Interface] PrivateKey = <client_private_key> Address = 10.13.13.3/32 [Peer] PublicKey = <server_public_key> Endpoint = myvpn.duckdns.org:51820 AllowedIPs = 0.0.0.0/0, ::/0
Replace
<client_private_key>
with the key generated for the client, and<server_public_key>
with your Raspberry Pi’s public key.
Step 5: Testing the VPN
Once everything is set up, you can test the VPN by connecting to it from your client devices. Make sure to check that you can access your Raspberry Pi and any other services you’ve configured through the VPN.
To verify connectivity, you can use ping
or try accessing services hosted on the Raspberry Pi, such as Docker containers you’ve set up.
Conclusion
Setting up WireGuard on a Raspberry Pi, combined with DuckDNS for dynamic DNS, allows you to maintain a secure VPN server that’s accessible regardless of your changing IP address. With a streamlined configuration process and a lightweight footprint, WireGuard is an excellent choice for Raspberry Pi VPN setups.
By following this guide, you should have a fully functioning WireGuard VPN server, protected by DuckDNS, and accessible remotely from anywhere.
Subscribe to my newsletter
Read articles from DevOpshelian directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by