← Start of tutorial

WIUNIX ACADEMY

Set up a routed WireGuard site-to-site VPN on Ubuntu and Debian

Page 4 of 8. Review the earlier steps and prerequisites before continuing.

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Ubuntu 26.10Reviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment24 editable values
09

LET’S BUILD

Create a service owning only this table

On A/B. This oneshot unit owns only academy_wg; distribution nftables/UFW/firewalld services are outside this fresh-host recipe. Stopping it briefly removes its protection: never restart blindly during dependent work. Later rule edits need a planned change with the VPN stopped.

Bash
sudo nano /etc/systemd/system/academy-wg-filter.service
How do I know it worked?

A new unit file is ready for the next content.

Filter service file

FILE CONTENT on A/B. nft loads the file transactionally.

systemd · /etc/systemd/system/academy-wg-filter.service
[Unit]
Description=Academy dedicated WireGuard gateway filter
Before=wg-quick@wg0.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/nft -f /etc/wireguard/academy-filter.nft
ExecStop=/usr/sbin/nft delete table inet academy_wg

[Install]
WantedBy=multi-user.target
10

LET’S BUILD

Validate, activate and prove second SSH access

On A/B with console ready and current SSH open. A dependency requires filter startup before wg-quick. After activation, inspect the rules and establish a NEW authorized SSH session. If it fails, recover through the console-only panel; never flush the ruleset.

Bash
sudo install -d -m 0755 /etc/systemd/system/wg-quick@wg0.service.d
sudo tee /etc/systemd/system/wg-quick@wg0.service.d/20-academy-filter.conf >/dev/null <<'UNIT'
[Unit]
Requires=academy-wg-filter.service
After=academy-wg-filter.service
UNIT
sudo nft -c -f /etc/wireguard/academy-filter.nft
sudo systemd-analyze verify /etc/systemd/system/academy-wg-filter.service
sudo systemctl daemon-reload
sudo systemctl enable --now academy-wg-filter.service
sudo nft list table inet academy_wg
How do I know it worked?

Filter is active; rules are correct and a second authorized SSH session succeeds.

Second SSH session from the management workstation

On your management workstation in a NEW terminal, replace username, public IPs and port with the actual values. Keep the original sessions and console open.

Bash
ssh -p 22 -l REPLACE_ADMIN 198.51.100.10
ssh -p 22 -l REPLACE_ADMIN 203.0.113.20

Console-only management recovery

Only if the new filter blocks management, from independent console. Correct source/port before retrying.

Bash
sudo systemctl stop academy-wg-filter.service
11

LET’S BUILD

Start both tunnel interfaces

On A/B after filters and second SSH sessions pass. wg-quick normally chooses MTU from the endpoint path. Active systemd state proves interface setup, not a handshake or receiver data.

Bash
sudo systemctl enable --now wg-quick@wg0.service
systemctl is-active wg-quick@wg0.service
ip -br address show wg0
sudo wg show wg0 public-key
sudo wg show wg0 endpoints
sudo wg show wg0 allowed-ips
How do I know it worked?

Correct tunnel IPs and peer prefixes appear without a changed default route.

Explore all tutorials ↗