Hướng dẫn · 19/09/2026

How to Install a Secure WireGuard VPN on Ubuntu Server

WireGuard is a compact, modern, cross-platform VPN suited to secure remote access to servers and private networks. This guide builds a peer-to-site deployment on Ubuntu Server: every device receives a unique key pair, the server routes VPN traffic, and the firewall limits access.

Hướng dẫn cài WireGuard VPN trên Ubuntu Server an toàn từ A-Z

WireGuard is a compact, modern, cross-platform VPN suited to secure remote access to servers and private networks. This guide builds a peer-to-site deployment on Ubuntu Server: every device receives a unique key pair, the server routes VPN traffic, and the firewall limits access.

A VPN does not replace application authorization. A user connected to the network should still reach only the services they need.

Example architecture and values

  • The Ubuntu Server has a public IP or receives a forwarded UDP port.
  • Its Internet interface is eth0; replace this with the actual name.
  • WireGuard network: 10.66.66.0/24.
  • VPN server: 10.66.66.1; first client: 10.66.66.2.
  • UDP port: 51820.

Find the outgoing interface with ip route get 1.1.1.1. If the server is behind a router, forward UDP 51820 to its LAN address and reserve that address in DHCP. Ordinary port forwarding does not work behind CGNAT; obtain a public IP, suitable IPv6, an intermediary VPS, or another tunnel design.

1. Update Ubuntu and install WireGuard

sudo apt update
sudo apt upgrade
sudo apt install wireguard qrencode
sudo mkdir -p /etc/wireguard
sudo chmod 700 /etc/wireguard

qrencode is optional and used for phone enrollment. Before changing a remote firewall, keep a second SSH session open or ensure provider-console access so a mistake does not lock out administration.

2. Generate server keys

sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server.key'
sudo sh -c 'wg pubkey < /etc/wireguard/server.key > /etc/wireguard/server.pub'
sudo cat /etc/wireguard/server.pub

Only root should read the private key. Never send it through chat or email or commit it to Git. The public key can be shared with peers. Give every client its own pair so one device can be revoked independently.

3. Enable IP forwarding

Forwarding may not be needed when clients access only services on the VPN server itself. When the server is a gateway to the Internet or LAN, create:

sudo tee /etc/sysctl.d/70-wireguard-routing.conf > /dev/null <<'EOF'
net.ipv4.ip_forward = 1
EOF
sudo sysctl -p /etc/sysctl.d/70-wireguard-routing.conf

Run sysctl net.ipv4.ip_forward and expect 1. Enable IPv6 forwarding only after designing IPv6 addressing and firewall rules rather than copying IPv4 assumptions.

4. Create the server configuration

Create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.66.66.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY

# Client laptop
[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.66.66.2/32

Replace placeholders with real key values, then run sudo chmod 600 /etc/wireguard/wg0.conf. In WireGuard, AllowedIPs selects the peer for outbound traffic and acts as a source-address ACL on receipt. Never assign the same /32 to two clients.

To avoid embedding the server private key in the primary config, Ubuntu documentation demonstrates PostUp = wg set %i private-key /etc/wireguard/server.key. Either way, protect both key and configuration files with filesystem permissions.

5. Configure UFW and NAT

Allow SSH first and then open WireGuard:

sudo ufw allow OpenSSH
sudo ufw allow 51820/udp
sudo ufw route allow in on wg0 out on eth0 from 10.66.66.0/24
sudo ufw route allow in on eth0 out on wg0 to 10.66.66.0/24

For clients to use the server as an Internet gateway, add this NAT block near the top of /etc/ufw/before.rules, before existing *filter tables:

*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.66.66.0/24 -o eth0 -j MASQUERADE
COMMIT

Set DEFAULT_FORWARD_POLICY="ACCEPT" in /etc/default/ufw, then:

sudo ufw enable
sudo ufw reload
sudo ufw status verbose

Replace eth0 with the actual Internet interface. For LAN-only access where the LAN router has a return route to 10.66.66.0/24, routing without NAT preserves client addresses in logs; adapt routes and firewall rules to the real topology.

6. Create the first client

Generating keys on the client is preferable because its private key never leaves the device. On Linux:

umask 077
wg genkey > client.key
wg pubkey < client.key > client.pub

Add the client public key to its server [Peer] block. The client configuration is:

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

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = vpn.example.com:51820
AllowedIPs = 10.66.66.0/24
PersistentKeepalive = 25

PersistentKeepalive = 25 helps a client behind NAT maintain its mapping but is not necessary on every peer. Use dynamic DNS when the server public address changes.

7. Choose split tunnel or full tunnel

The configuration above is a split tunnel: only 10.66.66.0/24 uses the VPN. To reach a LAN, add its subnet, such as 192.168.10.0/24, to client AllowedIPs and permit the exact forwarding flow.

For a full tunnel, use AllowedIPs = 0.0.0.0/0, adding ::/0 only after IPv6 is configured. All client Internet traffic then crosses the server, requiring forwarding, NAT, DNS, and adequate capacity. It protects traffic on public Wi-Fi but adds load, latency, and operational responsibility.

8. Start and test the tunnel

sudo wg-quick up wg0
sudo wg show
ip address show wg0
sudo systemctl enable wg-quick@wg0

Connect the client, run ping 10.66.66.1, test private services, and inspect latest handshake and transfer in sudo wg show. With a full tunnel, verify the client's public IP and DNS path.

Use sudo systemctl reload wg-quick@wg0 to add peers with less disruption. Address, route, and hook changes may still require a full restart.

9. Add a phone securely with a QR code

qrencode -t ansiutf8 < phone.conf

In the mobile WireGuard application, create a tunnel from QR and scan it in a private administrative session. The QR contains the private key, so treat it as a password: do not screenshot it, attach it to a ticket, or retain temporary files unnecessarily.

10. Revoke a device

Remove the device's [Peer] block from the server and reload the service. Do not reuse keys for replacement hardware. If a server private key is exposed, create a new server pair and update every client; rotate only one peer when that peer's private key is compromised.

Troubleshooting

  • No handshake: inspect UDP 51820, port forwarding, public IP or CGNAT, Endpoint, and public keys.
  • Handshake but no ping: check AllowedIPs, duplicate addresses, UFW, and ip route.
  • Server reachable but no LAN or Internet: check IP forwarding, FORWARD rules, NAT, and return routes.
  • IP works but names fail: inspect client DNS and resolver reachability through the tunnel.
  • Some sites hang: test a lower MTU such as MTU = 1380 after confirming a path-MTU issue.
  • Mobile connection drops: apply PersistentKeepalive = 25 to the peer behind NAT.
sudo wg show
sudo journalctl -u wg-quick@wg0
ip route
sudo ufw status verbose
sudo ss -lunp | grep 51820

Security and operations checklist

  1. Every device has a unique key and VPN address.
  2. Private keys and configurations have restricted permissions.
  3. Firewall rules expose only necessary services to the VPN subnet.
  4. Public SSH is removed where administration can use the VPN.
  5. Peer owner, issue date, and revocation date are recorded.
  6. An encrypted server configuration backup exists off-host.
  7. Ubuntu is patched and unexpected handshakes are monitored.
  8. Peer revocation and configuration recovery are tested.

Conclusion

A sound WireGuard VPN is more than a successful handshake. It needs per-device keys, precise AllowedIPs, restrictive firewall rules, intentional routing or NAT, and a clear revocation process. Start with a small split tunnel, verify each flow, and expand to LAN or full-tunnel access only when required.

References

Discussion

Comments 0

Sign in to comment

You need an account to join the discussion and reply to other readers.

Sign inRegister

No comments yet. Be the first to share your thoughts.