Use case · VPN gateway

A WireGuard VPN server on a Cloud VPS, from keys to peers

A WireGuard VPN server is one Linux host with a public IPv4 address, a wg0 interface listening on a UDP port, IPv4 forwarding switched on and a NAT rule for the tunnel subnet; every client is a peer identified by its public key. WireGuard runs in the Linux kernel and publishes no hardware requirements, so on a VPS the figure that matters is traffic, not cores. This page builds the server on a Cloud VPS running Ubuntu, adds peers, and shows how the egress allowance meters a tunnel.

See the flavors

What WireGuard needs from the machine

WireGuard encapsulates IP packets in UDP. The project documents no CPU, memory or disk minimum: the module lives in the kernel, the configuration is a short text file, and the only daemon is the kernel itself. What the gateway does need is set out below.

RequirementWhyOn the Cloud VPS
Public IPv4 reachable on one UDP portClients send their handshake to the server's EndpointEach machine has its own IPv4 address
RootCreating interfaces, sysctl, netfilterRoot over SSH, keys installed at build
A Linux kernel with the moduleUbuntu and Debian ship it; Fedora-family systems need the tools packageUbuntu, Debian, AlmaLinux, Rocky Linux from official cloud images
IPv4 forwarding and source NATOnly needed when clients send internet traffic through the serverSet by you, below
Outbound trafficIn a full tunnel every byte a client downloads is sent again by the serverMetered as egress; see the traffic section

Routing is per key. WireGuard calls it cryptokey routing: on the server, each peer's AllowedIPs is both the route for packets going to that peer and the access list for packets arriving from it. A decrypted packet whose source address is not in the sending peer's list is dropped.

Why a VPS fits this job

A VPN gateway for one person or a small team is the small, steady job a virtual machine is sized for. The Cloud VPS is a KVM guest on OpenStack hosts that Server Room operates in New York. Each flavor caps its disk operations, disk throughput and port, so a neighbour cannot take those from your guest; vCPUs are not pinned, so processor time is shared. WireGuard's per-packet work is light enough that the shared vCPU is rarely what limits a small tunnel.

  • Running a VPN endpoint is explicitly allowed on the Cloud VPS.
  • The image list is Ubuntu, Debian, AlmaLinux and Rocky Linux; paste your SSH keys on the order page and they are installed for root.
  • Building starts once the first invoice is paid and usually takes a couple of minutes.
  • A noVNC console opens from the Virtual Machines tab while the machine runs, from a link that works once and expires after ten minutes. That is the way back in if a firewall rule locks out SSH.
  • Resizing to a larger flavor is a support request: one restart, same addresses, same data.

How egress metering applies to a tunnel

The monthly allowance counts only what the machine sends. In a full tunnel the gateway relays both directions, so the arithmetic is simple: a client downloading 10 GB means the VPS receives 10 GB from the internet (ingress, not counted) and sends 10 GB plus WireGuard's encapsulation overhead to the client (egress, counted). A client uploading 10 GB is the reverse: ingress from the client, egress to the internet. Either way, roughly everything that crosses the tunnel is counted once.

  • The period runs from the account's billing day, not the 1st, and unused traffic does not carry over.
  • At the allowance, egress is shaped to 10 Mbit/s for the rest of the period; ingress keeps full port speed and the machine is not stopped or suspended. For VPN users that means downloads through the tunnel slow to 10 Mbit/s.
  • Extra traffic can be bought in the Virtual Machines tab and counts once its invoice is paid.
  • The elastic billing option has no allowance and no throttle: egress is charged per GB and compute by the second while the machine runs.

A split tunnel, where AllowedIPs lists only private ranges, sends only that traffic through the server. For reaching internal services rather than browsing, it uses a fraction of the egress a full tunnel does.

Installing WireGuard and generating keys

Log in as root on a fresh Ubuntu machine. WireGuard's install page lists apt install wireguard for Ubuntu and Debian; on AlmaLinux and Rocky Linux the tools package is wireguard-tools. Keys are generated with wg genkey and wg pubkey under umask 077, as the quickstart shows. The last line prints the default route; its dev field is the public interface name to use wherever eth0 appears below, since cloud images often name it differently.

apt update && apt install wireguard
cd /etc/wireguard
umask 077
wg genkey | tee server.key | wg pubkey > server.pub

# make the kernel route between wg0 and the public interface
echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/70-wireguard-routing.conf
sysctl -p /etc/sysctl.d/70-wireguard-routing.conf

ip route show default

The server's wg0.conf

wg-quick reads /etc/wireguard/wg0.conf. Address and the PostUp/PreDown hooks are wg-quick extensions; everything else is passed to wg setconf. The private key is loaded from its own file by a PostUp hook, the method Ubuntu's server guide recommends, so the config can be shared for troubleshooting without leaking the secret. The NAT rule is added when the interface comes up and removed before it goes down.

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PostUp = wg set %i private-key /etc/wireguard/server.key
PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

[Peer]
# laptop
PublicKey = LAPTOP_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32

ListenPort is optional; without it the kernel picks a random port on each start, which a client config cannot follow. Any free UDP port works. Pick a tunnel subnet that does not collide with the networks your clients sit on.

Firewall, start-up and the first peer

  1. Allow SSH before anything else: ufw allow 22/tcp. The ufw manual warns that enabling the firewall flushes its chains and can drop an SSH session.
  2. Open the WireGuard port: ufw allow 51820/udp.
  3. Let tunnel traffic be forwarded out: ufw route allow in on wg0 out on eth0. Forwarded packets are filtered separately from traffic addressed to the host, so the port rule alone is not enough.
  4. Turn the firewall on with ufw enable.
  5. Register the unit for boot with systemctl enable wg-quick@wg0, then bring the interface up with systemctl start wg-quick@wg0.
  6. On the client, install WireGuard, generate its own key pair the same way, and write the config below. Put the client's public key into the server's [Peer] block.
  7. Check from the server with wg show: a latest handshake line under the peer means the keys and the port are right.
[Interface]
PrivateKey = LAPTOP_PRIVATE_KEY
Address = 10.8.0.2/24

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = VPS_IPV4:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

AllowedIPs = 0.0.0.0/0 makes the tunnel the client's default route for IPv4; wg-quick handles it with an fwmark and policy rules, so ip route still shows the old default. IPv6 traffic is not covered by this config: on a network with IPv6, the client's IPv6 connections bypass the tunnel unless you also tunnel IPv6 or disable it on the client. PersistentKeepalive = 25 is the interval the quickstart calls sensible for a peer behind NAT; leave it out on peers that do not need it.

Adding peers and keeping it tidy

  • Each new device gets its own key pair and the next free /32, for example 10.8.0.3/32. Never share a key between devices: the server cannot tell them apart and routes to whichever spoke last.
  • Append a [Peer] block to wg0.conf and run systemctl reload wg-quick@wg0. The unit's reload runs wg syncconf on the stripped config, which adds the peer without dropping existing sessions. Changes to Address or the hooks need a restart.
  • For phones, Ubuntu's guide turns a client config into a QR code with qrencode. The private key has to be written inside that config, so the QR code contains it: show it only to the device it is for, and do not save or share it.
  • An optional PresharedKey, made with wg genpsk, adds a symmetric key on top of the public-key exchange; both sides must carry the same value.
  • DNS: with a full tunnel the client may still ask the resolver of whatever network it is on. Add a DNS line to the client config pointing at a resolver you trust, or run one on the server and point clients at 10.8.0.1.
  • Keep the kernel and the wireguard package patched with the rest of the system.

When a VPS is the wrong host

The Cloud VPS is sold in New York only, so its exit address is in New York. If clients need an exit in Europe, or the tunnel carries a team's traffic all day and the egress allowance is spent month after month, a dedicated server is the next step: the port carries no allowance at all and you choose the city from the five we operate. The same goes for a gateway that should sit beside a hypervisor of your own, or one you want to manage from the hardware's own console below the operating system.

A common pattern is a small VPN gateway in front of private services that should never face the internet, such as a self-hosted Nextcloud server reachable only on its tunnel address.

Questions

Is a VPN endpoint allowed on the Cloud VPS?

Yes. The service page states plainly that running a VPN endpoint is fine. The terms of service still govern what passes through it, as they do for any traffic the machine sends.

Which UDP port should the server listen on?

Any free one. WireGuard has no reserved port; its documentation uses 51820 in examples, which is why most guides do too. Set it explicitly with ListenPort, because without it the kernel chooses a random port each time the interface comes up.

Does tunnel traffic count against the allowance twice?

No. Only egress is metered. A download through a full tunnel arrives at the VPS as ingress, which is free, and leaves as egress to the client, which counts once. Uploads are the mirror image.

Can I use Debian or Rocky Linux instead of Ubuntu?

Yes. All four systems on the Cloud VPS come from their distributions' official cloud images. Debian installs with apt install wireguard, and the steps on this page work unchanged. On AlmaLinux and Rocky Linux install wireguard-tools. The wg0.conf and wg-quick commands are the same there, but the firewall is firewalld rather than ufw, so open the UDP port and enable masquerading with firewall-cmd. If you keep the iptables hooks, install the iptables package first.

What if a firewall change locks me out of SSH?

Open the console from the Virtual Machines tab. It is a noVNC session in the browser while the machine runs, so you can sign in as root and fix the rule. The root password is shown in the dashboard on request.

How many peers can one server carry?

The bound that bites first is traffic, not the peer list: every peer in a full tunnel adds its downloads to the server's egress. Give each peer its own /32 inside the tunnel subnet, size the subnet for the devices you expect (a /24 leaves room for 253 clients beside the server), and watch the Virtual Machines tab's daily egress figures as you add people.

Put the gateway on a Cloud VPS

A KVM guest in New York: root access, its own IPv4 address and a browser console, built once the first invoice is paid, which usually takes a couple of minutes.

See the flavors

Related on Server Room

Other use cases