Skip to content

Build Your Own Private VPN - The Ultimate WireGuard + VPS Guide

Build your own high-speed, log-free private VPN for under $10/year using WireGuard and a budget VPS. This step-by-step guide solves common low-RAM crashes and IPv6 errors to ensure total digital privacy.

/ ARTICLE
[ FIG. 1 ]
Private VPN from VPS

WireGuard is about 4,000 lines of code. OpenVPN is closer to 100,000. That difference is why this takes an evening rather than a weekend, and why the resulting tunnel is fast enough that you will forget it is running.

Before the instructions, one thing worth being honest about, because most guides on this topic are not. Self-hosting does not make you anonymous. It moves your traffic from your ISP to a VPS you rented with your own payment card, on an IP address used by exactly one person: you. That is worse for anonymity than a commercial provider whose exit IP is shared by thousands. What you gain instead is control and integrity — a tunnel you configured, logging you decide on, a stable address you can allow-list, and safe access to hostile Wi-Fi. Those are excellent reasons. Hiding from a determined adversary is not one of them.

With that settled: this covers the full build, plus the two failures that reliably catch people on budget hosting — the out-of-memory kill during install, and IPv6 routing that stops the service from starting at all.


Prerequisites

Three things:

  1. A budget VPS — Annual deals under $10 are easy to find from providers like RackNerd. Take KVM, not OpenVZ: OpenVZ containers share the host kernel, and WireGuard needs a kernel module the host will not give you. That single detail is the difference between this working and an hour of confusing errors. Ubuntu 22.04 or 24.04 LTS, 1 vCPU, 512 MB RAM. Also check the bandwidth allowance — cheap plans often cap at 1–2 TB a month, which is fine for browsing and quickly not fine if you stream through it.
  2. Basic Linux Terminal Skills — If you’re new to the command line, check out my guide on the Introduction to the Open-Source Operating System before continuing.
  3. Secure SSH Access — Make sure you can log into your VPS securely. I strongly recommend reading through How to Secure Your SSH Server before moving forward.

Privacy Architecture - How Traffic Flows Through Your Private VPN

Step 1: Setting Up Swap (Essential for Low-RAM Servers)

Skip this on a 512 MB box and the install will appear to fail for no reason. What actually happens: apt and the kernel headers push memory past the limit, the kernel’s OOM killer picks a process and terminates it, and you are left with a half-configured system. The clue is not in the terminal output — it is in dmesg, where you will find a line naming the process that was killed. Worth knowing generally: OOM kills look like random failure everywhere they occur.

A swap file trades SSD space for memory headroom. Slow, but the alternative is a failed install:

# Create a 1GB swap file
sudo fallocate -l 1G /swapfile

# Lock it down so only root can access it
sudo chmod 600 /swapfile

# Format it as swap space
sudo mkswap /swapfile

# Activate it immediately
sudo swapon /swapfile

# Persist it across reboots
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Verify it worked:

free -h

Roughly 1.0Gi under Swap means it took. If the total reads zero, the fstab line is the usual culprit — check you appended rather than overwrote, because a mangled /etc/fstab will stop the machine booting.


Advertisement

Step 2: Install WireGuard Using an Automated Script

Manual configuration is entirely doable — keys, interface, NAT masquerading, forwarding rules — and mostly consists of iptables incantations that are easy to get subtly wrong. The Angristan WireGuard installer is a long-running, widely audited open-source script that does the lot.

Note what you are doing here: piping a script from GitHub into a root shell. That is the same pattern security people rightly complain about. This one is popular and well reviewed, which mitigates the risk without removing it — the honest habit is to download it first, read it, and then run it. The commands below do it in that order for a reason.

sudo apt update && sudo apt install curl -y
curl -O https://raw.githubusercontent.com/angristan/wireguard-install/master/wireguard-install.sh
chmod +x wireguard-install.sh
sudo ./wireguard-install.sh

The prompts are mostly safe to accept as they come:

  • Public IPv4 address — Press Enter. The script detects your server’s IP automatically.
  • Public IPv6 address — If your VPS doesn’t support IPv6, leave it blank or press Enter to skip.
  • Private interface — Press Enter to use the default (wg0).
  • WireGuard IPv4 — Press Enter (default: 10.66.66.1/24).
  • WireGuard IPv6 — Press Enter (default: fd42:42:42::1/64).
  • Port51820 is the default. Consider changing it to something in the high ephemeral range: WireGuard on its standard port is trivially fingerprintable, and networks that block VPNs block it first. This is obscurity, not security — it will not defeat deep packet inspection, but it does get you past lazy port-based filtering.
  • DNS servers — Cloudflare (1.1.1.1) is fast; AdGuard DNS also filters ads and trackers at the resolver. Whichever you choose now sees every domain you look up, which is the same trust decision you were making with your ISP, just pointed elsewhere.

The script then creates your first client. Name it after the device — iphone, work-laptop — because in eight months you will be looking at this list trying to remember what client1 was, and revoking the wrong one locks you out of something you use.


Step 3: Fixing IPv6 Issues (The Most Common Failure Point)

Cheap nodes frequently ship without IPv6, or with it available only after a manual request. The installer configures both stacks by default, wg-quick applies the interface configuration atomically, and one failing ip6tables rule aborts the entire thing. The tunnel does not come up degraded. It does not come up at all.

Job for wg-quick@wg0.service failed is this, roughly nine times in ten. Confirm before you start editing:

sudo journalctl -xeu wg-quick@wg0

An error naming ip6tables or an Address line containing fd42 puts you in the right place.

How to Fix It

Open the WireGuard server configuration file:

sudo nano /etc/wireguard/wg0.conf

Comment out every IPv6 reference with # rather than deleting it — if your host enables IPv6 later, restoring three lines beats reconstructing them. Look for the Address entry with the fd42: prefix, every ip6tables rule in PostUp/PostDown, and any AllowedIPs containing ::/0.

The result should read like this:

[Interface]
Address = 10.66.66.1/24
ListenPort = 51820
PrivateKey = <YOUR_SERVER_PRIVATE_KEY>

# IPv4 routing rules
PostUp = iptables -I INPUT -p udp --dport 51820 -j ACCEPT
PostUp = iptables -I FORWARD -i eth0 -o wg0 -j ACCEPT
PostUp = iptables -I FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

PostDown = iptables -D INPUT -p udp --dport 51820 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[!NOTE] The interface name eth0 in the example above may differ on your server. Run ip route show | grep default to find your actual interface name and update the config accordingly.

Save with Ctrl+O, Enter, then exit with Ctrl+X.

Restart WireGuard to apply the changes:

sudo systemctl restart wg-quick@wg0

Then confirm it is genuinely up rather than merely not complaining — systemctl status can look content while the interface is absent:

sudo wg show

A wg0 interface with a listening port and your peer listed means the server side is done. There is one thing left that everyone forgets: this survives a reboot only if the unit is enabled. sudo systemctl enable wg-quick@wg0, or the first time your provider migrates the node you will find the tunnel quietly gone.

Installation Workflow - Troubleshooting & Configuration Logic

Step 4: Connecting Your Devices

Mobile (Android and iOS)

Phones are the easy case, because the QR code carries the whole profile — including the private key. Which is the thing to be careful about: do not screenshot it, do not paste it into a chat to get it onto another device, and clear the terminal afterwards. Anyone who photographs that code has your tunnel.

  1. Run the installer again:
    sudo ./wireguard-install.sh
    
  2. Select Add a new user and enter a name like phone.
  3. The script outputs a QR code directly in the terminal.
  4. Install the official WireGuard app from the Google Play Store or Apple App Store.
  5. Tap +, choose Scan from QR code, and point your camera at the terminal. The profile imports instantly.

Desktop (Windows, macOS, and Linux)

Desktops need the configuration file itself. Move it over SSH — scp — rather than emailing it to yourself, for the reason above.

  1. Create a new client profile via the script (e.g., laptop).
  2. Find the generated config file—typically in the home directory of the user who ran the command (e.g., /root/wg0-client-laptop.conf).
  3. Display its contents:
    cat ~/wg0-client-laptop.conf
    
  4. Copy the full output.
  5. If you disabled IPv6 on the server, edit the [Peer] section before importing:
    • Change: AllowedIPs = 0.0.0.0/0, ::/0
    • To: AllowedIPs = 0.0.0.0/0
  6. Open the WireGuard desktop client, add a new empty tunnel, paste the edited configuration, and click Activate.

One extra line worth adding to the [Peer] section on laptops and phones: PersistentKeepalive = 25. Home routers and mobile carriers drop idle UDP mappings after a minute or two, and without a keepalive the tunnel appears connected while nothing traverses it until you send traffic. A packet every 25 seconds costs essentially nothing and removes an entire class of “it says connected but the internet is broken” confusion.


Step 5: Verifying the Connection and Checking for Leaks

A green indicator means the handshake succeeded. It says nothing about whether your traffic is actually going through the tunnel, and a VPN that half-works is worse than none — you behave as though you are protected while you are not.

Check your public IP. ipinfo.io should report your VPS address and its datacentre, not your ISP. If you still see home, the client’s AllowedIPs is not 0.0.0.0/0 and you are only routing the tunnel subnet.

Run a DNS leak test. dnsleaktest.com, extended test. Your ISP’s resolvers appearing here means DNS queries are bypassing the tunnel — your traffic is encrypted, and a full list of every domain you visit is being handed to your ISP anyway. This is the most common failure, and the usual cause on Windows is a second network adapter still resolving on its own. On Android, check that “Block connections without VPN” is enabled in the always-on VPN settings.

Test the IPv6 leak specifically. Having disabled IPv6 on the server, a device with working native IPv6 will route those requests outside the tunnel entirely. ipv6-test.com will tell you. If it finds an address, disable IPv6 on the client’s network adapter until your host supports it.

For browser-level leaks — WebRTC in particular, which can expose your real address regardless of tunnel state — see Essential Tools for Privacy in Daily Life.

Final Thoughts

What you have now is a tunnel whose configuration you can read, on hardware you rent, with logging that exists only if you decide it does. Under a pound a month, and fast enough on WireGuard that you will stop noticing it.

Be clear about the trade you made, though. You are the only user of that exit IP, so the tunnel gives you integrity rather than anonymity. You are now the administrator, which means you patch the box and you notice when it stops working. And there is one exit location, so the geographic flexibility a commercial provider sells you is gone. For hostile Wi-Fi, for a stable address you can allow-list, and for not handing your browsing to whoever operates the café router, it is the better answer. For staying hidden, it is the wrong tool, and no amount of configuration changes that.

If you want to understand how these privacy and isolation concepts scale up to enterprise environments, my guide on Vulnerability Assessment and Management in Large-Scale Enterprise Networks covers exactly that.


Share article

Subscribe to my newsletter

Receive my case study and the latest articles on my WhatsApp Channel.

Warning

Ask CyberROX AI