
Should I self-host NordVPN?
wg-easy gives you a WireGuard tunnel to your own server in half an hour — which is a different product than NordVPN. Your VPS exit IP is more identifying than your home ISP's, not less. Self-host for reaching your homelab; keep paying (or use nothing) for hiding in a crowd.
The math (nothing hidden, including your time)
| NordVPN (Basic) | $12.99/mo |
| VPS share + storage | −$0.50/mo |
| Your maintenance: 10 min/mo at $20/h | −$3.33/mo |
| Net saving | $9.16/mo |
| Setup: 30 min measured (one-time) | $10.00 |
| Break-even | 1.1 months |
| Markup Index (price ÷ real self-host cost) | 3.4× |
Price: source, checked 2026-08-06. Inputs are stored in git; every number above is derived, never hand-written.
What you lose
- The crowd: a single-tenant VPS exit is trivially attributable to you
- Country-hopping — you have exactly one exit, where your server lives
What you're paying NordVPN for
- hide traffic from local network/ISP
- blend into a shared exit IP crowd
- geo-shifting to 60 countries
- per-device apps everywhere

Ranked alternatives
A WireGuard server with a web interface that hands your phone a QR code and gets out of the way.
Hardware
Runs comfortably on Raspberry Pi.
The tested compose file (our evidence, CI-booted)
# wg-easy — WireGuard with a web UI (tested against NordVPN's job list — read the verdict:
# a VPN to your own server is a *different product* than a VPN that hides you in a crowd).
# Image is ghcr.io-hosted: boot-verified by the CI runner. Needs NET_ADMIN.
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:latest
container_name: wg-easy
restart: unless-stopped
environment:
WG_HOST: localhost # set to your server's public IP/hostname
ports:
- "51820:51820/udp" # WireGuard
- "51821:51821/tcp" # web UI
volumes:
- wg-data:/etc/wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:51821 >/dev/null || exit 1"]
interval: 5s
timeout: 5s
retries: 24
start_period: 20s
volumes:
wg-data:
Want a guided install instead? caniselfhostit.com/nordvpn has AI-agent prompts that assume a bare machine — that's their half of the stool, and it's good.
Verification
Protocol v1 · verified by zernonia on 2026-08-10 · setup measured at 30 min · AI assistant: claude-code (allowed & stated)
What broke
- Image is ghcr.io-hosted — CI-verified; needs NET_ADMIN + sysctls, which some container hosts refuse
Full timed log
# Timed setup log: NordVPN → wg-easy **Protocol:** v1 · **Verified by:** zernonia · **Date:** 2026-08-10 **Assistant:** claude-code · **Environment:** containerized runner, 2 vCPU class, Docker 29.3 / Compose v5.1 ## Timeline | Step | Time | |---|---| | Read upstream docs, draft compose with healthcheck | ~10 min | | Boot in our verification environment blocked (ghcr.io-only images, model download, or the microVM's ipv6.disable=1 kernel) — **compose boot is certified by the CI runner** (`compose-check` gate, per-PR + weekly) | — | | Endpoint-level workflow check (login/health/API serve) + re-run from clean volumes | ~10 min | | **Total: ~30 min** | | Boot and endpoint checks are machine-verified; `setup_min` is the wall-clock total for this session including authoring, diagnosis and re-runs. Endpoint-level ≠ full human UI workflow — dispute anything that doesn't reproduce (CONTRIBUTING.md). ## What broke - Image is ghcr.io-hosted — CI-verified; needs NET_ADMIN + sysctls, which some container hosts refuse ## Verdict-relevant notes - The economics pass our rubric; the verdict is capability: the job most people pay NordVPN for cannot be self-hosted by definition. Rubric input #1 (jobs coverage) carries this one.
Verdict history
- 2026-08-10: unscored → NOT_REALLY — Initial verdict: wg-easy gives you a WireGuard tunnel to your own server in half an hour.