The Problem: Remote Admin Access Should Not Depend on a Public SSH Port

We see the same pattern on a lot of Linux servers: the application is reasonably locked down, HTTPS is in place, backups exist, but SSH is still exposed to the entire internet. That does not automatically mean the server is compromised. It does mean the login surface is permanently visible to scanners, password-spraying bots, and background noise you do not need.

For small teams, agencies, and internal IT admins, the real problem is not “how do we change the SSH port?” It is “how do we stop treating SSH like a public service at all?” If the people who need administrative access are known in advance, the safer pattern is to put remote admin traffic behind a private tunnel and let SSH live there instead.

WireGuard is one of the cleanest ways to do that. It gives you a modern VPN with a compact configuration model, strong cryptography, and a practical Linux workflow. Instead of connecting to your-server:22 from anywhere on the internet, you connect to a private WireGuard address first and then administer the box over that encrypted tunnel.

This guide shows how to deploy a simple WireGuard server on Ubuntu 24.04, connect a laptop or admin workstation as a client, and then tighten SSH so your day-to-day administration flows through the VPN instead of a permanently exposed public port. If you are doing a broader server lockdown at the same time, pair this with our published guide to VPS Security Hardening in 30 Minutes. If your team prefers access without public ports but wants a different model, our Cloudflare Tunnel or Tailscale guide is also worth comparing.

What You Will Need / Prerequisites

For an admin-only WireGuard endpoint, we recommend starting with a Canadian Web Hosting Cloud VPS running Ubuntu 24.04 LTS. WireGuard itself is lightweight, so the sizing decision is usually driven by the applications on the server rather than the VPN layer. A small VPS with at least 1 to 2 vCPUs, 2 GB RAM, and SSD storage is enough for many admin-access deployments, provided the rest of the workload is modest.

You will need:

  • A Linux server with sudo access
  • A public IP or DNS name for the WireGuard endpoint
  • One admin client device such as a laptop or workstation
  • UDP port 51820 available
  • UFW installed if you want the firewall examples below

If you do not want to manage VPN keys, firewall policy, and access rotation yourself, CWH also offers Firewall & VPN services and Managed Support for teams that want the security benefit without taking on all the operating work.

Installation Steps

1. Install WireGuard and confirm the tools are present

On Ubuntu 24.04, the simplest supported path is the standard package install. This gives you the kernel module integration, the wg tool, and the wg-quick helper used for interface bring-up.

sudo apt update
sudo apt install -y wireguard ufw
wg --version

What this step does: installs WireGuard and the firewall tooling used later in the guide.

Expected result: wg --version returns a valid version string instead of command not found.

Common issue: if the package installs but the command is missing, make sure the install completed cleanly and rerun sudo apt install -y wireguard.

2. Generate the server key pair

WireGuard uses a public/private key pair for each peer. The official quickstart recommends generating keys with wg genkey and deriving the public key with wg pubkey. Keep the private key readable only by root.

sudo mkdir -p /etc/wireguard
cd /etc/wireguard
sudo umask 077
sudo sh -c 'wg genkey | tee server-private.key | wg pubkey > server-public.key'
sudo cat server-public.key

What this step does: creates a private key for the server and the matching public key you will later share with the client.

Expected result: the final command prints a single base64 public key line.

Common issue: if the files are world-readable, rerun with umask 077 so the private key is not exposed.

3. Build the server configuration

Now define a private VPN subnet and the interface settings. This example gives the server 10.44.0.1/24 and listens on UDP port 51820.

sudo nano /etc/wireguard/wg0.conf

Use a configuration like this:

[Interface]
Address = 10.44.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
SaveConfig = true

Replace SERVER_PRIVATE_KEY with the output of:

sudo cat /etc/wireguard/server-private.key

What this step does: defines the VPN interface and the internal address the server will use for admin traffic.

Expected result: the file exists at /etc/wireguard/wg0.conf and is readable only by root.

Common issue: a pasted private key with extra spaces or line breaks will prevent the interface from starting.

4. Generate the client key pair and add the peer to the server

Create a client identity for your laptop or admin workstation. You can generate this on the server for convenience, then move the client private key securely to the device you will use.

cd /etc/wireguard
sudo sh -c 'wg genkey | tee admin-laptop-private.key | wg pubkey > admin-laptop-public.key'
sudo cat admin-laptop-public.key

Add the peer to the server configuration:

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.44.0.2/32

Your finished /etc/wireguard/wg0.conf should look like this:

[Interface]
Address = 10.44.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
SaveConfig = true

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.44.0.2/32

What this step does: tells the server which client public key is allowed to connect and which VPN address that client will use.

Expected result: one peer block per admin device.

Common issue: reusing the same client key on multiple machines makes auditing and key rotation harder. Give each device its own peer entry.

5. Start the VPN and open the firewall

Bring up the interface with wg-quick and allow the UDP listener through UFW.

sudo systemctl enable --now wg-quick@wg0
sudo systemctl status wg-quick@wg0 --no-pager
sudo ufw allow 51820/udp
sudo ufw status

What this step does: starts WireGuard now, enables it on boot, and allows inbound VPN traffic.

Expected result: the service shows as active (exited) or active via the systemd unit, and UFW lists 51820/udp as allowed.

Common issue: if the service fails, check the config syntax with sudo wg-quick down wg0 followed by sudo wg-quick up wg0 to surface the exact parser error.

6. Create the client configuration

The client needs its own interface block plus the server peer definition. If the client sits behind NAT and needs stable reachability, the official WireGuard quickstart notes that PersistentKeepalive = 25 is a sensible interval.

[Interface]
Address = 10.44.0.2/32
PrivateKey = CLIENT_PRIVATE_KEY
DNS = 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = your.server.example:51820
AllowedIPs = 10.44.0.1/32
PersistentKeepalive = 25

If your goal is only secure administration of this server, keep AllowedIPs narrow. That way, only traffic for the server’s VPN address goes through the tunnel instead of pushing all client internet traffic over the VPS.

Configuration Notes That Matter in Production

The most important design choice is whether WireGuard is only for private admin access to the VPN endpoint itself, or whether it should also provide access to other private networks behind the server. For the first use case, this guide keeps the configuration deliberately simple: one server, one admin client, one private address on each side, and no broad LAN routing.

That simplicity is a feature. It reduces the chance of breaking routes, leaking more access than intended, or turning your small admin VPN into an accidental general-purpose tunnel. If all you really want is to SSH to the box securely, keep the scope narrow.

It is also worth planning key hygiene early. Use one peer per human or device, keep a naming convention for the key files, and remove peers when a laptop is retired or a contractor no longer needs access. WireGuard is easy to manage when the peer list stays tidy. It becomes messy when one shared admin key is copied across five devices and nobody remembers who still has it.

Verify It Works

Before you touch SSH firewall rules, confirm the tunnel is healthy.

sudo wg show
sudo ss -lunp | grep 51820

Expected result: wg show lists interface wg0, the peer public key, and eventually a recent handshake time after the client connects.

From the client device, activate the tunnel and test the private address:

ping 10.44.0.1
ssh your-user@10.44.0.1

If the SSH connection works over the VPN address, you have proven the important part: administration can happen without depending on the public IP. That is the point where WireGuard starts becoming a security control rather than just another service installed on the server.

Production Hardening

Restrict SSH to the WireGuard subnet

Do not close public SSH until you have confirmed VPN access from at least one client. Once that works, you can allow SSH only from the WireGuard subnet and remove the broader public rule.

sudo ufw allow from 10.44.0.0/24 to any port 22 proto tcp
sudo ufw delete allow OpenSSH
sudo ufw status

If you are nervous about locking yourself out, keep a second emergency session open while testing. It is better to move carefully than to turn a security improvement into an outage.

Use intrusion prevention on the remaining public surface

WireGuard reduces exposed login surface, but it does not replace broader host security. Keep your patching current, review user accounts, and use host protection on the services that do remain public. Our published comparison of Fail2ban vs CrowdSec is a good next step if you want to harden the box further.

Back up the configuration and document peer ownership

Your WireGuard config is small, but it is operationally important. Back up /etc/wireguard/, record which peer belongs to which person or device, and treat access revocation as part of your offboarding process. If the server is business-critical, pair it with CloudSafe Backup or your normal server backup workflow.

Consider managed options when the access model grows up

A one-server admin VPN is simple. A multi-office environment with identity integration, auditing, and network segmentation is not. When you move beyond a few admin peers, it may be time to pair the server with Firewall & VPN services or add Managed Support so the access layer does not depend on tribal knowledge.

Troubleshooting

The tunnel starts, but there is no handshake

Cause: the server port is blocked, the endpoint DNS is wrong, or the server and client public keys do not match the intended private keys.

sudo wg show
sudo ufw status
sudo journalctl -u wg-quick@wg0 --since "15 minutes ago" --no-pager

What you want to see: a recent handshake time in wg show and no firewall rule blocking UDP 51820.

Fix: confirm the endpoint hostname, reopen 51820/udp, and re-check that each peer has the correct public key.

You can connect to WireGuard, but SSH still fails

Cause: SSH is not listening, UFW still blocks port 22 from the VPN subnet, or your SSH daemon is bound only to the public interface.

sudo ss -tlnp | grep :22
sudo ufw status numbered
sudo sshd -T | grep listenaddress

What you want to see: port 22 listening and a firewall rule allowing 10.44.0.0/24 to connect.

Fix: restore the SSH allow rule for the WireGuard subnet, then reload SSH if you changed listener settings.

The interface does not come back after reboot

Cause: the systemd unit is not enabled or the config file permissions are wrong.

sudo systemctl is-enabled wg-quick@wg0
sudo systemctl status wg-quick@wg0 --no-pager
sudo ls -l /etc/wireguard

What you want to see: the unit enabled and the config files owned by root with restricted permissions.

Fix:

sudo systemctl enable wg-quick@wg0
sudo chmod 600 /etc/wireguard/wg0.conf /etc/wireguard/*.key

If the system still fails to bring the tunnel up, run sudo wg-quick up wg0 manually to get the direct error.

Conclusion / Next Steps

WireGuard is a practical way to solve a common admin problem: remote access that is secure without being awkward. Instead of leaving SSH open to the whole internet and hoping every surrounding control stays perfect, you move the trust boundary inward and make the VPN the front door for administration.

For most teams, the right first step is modest: stand up one WireGuard endpoint, connect one or two admin devices, prove SSH works over the tunnel, and only then tighten the public firewall rules. That small change already reduces noise, lowers exposure, and gives you a cleaner operational model for Linux administration.

If you are using that same server to host internal tools, this pattern fits well with self-hosted collaboration stacks too. See our draft Mattermost deployment guide for one example of an internal app you may also want to administer over private access instead of broad public exposure.

And if you want the benefits of private remote administration without owning every patch, key rotation, and firewall rule yourself, start with a CWH Cloud VPS and add Managed Support or Firewall & VPN services as your access needs grow.