The easy part and the part that locks you out
WireGuard is a genuinely good piece of engineering: a small, fast, modern VPN that lives in the kernel and hides behind a couple of keys and a config file. Installing it takes one command. Generating a key pair takes one more. And then comes the step that has locked more people out of their own servers than any package ever will: bringing the interface up changes the machine's routing, and a routing change made carelessly can sever the very SSH session you are typing into.
So the thesis here is narrow and important: the install is trivial; the interface step is destructive, and deserves to be treated like one. Snapshot before, keep a rollback ready, and never close the session you have until a new one proves the machine is still reachable. Everything else in this piece serves that one rule.
Before the first package: read the network you are about to touch
Reconnaissance for a VPN is not optional politeness — it is how you avoid stacking a second tunnel on a working one, or breaking the addresses you depend on.
- Is WireGuard already here?
command -v wg && wg --version. If it is, you are configuring, not installing. - Does an interface already exist?
wg show. A live tunnel is a config you must not overwrite; read it before you touch anything, because clobbering a workingwg0is exactly how a remote link disappears. - What are the current interfaces and addresses?
ip -4 addr show | grep -c inet. You need to know how you currently reach the box so that whatever WireGuard does to the routing table does not quietly take that path away.
1. Install the package
On Debian and Ubuntu it is apt-get update && apt-get install -y wireguard. The proof it worked is a version string from wg --version — not that apt exited zero. Nothing about installing the package touches your connectivity yet; the package is inert until an interface is configured and brought up. That order matters, and it is why the dangerous step comes last, deliberately, after the safe ones have been proven.
2. Generate keys — and keep the private one private
WireGuard's security rests entirely on a key pair, so the way you create them is not a detail. The correct incantation sets the file mode before the key ever exists:
umask 077 && wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
The umask 077 is doing real work: it ensures the private key is written readable only by its owner, before a single byte lands on disk. A private key that is world-readable is a VPN anyone on the box can impersonate. The verification is concrete — test -s /etc/wireguard/privatekey && echo ok confirms the key exists and is non-empty — and it should be paired with a check that the permissions are as tight as you intended. This step is safe: it creates files, it does not touch the network.
3. Bring up the interface — the destructive step
Now the part that earns its warning. You write /etc/wireguard/wg0.conf and enable the interface with systemctl enable --now wg-quick@wg0. This is where routing changes, and it is why the interface step is classified as genuinely destructive: done wrong, it takes your access with it.
The classic foot-gun is AllowedIPs = 0.0.0.0/0, which tells WireGuard to route all traffic through the tunnel. On a client that is exactly what you want; on a remote server you administer over SSH, it can re-route your own management traffic into a tunnel that is not yet fully up, and the session dies mid-command. Decide deliberately whether this interface carries everything or only a private subnet, and if you are unsure, scope AllowedIPs to the VPN range and nothing more.
Treat this step the way any destructive change should be treated: snapshot the working state first, keep a rollback one command away — systemctl disable --now wg-quick@wg0 — and hold your current SSH session open while you open a new one to confirm the box is still reachable. Do not close the session that works until a fresh connection proves you have not locked yourself out. The verify for the step is that the interface is actually up: wg show wg0 >/dev/null 2>&1 && echo up. But the verify that matters to you is a second, independent login that succeeds.
What WireGuard does not do for you
WireGuard gives you an encrypted transport and private addressing between peers. It is not per-user access control: everyone with a valid key and a matching peer entry is on the network, and a leaked private key is access, full stop — there is no separate password to also get past. It is not a firewall for the services behind it; binding a database to a WireGuard address is better than binding it to the public internet, but the service still needs its own authentication. And a VPN is not a substitute for the hardening those services need in their own right. A private network narrows who can reach a port; it does not decide what they may do once they get there.
The check that proves the tunnel, and your access
In order: wg --version for the package; a private key that exists with tight permissions; wg show wg0 reporting the interface up with its peers; and — the one that actually protects you — a fresh SSH connection, opened after the interface came up, that succeeds. Prove the routing change did not cost you your access before you trust it, and never from the session you would lose. If the new login fails, the rollback is one command, and you still have the old session to run it from.
Where Servor fits
Servor ships WireGuard as a recipe — one of 150+ vetted playbooks — and the recipe shape is exactly what a network-altering task needs. It is not a script fired blind: it starts with reconnaissance, reading whether WireGuard is present, whether an interface already exists, and what the current addresses are, so the run adapts to a real server rather than assuming an empty one. Each step carries its own verify — the version, the key file, wg show wg0 — so the run proves it worked. The playbook is idempotent: an existing tunnel is read and reported, never overwritten.
Crucially, the interface step is marked destructive, which is not cosmetic: it triggers a snapshot beforehand, requires a second approval, and carries an explicit rollback (systemctl disable --now wg-quick@wg0) — because a routing change on a remote box is precisely the kind of operation that should never be slipped through unattended. And the execution never leaves the zero-knowledge path: every command is signed in your browser with a key derived from your vault key, relayed verbatim, and verified by the agent on the machine before it runs. Because the agent reaches the control plane over an outbound connection, your management path does not depend on the very routing you are about to change — the safety net does not run through the tunnel you might break.
The same care applied to the administrative door is in the SSH-hardening piece; the discipline for making any risky change reversible is in the safe destructive operations piece; and the approve-sign-verify loop behind it all is in the Plan-Execute-Verify piece. Browse the rest of the recipe catalogue, or see how it fits together in our server operations guide.