WireGuard Backhaul (wg-easy)
A bidirectional VPN tunnel between the Hetzner VPS and the TrueNAS homelab, used as a backbone connection. Unlike Pangolin/Olm (which is VPS→homelab only), this allows the homelab to initiate connections to the VPS.
Architecture
TrueNAS (wg-easy server) Hetzner VPS (WireGuard peer)
10.8.0.1 ◄────── WireGuard ──────► 10.8.0.x
192.168.50.0/24 (VPS LAN services)
- Server: wg-easy runs on TrueNAS, reachable via DDNS (
tnt-mephisto.asuscomm.com:51821) - VPN subnet:
10.8.0.0/24 - Allowed routes pushed to peers:
192.168.50.0/24(homelab LAN) +10.8.0.0/24(VPN tunnel)
Prerequisites
- TrueNAS with Docker/Dockge
- Home router with port forwarding capability
- WireGuard installed on the VPS (
apt install wireguard-tools) - DDNS hostname pointing to your home IP
Step 1: Generate Password Hash
wg-easy requires a bcrypt hash for the web UI password. Generate one with Docker before deploying:
docker run --rm ghcr.io/wg-easy/wg-easy wgpw 'YourPasswordHere'
Copy the output — it will look like $2b$12$.... This goes into your .env file.
Step 2: Create .env File
In Dockge, create an .env file alongside the compose file:
PASSWORD_HASH=$$2b$$12$$your_hash_here
Important: Escape every
$in the hash as$$in the.envfile.
Step 3: Deploy wg-easy on TrueNAS
Create a new stack in Dockge with this compose file:
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:latest
container_name: wg-easy
network_mode: host
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_ADMIN
labels:
- homepage.group=Homelab
- homepage.name=WireGuard
- homepage.icon=wireguard.png
- homepage.href=http://192.168.50.203:51822/
- homepage.description=VPN manager
ports:
- 51821:51821/udp # WireGuard tunnel
- 51822:51822/tcp # Web UI
volumes:
- /mnt/tnt-hex/configs/wireguard:/etc/wireguard
environment:
TZ: Etc/UTC
WG_HOST: tnt-mephisto.asuscomm.com
WG_PORT: "51821"
PORT: "51822"
WG_PATH: /etc/wireguard
WG_DEVICE: enp34s0
WG_MTU: "1420"
WG_DEFAULT_DNS: 1.1.1.1
WG_DEFAULT_ADDRESS: 10.8.0.x
WG_ALLOWED_IPS: |-
192.168.50.0/24
10.8.0.0/24
WG_PERSISTENT_KEEPALIVE: "120"
PASSWORD_HASH: ${PASSWORD_HASH}
DEBUG: |-
Server
WireGuard
networks: {}
Note:
WG_DEVICEmust match the TrueNAS host NIC name. Verify withip link showon the TrueNAS shell.
Step 4: Port Forward on Home Router
Forward UDP port 51821 to TrueNAS (192.168.50.203):
| External Port | Protocol | Internal IP | Internal Port |
|---|---|---|---|
| 51821 | UDP | 192.168.50.203 | 51821 |
Step 5: Add VPS as a Peer
- Open the wg-easy web UI:
http://192.168.50.203:51822 - Log in with your password
- Click + New Client
- Name it
hetzner-vps(or similar) - Click the Download button next to the new peer to get its
.conffile
The downloaded config will look like:
[Interface]
PrivateKey = <generated>
Address = 10.8.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = <server public key>
PresharedKey = <generated>
AllowedIPs = 192.168.50.0/24, 10.8.0.0/24
PersistentKeepalive = 120
Endpoint = tnt-mephisto.asuscomm.com:51821
Step 6: Configure WireGuard on the VPS
Copy the downloaded config to the VPS:
scp hetzner-vps.conf user@your-vps:/etc/wireguard/wg-homelab.conf
Or paste it directly on the VPS:
sudo nano /etc/wireguard/wg-homelab.conf
Enable and start the tunnel:
sudo systemctl enable --now wg-quick@wg-homelab
Step 7: Verify Connectivity
From the VPS, ping the TrueNAS server through the tunnel:
ping 10.8.0.1 # wg-easy server VPN IP
ping 192.168.50.203 # TrueNAS LAN IP (routed via WG_ALLOWED_IPS)
Check tunnel status on the VPS:
sudo wg show
You should see the peer with a recent latest handshake timestamp and traffic counters incrementing.
Troubleshooting
No handshake / tunnel not establishing:
- Verify port forward is active:
nc -u tnt-mephisto.asuscomm.com 51821(should not time out immediately) - Check DDNS resolves correctly:
dig tnt-mephisto.asuscomm.com - Confirm
WG_DEVICEmatches the actual NIC:ip link showon TrueNAS shell
Peer connects but homelab LAN unreachable:
- Confirm
WG_ALLOWED_IPSincludes192.168.50.0/24in the wg-easy config - Verify IP forwarding is enabled on TrueNAS:
sysctl net.ipv4.ip_forward(should be1)
wg-easy web UI unreachable:
- Check the container is running:
docker ps | grep wg-easy - Confirm
network_mode: hostis set (required for kernel WireGuard interface access)
Password hash not accepted:
- Ensure all
$characters inPASSWORD_HASHare doubled ($$) in the.envfile