If you manage more than one server, or you just got tired of exposing phpMyAdmin, a staging site, or your monitoring dashboard to the open internet, a VPN is the fix. WireGuard has become the default choice because it's fast, the config file fits on a napkin, and it's already in the Linux kernel on any modern distro. This guide walks through installing it on a SkyServer VPS, connecting a client, and the handful of things that trip people up on the first attempt.

Why Put a VPN in Front of Your Admin Tools

Most VPS attacks aren't clever — they're bots scanning every IP on the internet for open ports. If your database admin panel, Grafana dashboard, or internal API only accepts connections from inside a WireGuard tunnel, none of that scanning matters. You've effectively removed the attack surface instead of trying to defend it. It's also just convenient: once connected, your laptop behaves as if it's sitting on the VPS's private network, so you can reach services bound to 127.0.0.1 or an internal subnet without SSH tunneling every single time.

Before You Start

  • A SkyServer VPS running Ubuntu 22.04/24.04, AlmaLinux 8/9, or Debian 11/12
  • Root or sudo access over SSH
  • One free UDP port (51820 is the WireGuard default, but you can pick anything)
  • A client device — laptop, phone, or another server

Step 1: Install WireGuard on the Server

On Ubuntu/Debian:

sudo apt update
sudo apt install wireguard wireguard-tools -y

On AlmaLinux/Rocky:

sudo dnf install epel-release -y
sudo dnf install wireguard-tools -y

Step 2: Generate the Server Keys

WireGuard uses public-key pairs instead of passwords. Generate the server's pair and lock down the private key:

cd /etc/wireguard
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key

Keep server_private.key secret — it never leaves this box. You'll paste server_public.key into every client config.

Step 3: Write the Server Config

Create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <paste server_private.key here>
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]
# client 1 — added in Step 5
PublicKey = <client public key>
AllowedIPs = 10.10.0.2/32

Swap eth0 for whatever your VPS calls its main interface — check with ip route | grep default if you're not sure. 10.10.0.0/24 is just a private range for the VPN itself; it doesn't need to match anything else on your network.

Step 4: Turn On IP Forwarding

Without this, the VPS won't route traffic between the tunnel and the internet (needed if you want full-tunnel VPN, not just access to the VPS itself):

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

If you only want to reach services running on this one VPS — not route all your internet traffic through it — you can skip forwarding and drop the PostUp/PostDown NAT lines entirely. Just point AllowedIPs on the client at the VPN subnet instead of 0.0.0.0/0.

Step 5: Generate a Client Config

Run these on the client machine, or on the server if it's easier and you're copying keys over securely:

wg genkey | tee client_private.key | wg pubkey > client_public.key

Client config, saved as wg0.conf on the client:

[Interface]
PrivateKey = <client_private.key>
Address = 10.10.0.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = <server_public.key>
Endpoint = your.vps.ip.address:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Set AllowedIPs = 10.10.0.0/24 instead of 0.0.0.0/0 if you only want split-tunnel access to the VPS's private network, leaving your regular internet traffic alone. Add the client's public key and its 10.10.0.2/32 address as a [Peer] block back in the server's wg0.conf (Step 3).

Step 6: Open the Firewall and Start the Tunnel

Whichever firewall you're running — UFW, firewalld, or CSF — allow the UDP port:

# UFW
sudo ufw allow 51820/udp

# firewalld
sudo firewall-cmd --permanent --add-port=51820/udp
sudo firewall-cmd --reload

Then bring the interface up on the server:

sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0

On the client, run wg-quick up wg0 (Linux) or import the config into the official WireGuard app (Windows, macOS, iOS, Android). For mobile, generate a QR code so you don't have to retype keys:

sudo apt install qrencode -y
qrencode -t ansiutf8 < client-wg0.conf

Step 7: Verify the Connection

sudo wg show

You want to see the peer listed with a recent latest handshake timestamp and a nonzero transfer count. From the client, ping the server's VPN address:

ping 10.10.0.1

If that responds, the tunnel is live.

Common Problems and Fixes

SymptomLikely CauseFix
No handshake at allUDP 51820 blocked by firewall or providerRe-check ufw/firewall-cmd rules and any network-level firewall on the VPS control panel
Handshake succeeds, but no internet through the tunnelIP forwarding off, or NAT/MASQUERADE rule missing or pointing at the wrong interfaceConfirm net.ipv4.ip_forward = 1 and that PostUp references your real outbound interface
Connects, but only reaches the VPS itselfClient's AllowedIPs is scoped to the VPN subnet onlyExpected in split-tunnel mode — set to 0.0.0.0/0 for full tunnel
Works for a minute, then dropsNAT/router in front of the client is dropping idle UDP sessionsKeep PersistentKeepalive = 25 in the client config
DNS still resolves through your ISPClient OS ignoring the DNS line in the configOn Linux, install resolvconf or systemd-resolved integration; on desktop apps this is usually automatic

Locking It Down Further

  • Give each device its own key pair — never share one private key across multiple clients. If a laptop is lost, you revoke just that peer.
  • Restrict AllowedIPs per peer as tightly as the use case allows. A monitoring server that only needs to poll one internal port doesn't need 0.0.0.0/0.
  • If your VPS has a dynamic IP or you're connecting between multiple sites, pair the client Endpoint with a small DDNS hostname instead of a raw IP.
  • Periodically run wg show and prune peers you no longer recognize from wg0.conf.
  • Combine this with SSH key-only login and fail2ban — WireGuard protects services behind it, but SSH itself is still worth hardening on its own.

Frequently Asked Questions

Is WireGuard better than OpenVPN for a VPS?

For most use cases, yes. WireGuard's codebase is a fraction of OpenVPN's size, it's built into the Linux kernel so there's less overhead, and setup is simpler because there's no certificate authority to manage — just key pairs. OpenVPN still has an edge in some corporate environments that require TCP-only traffic to get through restrictive firewalls, but for admin access to your own servers, WireGuard is the easier and faster choice.

Will running WireGuard slow down my VPS?

No, it's lightweight even on small VPS plans. The main cost is the encryption overhead on traffic passing through the tunnel, which is minimal on modern CPUs. You won't notice any impact on the services already running on the box.

Can I connect multiple devices to the same VPS?

Yes. Each device gets its own key pair and its own [Peer] block in the server config, with a unique address in the 10.10.0.0/24 range (or whatever subnet you chose). There's no practical limit for typical admin-access use cases.

Does this work if my VPS is behind CGNAT or my home internet is?

If the VPS has a public IP — which every SkyServer VPS does — clients connecting to it work fine regardless of what's happening on the client's end of the connection. CGNAT only becomes a problem if you're trying to reach a client from the server side, which isn't how this setup works.

Do I still need my firewall (UFW/CSF) if I set up WireGuard?

Yes — WireGuard secures one path in, it doesn't replace your firewall. Keep your firewall rules in place for the ports you intentionally expose (HTTP/HTTPS, SSH if you still allow direct access), and use the VPN specifically to hide the ports and services you don't want public at all.