Skip to main content

Protect Your Online Life: How to Create a Secure Home VPN

Submitted by @ReneSerulle on
Person connecting remotely to Home VPN.

This guide shows you how to turn a Raspberry Pi into a secure home VPN server. It draws on our own journey building a VPN for a Verizon Fios network using a Pi 4 and a custom domain (vpn.insomnyak.com) with dynamic DNS. The emphasis is on open‑source tools, practical troubleshooting and security best practices. References from vendor documentation and security blogs support the recommendations.

Why Run Your Own Home VPN?

Setting up a private VPN gives you control over who can access your network and how your data is routed. VPNs encrypt traffic, protect home networks from cyber threats and allow you to access your network from anywhere. Using a VPN at home enhances privacy, secures your connection against threats on your home network and lets you access geo‑restricted content. In other words, a DIY VPN protects your family’s browsing, gives you remote access to computers or media servers on your LAN and bypasses geographic blocks: all without paying monthly fees.

Pros and Cons of Hosting Your Own VPN

ProsCons
Control & privacy – You control the server, keys and logs, so there is no third‑party tracking.Maintenance – You are responsible for updates, security patches and troubleshooting.
Remote access to your LAN – Your own VPN acts like a “secret tunnel” into your home network. It’s ideal for file shares, NAS devices or home automation dashboards.Exposure if misconfigured – A misconfigured port forward or firewall rule can expose your Pi and network to the internet.
Customization – You can set the encryption level, assign static IPs, create multiple users and combine with Pi‑hole for ad‑blocking.ISP limitations – Some ISPs block inbound connections or frequently change your public IP, which can break the VPN unless you use dynamic DNS.
Cost‑effective – A Raspberry Pi 4 plus an SD card is inexpensive and consumes little power, and the software (WireGuard/PiVPN) is open source.Learning curve – You need to understand networking concepts like IP addressing, NAT and DNS.

Requirements & Preparation

Hardware & Network

  • Raspberry Pi 4 (4 GB RAM or higher) with a fresh 64‑bit Raspberry Pi OS installed on a 128 GB SD card.

  • Verizon Fios Home Router (or any router with port‑forwarding capabilities).

  • A domain name and dynamic DNS service. In our build we used a sub‑domain (vpn.insomnyak.com) pointing to our public IP. Dynamic DNS keeps this host record updated if your ISP changes your IP.

  • Stable internet connection and a computer (macOS/Windows/Linux) for SSH access.

Software

  • WireGuard – modern, fast VPN protocol.

  • PiVPN – an installer and manager for WireGuard/OpenVPN on Raspberry Pi.

  • Optional: Pi‑hole for DNS filtering and ad‑blocking (covered later).

Before you start

  1. Flash Raspberry Pi OS and configure it headless. Use Raspberry Pi Imager’s advanced settings to set a hostname, user/password, Wi‑Fi credentials (if using Wi‑Fi), locale and enable SSH. Make sure to assign a static IP (or a DHCP reservation) so the Pi’s address doesn’t change when you reboot.

  2. Reserve an IP on your router for the Pi (e.g., 192.168.1.210), and note your router’s admin credentials.

  3. Set up a dynamic DNS record for your domain. You will point it to your public IP and update it automatically. Many registrars provide DDNS APIs; you can also use services like DuckDNS or Cloudflare.

  4. Open UDP port 51820 on your router and forward it to the Pi’s internal IP. WireGuard uses this port by default. Later, if you change the Pi’s interface (e.g., switch from Wi‑Fi to Ethernet), update the port‑forward rule accordingly.

Step‑by‑Step Setup Using PiVPN

PiVPN wraps the complexity of WireGuard into a friendly CLI wizard. The following steps were tested on our Pi.

1 Install PiVPN

SSH into the Pi using the reserved IP:

ssh pi@192.168.1.210

Then run the one‑line installer:

curl -L https://install.pivpn.io | bash

During installation you will be prompted for:

  • Network interface – choose eth0 or wlan0 depending on how the Pi is connected. Our final setup used eth0.

  • Local user – select the user that will administer PiVPN (usually pi).

  • VPN type – choose WireGuard.

  • Server port – use the default 51820 unless you need a different port. Remember to forward this in your router.

  • Public DNS name – select “DNS entry” and enter your dynamic DNS host (vpn.insomnyak.com). This ensures that clients always connect using your domain name even if the IP changes.

  • Upstream DNS provider – PiVPN will ask for DNS servers; you can enter 1.1.1.1, 9.9.9.9 or the IP of your Pi‑hole if you plan to install it later.

When the installer finishes, it will configure WireGuard, enable IP forwarding and set up basic firewall rules for you.

2 Generate a Client Profile

Use PiVPN’s CLI to add a new VPN client:

pivpn add

Give the profile a descriptive name (e.g., macbook or iphone). PiVPN generates a configuration file under /home/pi/configs/ and prints a QR code.

To fetch the config on your Mac:

scp pi@192.168.1.210:/home/pi/configs/macbook.conf .

Open the WireGuard app (available for macOS, Windows, iOS and Android) and import the .conf file or scan the QR code. The config will look like this:

[Interface]
PrivateKey = <client_private_key> 
Address = 10.120.130.2/24
DNS = 1.1.1.1, 9.9.9.9

[Peer]
PublicKey = <server_public_key> 
PresharedKey = <preshared_key> 
Endpoint = vpn.insomnyak.com:51820
AllowedIPs = 0.0.0.0/0, ::/0, 192.168.1.0/24
PersistentKeepalive = 25

The AllowedIPs directive routes all IPv4 and IPv6 traffic (0.0.0.0/0 and ::/0) and your home LAN (192.168.1.0/24) through the VPN. Without the local subnet appended, you will not be able to ping or SSH into devices on the LAN.

3 Test the Connection

  1. Deactivate Wi‑Fi on your laptop or phone and connect via mobile data or a different network.
  2. Activate the WireGuard profile. In the WireGuard app you should see a green indicator.
  3. From your client, check your public IP:

    curl ifconfig.me

If the VPN is routing properly, this command returns your home’s public IP rather than your mobile ISP’s address. You should also be able to ping and ssh to the Raspberry Pi and other devices on your LAN.

If you cannot reach LAN devices, verify that IP forwarding and NAT are working on the server:

  • Ensure that net.ipv4.ip_forward=1 is enabled in /etc/sysctl.conf and loaded with sudo sysctl -p. The Pi‑hole docs show how to enable IP forwarding for both IPv4 and IPv6.

  • Confirm that the WireGuard interface adds NAT rules. The Pi‑hole guide illustrates adding a PostUp rule (either nftables or iptables) to masquerade traffic leaving the Internet‑facing interface. With PiVPN this is configured automatically, but if you manually edit /etc/wireguard/wg0.conf be sure that PostUp includes -A POSTROUTING -s 10.120.130.0/24 -o eth0 -j MASQUERADE and that symmetric FORWARD rules allow traffic both from wg0 → eth0 and eth0 → wg0.

  • If you change the Pi’s network interface (e.g., switch from Wi‑Fi to Ethernet), update your router’s port‑forwarding rule. Our testing found that forgetting to update the port‑forward after deactivating Wi‑Fi prevented connections; once the rule pointed to the new IP the VPN worked again.

4 Persist Firewall Rules

iptables-persistent
sudo apt install iptables-persistent -y sudo netfilter-persistent save

This creates /etc/iptables/rules.v4 and /etc/iptables/rules.v6 which load automatically on boot.

Hardening & Best Practices

WireGuard’s security depends on how you configure and maintain it. A Netmaker security guide recommends the following best practices:

  1. Keep software up‑to‑date – regularly run sudo apt update && sudo apt upgrade wireguard to patch vulnerabilities.

  2. Use strong unique keys – generate keys with wg genkey and never reuse private keys between peers. Secure the config with strict permissions (chmod 600 /etc/wireguard/wg0.conf).

  3. Whitelist clients – set AllowedIPs for each peer to the specific addresses or subnets they need, preventing unauthorized access.

  4. Tune PersistentKeepalive – only enable keepalive when a peer is behind NAT; set it to a reasonable interval (e.g., 25 s) to maintain the connection without excessive traffic.

  5. Restrict firewall – open only the WireGuard port (UDP 51820) and block other inbound traffic. Monitor logs or set up custom logging to detect unauthorized access attempts.

  6. Consider a kill‑switch – create a script that monitors the wg0 interface and blocks outbound traffic if the VPN goes down.

Additional security tips for a home server include:

  • Disable password logins for SSH and use public‑key authentication.

  • Use a firewall like UFW for additional filtering (e.g., ufw allow 51820/udp and ufw allow OpenSSH).

  • Rotate keys periodically and remove unused clients (pivpn remove).

  • Use intrusion detection tools (e.g., Fail2Ban) to ban repeated connection attempts.

Enhancements & Optional Tools

Dynamic DNS Update Script

If your registrar supports an API, you can automate updating the vpn.insomnyak.com record when your public IP changes. Below is a sample Bash script for Cloudflare (replace placeholders):

 

#!/bin/bash
# Requirements: curl, jq
API_TOKEN="<CLOUDFLARE_API_TOKEN>"
ZONE_ID="<ZONE_ID>"
RECORD_NAME="vpn.insomnyak.com"

# Get current public IP
CURRENT_IP=$(curl -s https://api.ipify.org)

# Get existing record ID and IP from Cloudflare
RECORD_ID=$(curl -s -X GET   "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=$RECORD_NAME"   -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" | jq -r '.result[0].id')
EXISTING_IP=$(curl -s -X GET   "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID"   -H "Authorization: Bearer $API_TOKEN" | jq -r '.result.content')

if [ "$CURRENT_IP" != "$EXISTING_IP" ]; then
  echo "Updating DNS record to $CURRENT_IP"
  curl -s -X PUT     "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID"     -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json"     --data '{"type":"A","name":"'$RECORD_NAME'","content":"'$CURRENT_IP'","ttl":120,"proxied":false}'
else
  echo "IP has not changed ($CURRENT_IP)"
fi

Add this script to /usr/local/bin/update-ddns.sh, make it executable (chmod +x update-ddns.sh) and run it daily via cron (0 */2 * * * /usr/local/bin/update-ddns.sh >/dev/null 2>&1) to check every two hours.

Combining with Pi‑hole

Running Pi‑hole on the same Pi adds network‑wide ad‑blocking and can filter adult sites. When using Pi‑hole with WireGuard, set Pi‑hole’s IP as the DNS server in the client configuration (e.g., DNS = 192.168.1.210). The Pi-hole docs show how to enable IP forwarding, NAT and configure clients to access local devices. You can add blocklists or use family‑friendly DNS providers to block adult content.

Other Use Cases

  • Remote desktop – securely access your home PC or NAS using VNC/RDP over the VPN.

  • Self‑hosted services – host a media server (Plex/Jellyfin), Nextcloud or Home Assistant and reach them remotely via the VPN instead of exposing them to the internet.

  • Site‑to‑site connections – connect multiple homes or offices by setting up additional peers and routing between subnets.

Conclusion

Building a home VPN on a Raspberry Pi using WireGuard and PiVPN offers privacy, security and convenience. It lets you access your LAN from anywhere, encrypts your traffic over public Wi‑Fi and avoids monthly VPN fees. The process requires some networking knowledge, but with dynamic DNS, port forwarding and PiVPN’s automation, setup is manageable. Remember to keep your system updated, use strong keys, restrict firewall rules and monitor your logs. Consider combining your VPN with Pi‑hole for ad‑blocking and dynamic DNS scripts to keep your domain updated. With these steps you’ll have a reliable, secure gateway into your home network.