If you’re in a rural area trying to self-host services — a VPN endpoint, a game server, a website, or a remote monitoring platform — you’ve probably hit the same wall I did: no static IP from your ISP. Most rural ISPs use CGNAT or dynamic IPs, which means you can’t reliably point the internet at your home network.
The solution? A cheap cloud VPS that acts as your public-facing front door. I use UpCloud, a European cloud provider with US data centers that consistently beats AWS and DigitalOcean on price-to-performance. Here’s how to set one up and route traffic back to your home lab.
Why UpCloud?
I’ve tried most of the major VPS providers. Here’s why UpCloud wins for this use case:
- MaxIOPS storage — Their custom storage tier is genuinely fast. Not “fast for the price” fast, just fast.
- Simple pricing — $5/month gets you 1 vCPU, 1GB RAM, 10GB storage, and 1TB transfer. No surprise bandwidth bills.
- US data centers — Chicago and New York, with sub-20ms latency from most of the central US.
- API-first — Everything you can do in the UI, you can do via API. Great for automation.
- Hourly billing — Spin up a server for testing, tear it down when you’re done, pay pennies.
Step 1: Create Your Account and Server
Sign up at upcloud.com. Use my referral code 858PV7 and get 25 free credits! https://signup.upcloud.com/?promo=858PV7 Once you’re in:
- Click Deploy Server
- Choose your data center (I use Chicago for central US)
- Pick Ubuntu 24.04 LTS — it’s stable and has the longest support window
- Select the $5/month plan (1 vCPU, 1GB RAM, 10GB MaxIOPS)
- Add your SSH key (strongly recommended over password auth)
- Deploy
Your server will be up in about 45 seconds. Seriously. UpCloud’s provisioning is impressively fast.
Step 2: Initial Server Hardening
SSH into your new server and lock it down:
ssh root@your-server-ip
# Update everything
apt update && apt upgrade -y
# Create a non-root user
adduser deploy
usermod -aG sudo deploy
# Copy SSH keys to new user
mkdir -p /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
# Disable root SSH and password auth
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd
# Set up basic firewall
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Step 3: Set Up WireGuard Tunnel
This is the magic piece. WireGuard creates an encrypted tunnel between your VPS and your home network. Traffic hits the VPS’s public IP, travels through the tunnel, and arrives at your home server — bypassing CGNAT entirely.
# Install WireGuard on both machines
apt install wireguard
# On the VPS — generate keys
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
# On your home server — generate keys
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
Create the VPS config at /etc/wireguard/wg0.conf:
[Interface]
PrivateKey = (VPS private key)
Address = 10.0.0.1/24
ListenPort = 51820
[Peer]
PublicKey = (Home server public key)
AllowedIPs = 10.0.0.2/32, 192.168.0.0/16
Create the home server config:
[Interface]
PrivateKey = (Home private key)
Address = 10.0.0.2/24
[Peer]
PublicKey = (VPS public key)
Endpoint = your-vps-ip:51820
AllowedIPs = 10.0.0.1/32
PersistentKeepalive = 25
The PersistentKeepalive is crucial — it keeps the tunnel alive through your home router’s NAT. Without it, the tunnel dies after a few minutes of inactivity.
# Start WireGuard on both machines
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
# Verify the tunnel
ping 10.0.0.2 # From VPS, should reach home server
Step 4: Forward Traffic Through the Tunnel
Now set up iptables on your VPS to forward incoming traffic to your home server via the WireGuard tunnel:
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p
# Forward port 443 (HTTPS) to home server
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 10.0.0.2:443
iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
# Save rules
apt install iptables-persistent
netfilter-persistent save
Now any HTTPS traffic hitting your VPS gets forwarded through WireGuard to your home server. Add more PREROUTING rules for any other ports you need.
Step 5: Point Your Domain
Create DNS records pointing to your VPS’s public IP:
yourdomain.com A → VPS-IP
*.yourdomain.com A → VPS-IP
The wildcard record lets you add subdomains later without touching DNS again.
Cost Breakdown
Here’s what this setup costs monthly:
- UpCloud VPS: $5/month
- Domain name: ~$1/month (amortized)
- SSL certs: Free (Let’s Encrypt)
- WireGuard: Free (open source)
- Total: ~$6/month
Compare that to a static IP from most rural ISPs ($15-30/month extra, if they even offer it) and you’re saving money while getting a more flexible setup.
What Can You Host?
With this setup running, you can self-host basically anything:
- Home Assistant — Control your smart home from anywhere
- Plex / Jellyfin — Stream your media library remotely
- Matrix / Mattermost — Private team chat
- Nextcloud — Your own cloud storage
- Git repositories — Self-hosted Gitea or GitLab
- Network monitoring — Grafana dashboards for your infrastructure
The VPS handles the public-facing networking while your actual hardware stays safe behind your home firewall. Best of both worlds.
Pro Tips
- Monitor the tunnel: WireGuard is rock-solid, but set up a simple cron job that pings through the tunnel and alerts you if it drops.
- Use Caddy: Instead of Nginx, try Caddy as your reverse proxy. It handles SSL automatically and the config is much simpler.
- Snapshots: UpCloud’s snapshot feature lets you back up your entire VPS state. Take one before any major changes.
- Consider a Squid proxy: Running a transparent proxy on the VPS lets you route specific home traffic through the VPS’s IP — useful for services that need a clean IP reputation.
Alternative: MikroTik Router with Built-In WireGuard
If you’re running a MikroTik router with RouterOS v7+, you don’t need a separate Linux box as your WireGuard endpoint — it’s built right into the router. This is my preferred setup. Your router handles the tunnel directly, and you can policy-route specific devices through the VPS without touching their configs at all.
MikroTik makes solid, affordable routers for this. If you want a simple all-in-one with WiFi:
MikroTik hAP ax² (All-in-One) — WiFi 6, quad-core, handles WireGuard at line rate for most home connections. One box, done.
This is the one I actually use:
MikroTik hEX S (RB760iGS) — No WiFi (pair it with access points), but a rock-solid wired router with SFP and hardware offloading. Been running mine 24/7 for years without a single reboot.
Create the WireGuard Interface
Open a terminal to your MikroTik (WinBox, SSH, or WebFig) and create the WireGuard interface:
# Create the WireGuard interface
/interface/wireguard/add name=wg-vps listen-port=51820
# Check it — note the public key, you'll need it for the VPS peer config
/interface/wireguard/print
RouterOS auto-generates the keypair. Copy the public-key from the output — that goes into your VPS’s [Peer] section.
Assign an IP Address
# Give the tunnel interface an address
/ip/address/add address=10.0.0.2/24 interface=wg-vps
Add the VPS as a Peer
# Add your VPS as a WireGuard peer
/interface/wireguard/peers/add \
interface=wg-vps \
public-key="YOUR_VPS_PUBLIC_KEY_HERE" \
endpoint-address=your-vps-ip \
endpoint-port=51820 \
allowed-address=0.0.0.0/0 \
persistent-keepalive=25s
Setting allowed-address=0.0.0.0/0 means we can route anything through this tunnel. That doesn’t mean we will — the routing rules below control what actually goes through it.
Update the VPS Peer Config
On your VPS, add the MikroTik as a peer in /etc/wireguard/wg0.conf:
[Peer]
# MikroTik router
PublicKey = (MikroTik's public key from the print command above)
AllowedIPs = 10.0.0.2/32, 192.168.1.0/24
The 192.168.1.0/24 allows the VPS to route traffic back to your home LAN through the tunnel. Adjust to match your local subnet.
Route Specific Devices Through the VPS
This is where MikroTik shines. Instead of routing everything through the tunnel, you can selectively send specific devices’ internet traffic through the VPS. Perfect for a Plex server, a game server, or anything that needs a clean public IP.
# Create a routing table for VPS-bound traffic
/routing/table/add name=to-vps fib
# Default route through the tunnel in that table
/ip/route/add dst-address=0.0.0.0/0 gateway=10.0.0.1 routing-table=to-vps
# Don't policy-route traffic destined for the WG tunnel itself
# (prevents a routing loop — your VPS endpoint must go out the real WAN)
/ip/firewall/address-list/add list=vpn_endpoint address=your-vps-ip
/ip/firewall/mangle/add chain=prerouting action=accept \
src-address=192.168.1.100 dst-address-list=vpn_endpoint \
comment="Bypass VPN for WG endpoint traffic"
# Mark internet-bound traffic from your server for VPN routing
/ip/firewall/mangle/add chain=prerouting action=mark-routing \
new-routing-mark=to-vps passthrough=no \
src-address=192.168.1.100 dst-address-list=!rfc1918 \
comment="Route server traffic through VPS"
# NAT that traffic out the WireGuard interface
/ip/firewall/nat/add chain=srcnat action=masquerade \
src-address=192.168.1.100 out-interface=wg-vps \
comment="Masquerade server traffic on WG tunnel"
Replace 192.168.1.100 with the LAN IP of whatever device you want routed through the VPS. You can add multiple mangle and NAT rules for different devices.
The key detail: dst-address-list=!rfc1918 means only internet-bound traffic gets routed through the VPS. LAN traffic (192.168.x.x, 10.x.x.x, 172.16-31.x.x) stays local. Your server can still talk to everything on your network at full speed.
Allow WireGuard Through the Firewall
# Allow WireGuard traffic through the router's input chain
/ip/firewall/filter/add chain=input action=accept \
protocol=udp dst-port=51820 \
comment="Allow WireGuard"
# Allow established/related traffic on the WG interface
/ip/firewall/filter/add chain=forward action=accept \
connection-state=established,related in-interface=wg-vps
Verify It Works
# Check the tunnel is up and handshaking
/interface/wireguard/peers/print detail
# You should see a recent "last-handshake" and rx/tx byte counts
# Ping the VPS through the tunnel
/ping 10.0.0.1
Once the handshake is active, any device you’ve mangle-marked will have its internet traffic exit through your VPS’s public IP. You can verify by checking your public IP from that device — it should show the VPS IP, not your ISP.
Client Setup: macOS, Windows, and iOS
If you want to connect individual devices to your VPS tunnel (for remote access to your home network, or to use the VPS as a VPN exit point), here’s how to set up WireGuard on each platform.
macOS
Install from the Mac App Store or via Homebrew:
# Install via Homebrew
brew install wireguard-tools
# Generate keys
wg genkey | tee /tmp/wg-privatekey | wg pubkey > /tmp/wg-publickey
# Create the config
sudo mkdir -p /etc/wireguard
sudo tee /etc/wireguard/wg0.conf << 'EOF'
[Interface]
PrivateKey = (paste your private key)
Address = 10.0.0.3/24
DNS = 1.1.1.1
[Peer]
PublicKey = (VPS public key)
Endpoint = your-vps-ip:51820
AllowedIPs = 10.0.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25
EOF
# Bring the tunnel up
sudo wg-quick up wg0
# Check status
sudo wg show
# Bring it down
sudo wg-quick down wg0
Set AllowedIPs = 0.0.0.0/0 if you want all traffic routed through the VPS (full VPN mode). Use 10.0.0.0/24, 192.168.1.0/24 for split tunneling — only home network and tunnel traffic goes through WireGuard, everything else uses your local internet.
Windows
Download the official WireGuard client from wireguard.com/install.
- Install and open WireGuard
- Click Add Tunnel → Add empty tunnel
- It auto-generates a keypair — copy the Public Key shown at the top
- Paste this config into the editor:
[Interface]
PrivateKey = (auto-filled by the app)
Address = 10.0.0.4/24
DNS = 1.1.1.1
[Peer]
PublicKey = (VPS public key)
Endpoint = your-vps-ip:51820
AllowedIPs = 10.0.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25
- Save and click Activate
Don’t forget to add this client as a [Peer] on your VPS with its public key and AllowedIPs = 10.0.0.4/32.
iOS (and iPadOS)
Install WireGuard from the App Store.
The easiest method is to create a config file on your computer and scan it as a QR code:
# On your Mac or Linux box, create the mobile config
cat > /tmp/mobile-wg.conf << 'EOF'
[Interface]
PrivateKey = (generate a new key for this device)
Address = 10.0.0.5/24
DNS = 1.1.1.1
[Peer]
PublicKey = (VPS public key)
Endpoint = your-vps-ip:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF
# Generate a QR code to scan from your phone
qrencode -t ansiutf8 < /tmp/mobile-wg.conf
# Or if you don't have qrencode:
# brew install qrencode (macOS)
# apt install qrencode (Ubuntu/Debian)
Open WireGuard on your iPhone, tap + → Create from QR code, and scan it. Toggle the tunnel on and you’re connected.
For mobile, I recommend AllowedIPs = 0.0.0.0/0 (full tunnel) — when you’re on public WiFi, you want all traffic encrypted through your VPS anyway.
Remember: every new client device needs its own keypair and a corresponding [Peer] entry on the VPS. Each device gets a unique IP on the 10.0.0.x/24 subnet.
Self-hosting in rural areas doesn’t have to mean fighting with your ISP for a static IP. A $5 VPS and WireGuard give you everything you need to put your home lab on the public internet, securely and affordably.