Secure File Sync Between Linux Servers with Syncthing and WireGuard (Step-by-Step)

Why Syncthing + WireGuard is a smart choice

When you need reliable file synchronization between Linux servers, it’s tempting to reach for classic tools like rsync over SSH or an NFS share. Those options still work, but they can be painful when you have multiple sites, changing IP addresses, strict firewalls, or you want near real-time updates without a central storage server. A modern approach is to combine Syncthing (continuous, peer-to-peer file sync) with WireGuard (fast, secure VPN). You get encrypted transport, stable private IPs, and a sync tool that can handle intermittent connectivity gracefully.

This tutorial shows how to set up Syncthing to sync a directory between two Linux servers over a WireGuard tunnel. The result is a private “always-on” sync link that doesn’t require exposing Syncthing to the public internet.

What you’ll build

You will configure:

Server A: 10.10.10.1 (WireGuard interface: wg0)

Server B: 10.10.10.2 (WireGuard interface: wg0)

Syncthing will bind to the WireGuard interface so sync traffic stays inside the VPN. We’ll also harden firewall rules and enable Syncthing as a system service.

Prerequisites

Before you start, make sure both servers have sudo access and can reach each other on the internet (at least one side needs a reachable UDP port for WireGuard). You should also know which folder you want to sync, for example /srv/sync. This guide assumes Ubuntu/Debian-style commands; on RHEL/Fedora you can adapt package manager commands accordingly.

Step 1: Install WireGuard on both servers

On both servers, install WireGuard:

Debian/Ubuntu: sudo apt update && sudo apt install -y wireguard

Enable IP forwarding is not required for a simple point-to-point sync tunnel, but it doesn’t hurt to keep routing simple and only use the tunnel addresses for Syncthing.

Step 2: Create WireGuard keys

On each server, generate a keypair:

umask 077
wg genkey | tee ~/wg-private.key | wg pubkey > ~/wg-public.key

Copy each server’s wg-public.key to the other side. Keep private keys private.

Step 3: Configure the WireGuard tunnel

On Server A, create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.10.10.1/24
PrivateKey = SERVER_A_PRIVATE_KEY
ListenPort = 51820

[Peer]
PublicKey = SERVER_B_PUBLIC_KEY
AllowedIPs = 10.10.10.2/32
PersistentKeepalive = 25

On Server B, create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.10.10.2/24
PrivateKey = SERVER_B_PRIVATE_KEY

[Peer]
PublicKey = SERVER_A_PUBLIC_KEY
Endpoint = SERVER_A_PUBLIC_IP:51820
AllowedIPs = 10.10.10.1/32
PersistentKeepalive = 25

Start and enable the tunnel on both servers:

sudo systemctl enable --now wg-quick@wg0

Test connectivity:

ping -c 3 10.10.10.2 (from Server A)
ping -c 3 10.10.10.1 (from Server B)

Step 4: Install Syncthing on both servers

Install Syncthing from your distro repo or the official package source. On Debian/Ubuntu, the repo version may be older, but it still works. For a straightforward setup:

sudo apt update && sudo apt install -y syncthing

Step 5: Run Syncthing as a service (recommended)

Create a dedicated user (optional but clean) and run Syncthing under it. For a fast setup using your current user, enable the user service:

systemctl --user enable --now syncthing

If you prefer a system-wide service tied to a specific account:

sudo systemctl enable --now [email protected]

Step 6: Bind Syncthing to WireGuard only

To keep sync traffic inside the VPN, open Syncthing’s Web UI locally (or via SSH port forwarding) and adjust settings:

1) In Settings > Connections, set Listen Addresses to include the WireGuard IP, for example: tcp://10.10.10.1:22000 (Server A) and tcp://10.10.10.2:22000 (Server B).

2) Optionally disable global discovery and relays for a pure VPN setup: turn off Global Discovery and Enable Relaying. This reduces external dependencies and noise.

Step 7: Pair the devices and add a synced folder

In the Syncthing Web UI on Server A, click Add Remote Device, paste Server B’s Device ID, and save. Do the same in the other direction if it doesn’t auto-accept. Then add a folder such as /srv/sync on Server A and share it with Server B. On Server B, accept the share and choose the local path where files should land.

If you’re syncing application data, be mindful of file locks and databases. For PostgreSQL/MySQL, sync dumps or backups instead of live database files. For configs, scripts, and documents, Syncthing is a perfect fit.

Step 8: Firewall tips for a locked-down setup

At minimum, allow WireGuard UDP on the server that listens publicly (Server A in this example). With UFW:

sudo ufw allow 51820/udp

You do not need to expose Syncthing ports to the internet if it’s bound to the WireGuard IP. If you manage Syncthing’s UI remotely, use SSH port forwarding rather than opening the GUI port globally.

Troubleshooting checklist

No tunnel connection: verify public IP/port, confirm keys, and check sudo wg show for latest handshake times.

Devices don’t see each other: confirm Syncthing is listening on the WireGuard IP and that you used the correct Device IDs. Test with nc -vz 10.10.10.2 22000 across the tunnel.

Permissions problems: ensure the Syncthing service user can read/write the synced folder. Fix with ownership or ACLs.

Final notes

With Syncthing running over WireGuard, you get a clean and modern file sync stack: encrypted transport, stable addressing, and continuous synchronization without exposing extra services to the public internet. This approach scales nicely as you add more servers—just add peers to WireGuard and devices to Syncthing, then share the folders you need.

How to Set Up WireGuard VPN on Ubuntu Server 24.04 (Secure Remote Access in 15 Minutes)

Why WireGuard is a smart VPN choice in 2026

WireGuard is a modern VPN that focuses on speed, simplicity, and strong security. Compared to traditional VPN stacks, it uses fewer lines of code, performs well on low-cost VPS servers, and is easy to troubleshoot. This tutorial shows how to install and configure WireGuard on Ubuntu Server 24.04 so you can safely access your home or office network, manage servers remotely, and protect traffic on public Wi‑Fi.

What you need before starting

You will need: (1) an Ubuntu Server 24.04 machine with root or sudo access, (2) a public IP address or a router that can forward ports to the VPN server, and (3) a client device (Linux, Windows, macOS, Android, or iOS). If your server is behind NAT (common at home), you must forward a UDP port from your router to the server’s local IP.

Step 1: Update the server and install WireGuard

Start by updating packages and installing WireGuard and the helper tools. On Ubuntu 24.04, WireGuard is included in the standard repositories.

Run:

sudo apt update && sudo apt -y upgrade
sudo apt -y install wireguard

Step 2: Generate server keys (securely)

WireGuard uses public/private key pairs. Keep private keys secret and never paste them into tickets or chat. Create a dedicated directory and lock down permissions.

sudo -i
umask 077
mkdir -p /etc/wireguard
cd /etc/wireguard
wg genkey | tee server.key | wg pubkey > server.pub

You can view the public key with cat /etc/wireguard/server.pub. Avoid printing the private key unless absolutely necessary.

Step 3: Create the WireGuard server configuration

WireGuard’s default interface name is commonly wg0. Pick a private VPN subnet that does not conflict with your LAN. In this example, the VPN network is 10.10.10.0/24, and the server’s VPN IP is 10.10.10.1.

Create the config file:

nano /etc/wireguard/wg0.conf

Paste and adjust the following:

[Interface]
Address = 10.10.10.1/24
ListenPort = 51820
PrivateKey = YOUR_SERVER_PRIVATE_KEY

# Enable NAT so VPN clients can reach the internet (optional but common)
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

Replace YOUR_SERVER_PRIVATE_KEY with the content of /etc/wireguard/server.key. Also verify the server’s main network interface name. On many systems it is eth0, but it might be ens3, enp0s3, or similar. Check with ip a and update the PostUp/PostDown lines accordingly.

Step 4: Enable IP forwarding

If you want VPN clients to reach other networks (like the internet or your LAN), enable IP forwarding.

echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

Step 5: Create a client profile and add it to the server

Now generate keys for one client (repeat for each device). This example creates a client named laptop1 with VPN IP 10.10.10.2.

cd /etc/wireguard
wg genkey | tee laptop1.key | wg pubkey > laptop1.pub

Edit the server config and add a peer section at the bottom:

nano /etc/wireguard/wg0.conf

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.10.10.2/32

Replace CLIENT_PUBLIC_KEY with the content of laptop1.pub.

Step 6: Start WireGuard and enable it on boot

Bring up the VPN interface and ensure it starts automatically after reboots.

sudo systemctl enable --now wg-quick@wg0
sudo wg show

The wg show output is your first checkpoint. If the service fails, run sudo systemctl status wg-quick@wg0 to see exactly what went wrong (wrong interface name, missing key, or syntax issues are the usual suspects).

Step 7: Build the client configuration

Create a WireGuard client config file on your client device (or generate it on the server and copy it securely). You will need the server’s public key, the client’s private key, and your server’s public IP or DNS name.

Client config example:

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

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = YOUR_SERVER_PUBLIC_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

If you only want access to your private networks (and not route all traffic through the VPN), change AllowedIPs to your LAN subnet, for example 192.168.1.0/24, and keep 10.10.10.0/24 as needed. The PersistentKeepalive value helps mobile clients stay connected behind NAT.

Troubleshooting tips that save time

If the VPN connects but you cannot reach anything, check these items in order: (1) confirm UDP port 51820 is open/forwarded to the server, (2) verify your PostUp interface name matches the real outbound interface, (3) confirm IP forwarding is enabled, and (4) make sure the client’s AllowedIPs matches the routing you expect. Also review your firewall rules. On Ubuntu, you may need to allow the UDP port: sudo ufw allow 51820/udp. Finally, re-check keys; one incorrect character in a key line will prevent a proper handshake.

Next steps (best practices)

Once your first client works, add additional peers one at a time and assign each a unique VPN IP. Use a DNS name for the server if your IP changes often. Keep your system updated and consider restricting management access (SSH) to VPN-only for stronger security. WireGuard is lightweight enough to run on a small VPS, making it a practical “always-on” remote access solution for admins and power users.

Configure WireGuard VPN on Ubuntu Server 24.04 (With Clients, Firewall, and Split Tunneling)

Why WireGuard for a Modern VPN?

WireGuard has become a go-to VPN choice because it is fast, lightweight, and easier to maintain than many traditional VPN stacks. It uses modern cryptography, keeps configuration simple (a few keys and IPs), and performs well on cloud servers and home labs. In this tutorial, you will set up a secure WireGuard VPN server on Ubuntu Server 24.04, add clients, lock it down with a firewall, and optionally configure split tunneling so only specific traffic goes through the VPN.

What You Need

Before starting, make sure you have: (1) an Ubuntu Server 24.04 machine with sudo access, (2) a public IP address or a DNS name (for remote access), (3) UDP port 51820 available (or another port you choose), and (4) IP forwarding allowed (we will enable it). These steps work on a VPS and on-prem servers; for home routers you will also need port forwarding.

Step 1: Install WireGuard

Update packages and install WireGuard:

sudo apt update && sudo apt install -y wireguard

Ubuntu 24.04 ships with modern kernels and WireGuard support, so you don’t need extra repositories.

Step 2: Generate Server Keys

Create a secure directory and generate keys:

sudo umask 077
sudo mkdir -p /etc/wireguard
cd /etc/wireguard
sudo wg genkey | sudo tee server_private.key | sudo wg pubkey | sudo tee server_public.key

Your private key must remain secret. The public key will be shared with clients.

Step 3: Create the Server Configuration (wg0)

Decide on a VPN subnet. A common choice is 10.10.0.0/24. Create /etc/wireguard/wg0.conf:

sudo nano /etc/wireguard/wg0.conf

Paste and adjust the following (replace eth0 if your interface name differs):

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = (paste contents of /etc/wireguard/server_private.key)
PostUp = ufw route allow in on wg0 out on eth0
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

This enables NAT so VPN clients can reach the internet through the server (useful for secure browsing on public Wi-Fi). If you only need access to internal networks, you can skip NAT later and use routing instead.

Step 4: Enable IP Forwarding

Enable forwarding so the server can route traffic:

sudo nano /etc/sysctl.conf

Uncomment or add:

net.ipv4.ip_forward=1

Apply the change:

sudo sysctl -p

Step 5: Configure UFW Firewall

Allow SSH (if needed) and WireGuard’s UDP port:

sudo ufw allow OpenSSH
sudo ufw allow 51820/udp

Enable the firewall:

sudo ufw enable

If you are on a cloud provider, also open the same UDP port in the provider’s security group/firewall.

Step 6: Start WireGuard and Enable Autostart

Bring up the interface and enable it on boot:

sudo systemctl enable --now wg-quick@wg0

Verify status:

sudo wg
ip a show wg0

Step 7: Add a Client (Laptop/Phone)

On the server, generate a client key pair (example: client1):

cd /etc/wireguard
sudo wg genkey | sudo tee client1_private.key | sudo wg pubkey | sudo tee client1_public.key

Now add the client as a peer to the server. Edit /etc/wireguard/wg0.conf and append:

[Peer]
PublicKey = (paste contents of client1_public.key)
AllowedIPs = 10.10.0.2/32

Apply changes without dropping the tunnel:

sudo wg syncconf wg0 <(sudo wg-quick strip wg0)

Step 8: Create the Client Configuration

On your client device (or on the server to copy later), create a config named client1.conf:

[Interface]
PrivateKey = (paste contents of client1_private.key)
Address = 10.10.0.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = (paste contents of server_public.key)
Endpoint = YOUR_SERVER_IP_OR_DNS:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

The setting AllowedIPs = 0.0.0.0/0 routes all traffic through the VPN (full tunnel). PersistentKeepalive helps devices behind NAT stay connected.

Optional: Split Tunneling (Route Only What You Need)

If you only want access to the VPN subnet (and keep normal internet direct), change the client’s AllowedIPs to:

AllowedIPs = 10.10.0.0/24

If you need access to a private LAN behind the server (for example 192.168.1.0/24), add it:

AllowedIPs = 10.10.0.0/24, 192.168.1.0/24

Troubleshooting Tips

If the handshake does not happen, first confirm UDP port access from the internet and double-check the Endpoint. Run sudo wg on the server to see “latest handshake” timestamps. If clients connect but cannot browse the internet, re-check NAT rules and that IP forwarding is enabled. Also confirm your server interface name (use ip route to find it) and replace eth0 in the config if needed.

Next Steps

Once your first client works, repeat the peer/client steps for additional devices, giving each client a unique VPN IP (10.10.0.3/32, 10.10.0.4/32, and so on). For easier operations at scale, consider keeping a simple IP assignment list and backing up /etc/wireguard. With this setup, you now have a modern VPN that is fast, secure, and straightforward to maintain.

How to Deploy a Secure WireGuard VPN Server on Ubuntu 24.04 (With Client Setup)

Why WireGuard and Why Now?

WireGuard has become one of the most practical VPN technologies for modern networks because it is fast, lightweight, and easier to audit than older VPN stacks. For remote work, home labs, or small business admin access, a WireGuard server on Ubuntu 24.04 is a clean way to reach internal services without exposing them directly to the internet. This tutorial walks through a secure, real-world setup: server installation, firewall and forwarding, client configuration, and a few troubleshooting checks.

What You Need Before You Start

You will need an Ubuntu 24.04 server with root or sudo access, a public IPv4 address (or port-forwarding from your router), and a client device (Windows, macOS, Linux, Android, or iOS). Make sure you know your server’s public IP or DNS name. In this guide, we’ll use a private VPN subnet of 10.10.10.0/24 and the server will be 10.10.10.1.

Step 1: Install WireGuard on Ubuntu 24.04

Update packages and install WireGuard and basic firewall tooling:

Commands:
sudo apt update
sudo apt install -y wireguard ufw

Step 2: Generate Server Keys

WireGuard uses public key cryptography. Generate a private/public key pair for the server and protect the private key permissions:

Commands:
sudo umask 077
wg genkey | sudo tee /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pub

View the public key (you’ll share this with clients):

Command:
sudo cat /etc/wireguard/server.pub

Step 3: Create the WireGuard Interface Configuration

Create /etc/wireguard/wg0.conf. Replace YOUR_SERVER_PRIVATE_KEY with the contents of /etc/wireguard/server.key. If your server’s network interface is not eth0, replace it accordingly (common alternatives are ens3, enp1s0, etc.).

Command:
sudo nano /etc/wireguard/wg0.conf

Example wg0.conf:
[Interface]
Address = 10.10.10.1/24
ListenPort = 51820
PrivateKey = YOUR_SERVER_PRIVATE_KEY

PostUp = ufw route allow in on wg0 out on eth0; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = ufw route delete allow in on wg0 out on eth0; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

This configuration enables NAT so VPN clients can reach the internet or other networks through the server. If you only want access to internal resources and do not need internet tunneling, you can skip the NAT portion and route traffic differently, but NAT is the most common starter setup.

Step 4: Enable IP Forwarding

To route packets between the VPN interface and your main network interface, enable IPv4 forwarding:

Commands:
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-wireguard-forward.conf
sudo sysctl --system

Step 5: Configure the Firewall (UFW)

Allow the WireGuard UDP port and enable the firewall:

Commands:
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status

If SSH is not already allowed and you are connected remotely, ensure OpenSSH is permitted before enabling UFW to avoid locking yourself out.

Step 6: Start and Enable the WireGuard Service

Bring up the interface and configure it to start at boot:

Commands:
sudo systemctl enable --now wg-quick@wg0
sudo wg show

The wg show output is your first verification point. At this stage you will not see peers yet, which is normal.

Step 7: Create a Client (Peer) Configuration

On your client device (or on the server if you prefer and then copy files securely), generate client keys. On Linux, you can run:

Commands (client side):
umask 077
wg genkey | tee client1.key | wg pubkey | tee client1.pub

Now add the client as a peer on the server by editing /etc/wireguard/wg0.conf and appending a [Peer] block. Replace CLIENT1_PUBLIC_KEY with the contents of client1.pub:

Server wg0.conf (append):
[Peer]
PublicKey = CLIENT1_PUBLIC_KEY
AllowedIPs = 10.10.10.2/32

Restart WireGuard to apply changes:

Command:
sudo systemctl restart wg-quick@wg0

Step 8: Build the Client VPN Profile

Create a client configuration file (for example client1.conf) and import it into the WireGuard app (Windows/macOS) or WireGuard mobile app (Android/iOS). Replace placeholders with your real values:

Example client1.conf:
[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY
Address = 10.10.10.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = YOUR_SERVER_PUBLIC_IP_OR_DNS:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

If you only want access to your internal network and not full tunneling, replace AllowedIPs = 0.0.0.0/0 with only the networks you want to reach (for example 192.168.1.0/24 and 10.10.10.0/24). Keeping AllowedIPs tight is a simple way to reduce risk and avoid routing surprises.

Step 9: Verify the Connection and Troubleshoot

After activating the tunnel on the client, run these checks on the server:

Commands:
sudo wg show
sudo ss -lunp | grep 51820

In wg show, look for a recent latest handshake time and increasing transfer counters. If the handshake never happens, confirm UDP port 51820 is reachable from the internet (cloud security group, router port-forwarding, ISP restrictions). If handshake works but you cannot browse, re-check NAT rules, IP forwarding, and the client’s AllowedIPs. Also confirm your main interface name is correct in the PostUp/PostDown rules.

Security Tips for a Cleaner VPN Deployment

Keep your server updated, use SSH keys instead of passwords, and consider installing Fail2ban for SSH hardening. For WireGuard itself, the strongest control is peer management: only add the peers you need, assign each peer a single /32 address, and remove peers immediately when a device is lost or a user no longer needs access. WireGuard is simple by design, so good operational habits make the biggest difference.

Once this is working, you can expand the setup by adding more peers, routing to additional internal subnets, or placing WireGuard behind a firewall appliance. But even as-is, this Ubuntu 24.04 WireGuard server provides a modern, reliable VPN foundation for secure remote access.

3.

Install and Use Tailscale on Linux for a Secure Mesh VPN (Zero-Config Remote Access)

Why Tailscale is a smart VPN choice in 2026

Remote work and mixed networks are now normal: laptops on coffee shop Wi‑Fi, servers in a data center, and a home lab behind ISP NAT. Traditional VPN setups can be slow to deploy and painful to maintain (port forwarding, firewall rules, IPsec complexity). Tailscale is a modern mesh VPN built on WireGuard that focuses on easy connectivity, strong encryption, and sensible access controls. In this tutorial you will install Tailscale on Linux, connect devices into a private network, and harden access using ACLs, MagicDNS, and subnet routing.

What you will build

By the end, you will have a working mesh VPN where your Linux machine can securely reach other devices using stable hostnames, even if both ends are behind NAT. You will also learn two advanced features that are extremely useful in real environments: subnet routes (to reach an entire LAN) and exit nodes (to route internet traffic securely through a trusted device).

Prerequisites

You need one Linux system (Ubuntu/Debian, Fedora, or similar), a Tailscale account (free tiers are available), and sudo/root access. If you plan to use subnet routing or exit nodes, you will need at least two devices in the same tailnet. This guide uses command-line steps so you can repeat them on servers without a desktop.

Step 1: Install Tailscale on Linux

On Ubuntu/Debian, the quickest method is to use Tailscale’s repository so updates arrive via your package manager. Run the following commands:

Ubuntu/Debian
curl -fsSL https://tailscale.com/install.sh | sh

On Fedora, you can use dnf:

Fedora
sudo dnf install -y tailscale
sudo systemctl enable --now tailscaled

Verify the daemon is running:

systemctl status tailscaled

Step 2: Authenticate and bring the interface up

Start Tailscale and authenticate the device into your tailnet. On a server without a browser, the command prints a login URL you can open from another device:

sudo tailscale up

After login, check your assigned Tailscale IP and status:

tailscale status
tailscale ip -4

At this point you should already be able to ping another enrolled device using its Tailscale IP. If ICMP is blocked by local firewall rules, test with SSH instead.

Step 3: Enable MagicDNS (easy hostnames)

One of the most practical improvements is MagicDNS, which lets you reach devices by name rather than memorizing IPs. Open the Tailscale admin console, go to DNS settings, and enable MagicDNS. Within a minute, you should be able to resolve peers using names like server1 or server1.your-tailnet.ts.net (the exact domain depends on your tailnet).

Test resolution from Linux:

getent hosts server1

Step 4: Create basic ACLs (least privilege access)

A common mistake is leaving a VPN “flat,” where any device can reach any other device. Tailscale supports ACLs to restrict traffic by user, group, device tags, protocol, and port. In the admin console, open ACLs and start from a minimal policy: allow your admins to access SSH (port 22) on servers, and deny everything else by default.

A simple example concept (you will adjust names to match your environment) is: admins can reach tagged servers on SSH, and developers can only reach specific services. After applying, confirm from a non-admin account that SSH is blocked and from an admin account that it works. This is a huge security win for helpdesk and IT operations.

Step 5 (Advanced): Advertise a subnet route to reach an entire LAN

Subnet routing is perfect when you want to access devices that cannot run Tailscale (printers, NAS, hypervisors, IoT, lab switches). Choose one Linux box inside the LAN to act as a router. Then advertise the network range. Example for a home lab subnet 192.168.10.0/24:

sudo tailscale up --advertise-routes=192.168.10.0/24

Approve the route in the admin console (it will show as “pending”). Once approved, other tailnet devices should be able to reach 192.168.10.x addresses through the router. If it fails, check Linux IP forwarding:

sudo sysctl -w net.ipv4.ip_forward=1

Also review firewall rules (ufw/firewalld/nftables). You are not “opening ports to the internet,” but you still need to allow forwarding inside the host.

Step 6 (Advanced): Configure an exit node for secure browsing

An exit node routes your internet traffic through a trusted device (for example, a VPS or a server at home). On the device that will serve as the exit node, run:

sudo tailscale up --advertise-exit-node

Approve it in the admin console. On a client device that should use the exit node:

sudo tailscale up --exit-node=<exit-node-name-or-ip> --exit-node-allow-lan-access

The optional --exit-node-allow-lan-access flag is useful when you want to keep access to your local network while sending internet traffic through the exit node.

Troubleshooting tips

If connectivity is inconsistent, first run tailscale ping <peer> to see whether a direct path is possible or if it is relayed. Relaying is still encrypted and safe, but it can be slower. If you cannot reach a peer by name, re-check MagicDNS, then test with the Tailscale IP. On servers, verify that local firewall policies are not blocking the required ports (especially when using subnet routing). Finally, confirm your ACL policy is not accidentally denying the service you are testing.

Conclusion

With Tailscale on Linux, you can build a secure mesh VPN in minutes and then layer on serious controls like ACLs, MagicDNS, subnet routing, and exit nodes. This approach scales cleanly from a single admin managing a home lab to a helpdesk team supporting remote endpoints, without the usual VPN headaches.

Configure WireGuard Site-to-Site VPN on Linux (2025 Guide)

Why WireGuard for a Site-to-Site VPN?

WireGuard has become a go-to VPN choice for modern Linux networks because it is fast, lightweight, and easier to audit than many legacy VPN stacks. For a site-to-site setup (connecting two networks, like HQ and a branch office), WireGuard works especially well: it uses simple public-key cryptography, keeps the configuration small, and performs efficiently even on modest hardware or small cloud VPS instances.

In this tutorial, you will build a reliable site-to-site WireGuard VPN between two Linux gateways. The steps are written for current distributions such as Ubuntu 22.04/24.04 or Debian 12, but the process is similar on most Linux systems. The goal is to route traffic between two private subnets securely, without exposing internal services to the public internet.

Network Example (Adjust to Your Environment)

This guide uses a clear example so you can map it to your own network. Site A (HQ) has LAN 192.168.10.0/24 and a Linux gateway with public IP A_PUBLIC_IP. Site B (Branch) has LAN 192.168.20.0/24 and a Linux gateway with public IP B_PUBLIC_IP. WireGuard will use a dedicated tunnel network: 10.99.0.0/24, where Site A will be 10.99.0.1 and Site B will be 10.99.0.2.

Prerequisites: UDP port access (commonly 51820), root or sudo privileges, and the gateways must be able to reach each other over the internet. Make sure you are not using overlapping LAN ranges (for example, both sides using 192.168.1.0/24). Overlapping subnets are a common reason site-to-site VPN routing fails.

Step 1: Install WireGuard

On both gateways, install WireGuard:

Ubuntu/Debian:

sudo apt update && sudo apt install -y wireguard

If you are using another distro, install the equivalent package (for example, on RHEL-based systems you may use EPEL or distro repositories depending on your version).

Step 2: Generate Keys (Both Sides)

WireGuard uses a private/public key pair per node. On Site A:

umask 077
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey

Repeat the same on Site B. Then read the public keys so you can paste them into the peer configuration:

cat /etc/wireguard/publickey

Keep private keys private. Do not copy them into tickets, chat, or documentation.

Step 3: Create the WireGuard Config on Site A

Create /etc/wireguard/wg0.conf on Site A:

[Interface]
Address = 10.99.0.1/24
ListenPort = 51820
PrivateKey = SITE_A_PRIVATE_KEY
PostUp = sysctl -w net.ipv4.ip_forward=1; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT

[Peer]
PublicKey = SITE_B_PUBLIC_KEY
AllowedIPs = 10.99.0.2/32, 192.168.20.0/24
Endpoint = B_PUBLIC_IP:51820
PersistentKeepalive = 25

The key line for site-to-site routing is AllowedIPs. It tells Site A that traffic for the branch LAN (192.168.20.0/24) should be routed into the tunnel toward Site B.

Step 4: Create the WireGuard Config on Site B

Create /etc/wireguard/wg0.conf on Site B:

[Interface]
Address = 10.99.0.2/24
ListenPort = 51820
PrivateKey = SITE_B_PRIVATE_KEY
PostUp = sysctl -w net.ipv4.ip_forward=1; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT

[Peer]
PublicKey = SITE_A_PUBLIC_KEY
AllowedIPs = 10.99.0.1/32, 192.168.10.0/24
Endpoint = A_PUBLIC_IP:51820
PersistentKeepalive = 25

Step 5: Enable IP Forwarding Permanently

WireGuard can come up fine but routing will still fail if forwarding is disabled after reboot. On both gateways:

echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard-forward.conf
sudo sysctl --system

Step 6: Start and Enable the Tunnel

Bring up the tunnel on both sides:

sudo systemctl enable --now wg-quick@wg0

Check status and handshake:

sudo wg show

You should see a recent handshake time and data counters increasing when traffic flows.

Step 7: Firewall and Routing Checks

If you cannot reach the remote LAN, start with the basics: confirm UDP port 51820 is open on both public interfaces, and confirm that the LAN hosts use the Linux gateway as their default route (or have a route to the opposite LAN via the gateway). A very common issue is that the gateways can ping each other over the tunnel, but client machines cannot, because the clients do not know where to send the return traffic.

Test from the gateways first: ping Site B tunnel IP from Site A (ping 10.99.0.2) and then ping a host on the branch LAN. If gateway-to-gateway works but LAN-to-LAN fails, you likely need to add static routes on your LAN routers or ensure the gateways are the default routers for their subnets.

Step 8: Quick Troubleshooting Tips

No handshake: verify the endpoint IP/port, confirm public keys match the correct peers, and check upstream NAT or security groups. Handshake but no LAN access: confirm IP forwarding is enabled, confirm AllowedIPs includes the remote LAN, and confirm routes on LAN clients. Intermittent connectivity: keep PersistentKeepalive = 25 on at least one side when NAT is involved.

Once the tunnel is stable, you can harden it further by limiting which ports are allowed between sites, moving from iptables rules to a dedicated firewall policy, and documenting the exact subnets in AllowedIPs so the VPN stays predictable as your network grows.

Configure a WireGuard Site-to-Site VPN on Linux (Ubuntu/Debian) with Persistent Routing

Why WireGuard for a Site-to-Site VPN?

WireGuard has become one of the most practical VPN choices for modern Linux environments because it is fast, secure, and easy to troubleshoot. Unlike many older VPN stacks, WireGuard uses a small codebase and straightforward configuration files. In this tutorial, you will set up a site-to-site WireGuard VPN between two Linux servers (or gateways) so that two private networks can reach each other reliably, even after reboots.

Example scenario (adjust to your environment): Site A has LAN 10.10.0.0/24 and a Linux gateway with public IP A_PUBLIC. Site B has LAN 10.20.0.0/24 and a Linux gateway with public IP B_PUBLIC. WireGuard tunnel network will be 10.99.0.0/24, using 10.99.0.1 on Site A and 10.99.0.2 on Site B.

Prerequisites

You need root (or sudo) access on both gateways, outbound UDP allowed, and ideally a static public IP or stable DNS name for each side. This guide assumes Ubuntu/Debian, but the same concepts apply to other distributions. You should also confirm that each gateway can route traffic for its LAN (common when the gateway is also the LAN router, or when static routes exist on the LAN router pointing to the gateway).

Step 1: Install WireGuard

On both servers, install WireGuard tools:

Command:
sudo apt update && sudo apt install -y wireguard

Step 2: Generate Key Pairs

WireGuard uses public/private key pairs. Generate them on each gateway and store them with correct permissions:

On Site A:
umask 077
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey

On Site B:
umask 077
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey

Display each public key (you will paste it into the opposite side’s config):

Command:
cat /etc/wireguard/publickey

Step 3: Create the WireGuard Interface Config

WireGuard configurations live in /etc/wireguard/. Create wg0.conf on each site. Replace placeholders like A_PRIVATE_KEY, B_PUBLIC_KEY, and public IPs/DNS names.

Site A: /etc/wireguard/wg0.conf

[Interface]
Address = 10.99.0.1/24
ListenPort = 51820
PrivateKey = A_PRIVATE_KEY

[Peer]
PublicKey = B_PUBLIC_KEY
Endpoint = B_PUBLIC:51820
AllowedIPs = 10.99.0.2/32, 10.20.0.0/24
PersistentKeepalive = 25

Site B: /etc/wireguard/wg0.conf

[Interface]
Address = 10.99.0.2/24
ListenPort = 51820
PrivateKey = B_PRIVATE_KEY

[Peer]
PublicKey = A_PUBLIC_KEY
Endpoint = A_PUBLIC:51820
AllowedIPs = 10.99.0.1/32, 10.10.0.0/24
PersistentKeepalive = 25

The key detail for site-to-site routing is AllowedIPs. It tells WireGuard what networks to send through the tunnel. Here, each side includes the other site’s LAN (10.10.0.0/24 or 10.20.0.0/24) so packets are routed correctly.

Step 4: Enable IP Forwarding

If your gateways must pass traffic between LAN and VPN, Linux needs forwarding enabled. On both sites, run:

Command:
sudo sysctl -w net.ipv4.ip_forward=1

To make it persistent across reboots, edit /etc/sysctl.conf (or create a file under /etc/sysctl.d/) and ensure this line exists:

net.ipv4.ip_forward=1

Step 5: Adjust Firewall to Allow WireGuard UDP

WireGuard typically listens on UDP 51820. Allow it on both gateways. If you use UFW:

Command:
sudo ufw allow 51820/udp

If you rely on nftables/iptables, allow inbound UDP 51820 and ensure forwarding is permitted between your LAN interface and wg0. Firewall rules vary by environment, but the goal is consistent: UDP port open and forwarding allowed.

Step 6: Bring Up the Tunnel and Enable Autostart

Start the interface on both sides:

Command:
sudo wg-quick up wg0

Enable it at boot:

Command:
sudo systemctl enable wg-quick@wg0

Step 7: Test Connectivity and Routing

First, verify WireGuard handshake status:

Command:
sudo wg

You should see a recent “latest handshake” timestamp after traffic flows. Next, test the tunnel IPs:

From Site A:
ping -c 4 10.99.0.2

From Site B:
ping -c 4 10.99.0.1

Then test LAN-to-LAN reachability. For example, from a host on Site A LAN, ping a host on Site B LAN (or test from the gateway if it can reach the LAN):

Example:
ping -c 4 10.20.0.50

Common Problems (and Quick Fixes)

No handshake: confirm UDP 51820 is reachable from the internet, double-check Endpoint address/port, and ensure the correct public keys are pasted. A mismatched key is the fastest way to waste an hour.

Handshake works but LAN traffic fails: this is usually routing or firewall forwarding. Confirm IP forwarding is enabled and that your firewall allows forwarding between LAN and wg0. Also verify that each peer’s AllowedIPs includes the remote LAN subnet.

Remote LAN devices don’t know the return route: if your WireGuard box is not the default router for the LAN, you may need a static route on the LAN router (e.g., route 10.20.0.0/24 via the Site A WireGuard gateway IP, and vice versa).

Final Notes for a Stable Production Setup

For long-term reliability, keep configs simple and document your addressing plan. Consider using DNS names for Endpoints if IPs change, but make sure DNS is stable. Once everything works, capture the working configuration and back up /etc/wireguard/ securely, since private keys are sensitive. With the tunnel online, you can extend this design to multiple sites or add policy-based firewall rules to limit traffic between subnets.

Set Up WireGuard VPN on Ubuntu Server 24.04 with Split Tunneling and QR Codes

Why WireGuard in 2025?

WireGuard is a modern VPN that focuses on speed, clean configuration, and strong cryptography. Compared to older VPN stacks, it is lightweight and easier to audit, which is why it has become a default choice for many admins who need secure remote access without complex tooling. In this tutorial, you will install WireGuard on Ubuntu Server 24.04, create a client profile, enable split tunneling (route only private subnets through the VPN), and generate a QR code for quick setup on mobile devices.

What You Need

Before you start, prepare: (1) an Ubuntu Server 24.04 VPS or on-prem server with root or sudo access, (2) UDP port 51820 allowed on your firewall/security group, (3) a public IP address or a DNS name, and (4) one client device (Windows, macOS, Linux, Android, or iOS). The steps below assume your server has a network interface like eth0. If your interface is different (for example, ens3), adjust the commands accordingly.

Step 1: Install WireGuard Tools

Update your package index and install WireGuard plus a QR utility. The qrencode tool is optional, but it makes mobile onboarding dramatically faster.

Commands:

sudo apt update
sudo apt install -y wireguard qrencode

Step 2: Enable IP Forwarding (Required for Routing)

If you want VPN clients to reach your internal networks (or the internet through the server), IP forwarding must be enabled. For split tunneling to private subnets, forwarding is still required so the server can route traffic between the VPN interface and your LAN/WAN interface.

Commands:

echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

Step 3: Generate Server Keys

WireGuard uses public/private key pairs. Keep private keys secret. We will store them in the WireGuard directory with strict permissions.

Commands:

sudo install -m 700 -d /etc/wireguard
cd /etc/wireguard
umask 077
wg genkey | sudo tee server.key | wg pubkey | sudo tee server.pub

Step 4: Create the Server Configuration (wg0.conf)

We will create a VPN subnet, for example 10.10.10.0/24. The server will use 10.10.10.1. For split tunneling, clients will only route specific private subnets through the tunnel, such as 192.168.1.0/24 and 10.0.0.0/8. If you also want full-tunnel later, you can expand the AllowedIPs on the client side.

Create /etc/wireguard/wg0.conf:

sudo nano /etc/wireguard/wg0.conf

Paste and adjust:

[Interface]
Address = 10.10.10.1/24
ListenPort = 51820
PrivateKey = (paste contents of /etc/wireguard/server.key)
# Replace eth0 with your public interface
PostUp = ufw route allow in on wg0 out on eth0; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = ufw route delete allow in on wg0 out on eth0; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

Step 5: Allow UDP 51820 in the Firewall

If you use UFW, allow WireGuard’s UDP port. If your hosting provider has an external firewall/security group, open the same port there as well.

Commands:

sudo ufw allow 51820/udp
sudo ufw enable
sudo ufw status

Step 6: Create a Client Profile (Keys + Peer Entry)

Now generate a client key pair, assign an IP like 10.10.10.2, and add the client as a peer in the server config. This example is for one client called laptop1. Repeat the pattern for more users (use a new key pair and a new IP each time).

Commands:

cd /etc/wireguard
umask 077
wg genkey | sudo tee laptop1.key | wg pubkey | sudo tee laptop1.pub

Edit the server config and append a peer block:

sudo nano /etc/wireguard/wg0.conf

Add at the end:

[Peer]
PublicKey = (paste contents of /etc/wireguard/laptop1.pub)
AllowedIPs = 10.10.10.2/32

Step 7: Start WireGuard and Enable It on Boot

Bring up the interface and make sure it persists after reboots. Then confirm WireGuard is listening.

Commands:

sudo systemctl enable --now wg-quick@wg0
sudo wg show
sudo ss -lunp | grep 51820

Step 8: Build the Client Configuration (Split Tunnel)

Create a local file on your admin machine, or generate it on the server and copy it securely. Replace YOUR_SERVER_PUBLIC_IP with your server’s public IP (or DNS name). For split tunneling, set AllowedIPs to only the networks you want routed through the VPN, plus the WireGuard subnet if you want client-to-client visibility.

Example client config (laptop1.conf):

[Interface]
PrivateKey = (paste contents of /etc/wireguard/laptop1.key)
Address = 10.10.10.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = (paste contents of /etc/wireguard/server.pub)
Endpoint = YOUR_SERVER_PUBLIC_IP:51820
AllowedIPs = 10.10.10.0/24, 192.168.1.0/24, 10.0.0.0/8
PersistentKeepalive = 25

Step 9: Generate a QR Code for Mobile Clients

On Android and iOS, the official WireGuard app can import from a QR code. This avoids typos in keys and endpoints. Run qrencode against the client configuration file and scan it in the app.

Commands:

qrencode -t ansiutf8 < laptop1.conf

Troubleshooting Tips

If the tunnel connects but you cannot reach private subnets, check routing on the server and confirm that the destination network knows how to return traffic to 10.10.10.0/24 (either via the WireGuard server as a gateway or via NAT). If handshakes never appear in wg show, verify UDP 51820 is open, confirm your Endpoint is correct, and ensure your server’s clock is accurate (NTP issues can sometimes cause confusing behavior). Finally, if you run another firewall besides UFW, make sure it is not blocking forwarding between wg0 and your outbound interface.

Next Steps

Once your first client works, add more peers and give each one a unique VPN IP. For better security hygiene, keep peer access tight by limiting AllowedIPs to only the subnets each user needs. If you want to manage many devices, consider storing configs in a password manager and rotating keys on a schedule, especially for contractors or short-term users.

Install and Secure WireGuard VPN on Ubuntu 24.04 LTS (DNS, Kill Switch, Mobile QR Codes)

Overview

This step-by-step guide shows you how to install and secure a WireGuard VPN on Ubuntu 24.04 LTS. You will enable IP forwarding, add NAT, configure DNS, generate mobile-friendly QR codes, and set up a client kill switch on Linux. WireGuard is fast, modern, and simple—perfect for remote access, privacy, and self-hosted lab networks.

What you need

You need an Ubuntu 24.04 server with sudo, a public IP (or port-forwarded UDP 51820), and a basic understanding of the terminal. Replace interface names like eth0 with your actual WAN NIC (for example, ens3 or enp1s0), and replace placeholders like SERVER_PUBLIC_IP with your values.

1) Install WireGuard and tools

Update the package index, then install WireGuard, UFW (if you use it), and a small utility to generate QR codes for mobile clients.

sudo apt update
sudo apt install -y wireguard qrencode ufw

2) Generate server keys

Create a private and public key for the server. The private key must stay secret and readable only by root.

sudo -i
umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub
cat /etc/wireguard/server.key
cat /etc/wireguard/server.pub

Copy the printed keys to use in the configuration files below. Do not share the private key with anyone.

3) Enable IP forwarding

Turn on IPv4 and IPv6 forwarding so the server can route traffic from clients to the Internet.

echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-wireguard.conf
echo 'net.ipv6.conf.all.forwarding=1' | sudo tee -a /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

4) Create the WireGuard server config

Create /etc/wireguard/wg0.conf. Replace SERVER_PRIVATE_KEY with the contents of /etc/wireguard/server.key, and replace eth0 with your external interface.

sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
SaveConfig = true
MTU = 1420

# NAT and forwarding rules (iptables-nft works on Ubuntu 24.04)
# Replace eth0 with your WAN NIC (e.g., ens3)
PostUp   = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; \
           iptables -A FORWARD -i %i -j ACCEPT; \
           iptables -A FORWARD -o %i -m state --state RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; \
           iptables -D FORWARD -i %i -j ACCEPT; \
           iptables -D FORWARD -o %i -m state --state RELATED,ESTABLISHED -j ACCEPT

Allow UDP 51820 on the firewall, then start and enable the service.

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

5) Add your first peer (client)

Generate a client keypair on the server (safe for a single user or a small team). Each client must have a unique address.

cd /root
umask 077
wg genkey | tee client1.key | wg pubkey > client1.pub
CLIENT_PRIV=$(cat client1.key)
CLIENT_PUB=$(cat client1.pub)
SERVER_PUB=$(cat /etc/wireguard/server.pub)

Append a [Peer] block for the client to /etc/wireguard/wg0.conf. This line assigns 10.8.0.2/32 to the client and restricts it tightly.

sudo bash -c 'cat >> /etc/wireguard/wg0.conf' << 'EOF'
[Peer]
# client1
PublicKey = REPLACE_WITH_CLIENT1_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32
EOF

Apply the change without downtime:

sudo wg syncconf wg0 <(wg-quick strip wg0)

6) Build the client config (with DNS)

Create a client configuration file that routes all traffic through the VPN and uses secure DNS. Replace SERVER_PUBLIC_IP or domain and keep port 51820/udp open. Linux, macOS, Windows, iOS, and Android all accept this format.

cat > client1.conf << EOF
[Interface]
Address = 10.8.0.2/32
PrivateKey = CLIENT1_PRIVATE_KEY
DNS = 1.1.1.1, 9.9.9.9
MTU = 1420

[Peer]
PublicKey = SERVER_PUBLIC_KEY
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = SERVER_PUBLIC_IP:51820
PersistentKeepalive = 25
EOF

7) Show a QR code for mobile apps

Install the WireGuard app on iOS or Android, then scan this QR code displayed in your terminal to import the profile instantly.

qrencode -t ansiutf8 < client1.conf

If your terminal does not render Unicode well, save a PNG with qrencode -o client1.png < client1.conf and open it locally.

8) Optional: Linux client kill switch

A kill switch blocks all traffic outside the VPN. The rules below let only the WireGuard handshake to the server bypass the tunnel. Add these to the client’s client1.conf, replacing SERVER_PUBLIC_IP if you use an IP and not a domain.

# Allow the handshake, then drop everything not via wg
PreUp = iptables -I OUTPUT -d SERVER_PUBLIC_IP -p udp --dport 51820 -j ACCEPT
PreUp = iptables -I OUTPUT ! -o %i -m addrtype ! --dst-type LOCAL -j DROP
PreUp = ip6tables -I OUTPUT ! -o %i -m addrtype ! --dst-type LOCAL -j DROP
PostDown = iptables -D OUTPUT ! -o %i -m addrtype ! --dst-type LOCAL -j DROP
PostDown = ip6tables -D OUTPUT ! -o %i -m addrtype ! --dst-type LOCAL -j DROP
PostDown = iptables -D OUTPUT -d SERVER_PUBLIC_IP -p udp --dport 51820 -j ACCEPT

On Android, you can also enable “Block connections without VPN” in system settings after importing the profile.

9) Test the tunnel

Connect your client and verify that your public IP changes to the server. You should also be able to reach private services across the tunnel.

# On the client
wg
curl -s https://ifconfig.me
dig +short txt ch whoami.cloudflare @1.1.1.1

Troubleshooting tips

If the client does not connect, verify that UDP 51820 is open and forwarded, confirm your external interface name in PostUp/PostDown, and ensure AllowedIPs on the server exactly match each client’s single /32 address. Lower MTU (e.g., 1280) if you observe stalls, especially behind cellular or PPPoE links. If your provider uses CGNAT and you cannot forward UDP, host the server on a VPS with a public IP.

Security and maintenance

Rotate keys periodically, remove unused peers, and keep Ubuntu updated. Use strong DNS resolvers or your own recursive resolver for privacy. For teams, restrict each peer with precise AllowedIPs and consider splitting traffic by adding only the subnets you need. Monitor sudo wg output to audit connected peers and data transferred.

You now have a modern, efficient WireGuard VPN on Ubuntu 24.04 with DNS, mobile QR onboarding, and an optional kill switch. This setup is fast enough for home labs and secure enough for remote teams.

How to Build a Zero‑Config Mesh VPN with Tailscale: Linux, Windows, and Docker (MagicDNS, ACLs, Exit Nodes)

Overview

Tailscale is a modern mesh VPN built on WireGuard that makes secure connectivity across laptops, servers, and containers almost effortless. Instead of managing keys and gateways by hand, you sign in with your identity provider and every device gets a stable, encrypted connection. In this tutorial, you will set up Tailscale on Linux, Windows, and Docker, enable MagicDNS for human‑friendly names, create fine‑grained ACL rules, and configure subnet routers and exit nodes. By the end, you will have a production‑ready, zero‑config VPN that can replace brittle port forwards and site‑to‑site tunnels.

Prerequisites

You need a Tailscale account (Google, Microsoft, GitHub, or SSO), admin rights on the devices, and outbound internet access. Optional but recommended: the ability to change local firewall rules. Tailscale supports Windows 10/11, Windows Server, macOS, Linux (Debian/Ubuntu, RHEL, Fedora, Alpine), and containers (Docker, Kubernetes).

Step 1 — Create the network and enable MagicDNS

Sign up at the Tailscale Admin Console and create a tailnet (your private network). In Settings → DNS, enable MagicDNS to get easy hostnames like web01.tailnet-name.ts.net. Also enable device approval if you want an admin to approve new devices before they can join.

Step 2 — Install on Windows

Download and install the Tailscale client for Windows. Launch it, click Log in, and complete the browser prompt. After the device appears in the Admin Console, give it a readable name (for example, win-laptop). To allow others to route their traffic through this machine later, you can designate it as an exit node in Settings, then in the client select Use exit node when needed.

Step 3 — Install on Linux

On Debian/Ubuntu, install and bring the service up. Example:

curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null; \

curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list; \

sudo apt-get update && sudo apt-get install -y tailscale; \

sudo systemctl enable --now tailscaled; \

sudo tailscale up

Follow the login URL, approve the device, and verify you can ping another device’s Tailscale IP or its MagicDNS name. On RHEL/Fedora, use dnf install tailscale with the corresponding repo instructions from Tailscale’s docs, then run systemctl enable --now tailscaled and tailscale up.

Step 4 — Join Docker containers

For containers, the simplest pattern is a Tailscale sidecar or running Tailscale inside the container with --net=host. Create an auth key in the Admin Console (Keys → Generate auth key). For ephemeral containers, mark it reusable and ephemeral. Then:

docker run --rm --net=host --cap-add NET_ADMIN --cap-add SYS_MODULE \

-e TS_AUTHKEY=tskey-XXXXX -e TS_HOSTNAME=app01 --name ts \

ghcr.io/tailscale/tailscale:stable

Alternatively, keep Tailscale in a sidecar and expose your app container over the Tailscale interface. Using ephemeral keys avoids long‑lived credentials inside images.

Step 5 — Use MagicDNS and stable names

With MagicDNS, you can connect to devices by name instead of IP, for example ssh ubuntu@web01. If a device is multihomed, Tailscale handles routing without your input. If you cannot resolve names, ensure MagicDNS is enabled and your OS DNS cache is clean (flush with ipconfig /flushdns on Windows or systemd-resolve --flush-caches on Linux).

Step 6 — Create Access Control Lists (ACLs)

ACLs define who can reach what. In the Admin Console, open Access controls and edit the JSON. Example to allow the Helpdesk group SSH to Linux servers and RDP to Windows only:

{ "groups": { "group:helpdesk": ["[email protected]","[email protected]"] }, "tagOwners": { "tag:linux": ["group:helpdesk"], "tag:windows": ["group:helpdesk"] }, "acls": [ { "action":"accept", "src":["group:helpdesk"], "dst":["tag:linux:22","tag:windows:3389"] } ] }

Tag devices by starting Tailscale with tags, for example sudo tailscale up --advertise-tags=tag:linux. Use the principle of least privilege and review the policy on every new service.

Step 7 — Advertise a subnet router

To reach an entire LAN behind a Linux box (like a lab or on‑prem server), advertise routes from that machine:

sudo tailscale up --advertise-routes=192.168.10.0/24

Approve the route in the Admin Console. If you prefer the LAN device IPs to be the source (no SNAT), add --snat-subnet-routes=false and ensure your LAN gateway routes replies back via the router.

Step 8 — Offer an exit node for internet egress

An exit node lets clients send all internet traffic through a trusted device; useful on public Wi‑Fi. On the chosen device run:

sudo tailscale up --advertise-exit-node

Enable it in the Admin Console, then on clients open the Tailscale client and select Use exit node. Confirm DNS and split‑tunnel settings match your security policy.

Step 9 — Firewall and auto‑start tips

Tailscale uses outbound UDP on random high ports (WireGuard) and falls back to TCP/443 via DERP relays when direct NAT traversal fails. Allow outbound UDP and HTTPS. On Linux, Tailscale manages its own interface (tailscale0), but you should avoid conflicting rules that drop established/related traffic. Ensure auto‑start with systemctl enable --now tailscaled (Linux) and verify the Windows service is running after reboots.

Troubleshooting

If a device shows offline, verify system time (NTP), restart the service with sudo systemctl restart tailscaled, and check that your identity provider token has not expired. If pings work but names do not, re‑enable MagicDNS and flush DNS caches. If a container cannot join, confirm it has --net=host or appropriate capabilities and that you used a valid auth key. For route issues, ensure routes are approved and that upstream routers have return routes when SNAT is disabled. As a last resort, try tailscale bugreport and review logs at /var/log or the Windows Event Viewer.

Security best practices

Use short‑lived, ephemeral auth keys in CI and containers. Turn on device approval and SSO/MFA. Rely on tags, not users, to grant access in ACLs. Keep systems patched and enable client auto‑updates. Prefer exit nodes you control and monitor. Regularly audit your ACL JSON and remove unused devices from the tailnet.

What you built

You now have a resilient, zero‑config mesh VPN that spans Windows, Linux, and Docker. With MagicDNS, ACLs, subnet routing, and exit nodes, you can securely reach any service without exposing ports to the internet, and you can grow the network in minutes instead of days.

How to Install and Secure WireGuard VPN on Ubuntu 24.04 (IPv6, UFW, and Mobile QR Codes)

Overview

WireGuard is a modern VPN that is fast, secure, and simple to manage. In this step-by-step guide, you will install a WireGuard server on Ubuntu 24.04 LTS, enable IPv4/IPv6 routing, lock it down with UFW firewall, and create a mobile-friendly client using a QR code. This setup is ideal for remote access, secure public Wi‑Fi, and self-hosted lab environments.

Prerequisites

You need an Ubuntu 24.04 server (root or sudo), a public IP or DNS record pointing to your server, and one open UDP port (default: 51820). Update your system and note the name of your Internet-facing interface (e.g., eth0 or ens3).

1) Install WireGuard and tools

Install core packages and utilities used for key generation and QR export.

sudo apt update && sudo apt -y install wireguard qrencode resolvconf

2) Enable IP forwarding (IPv4 and IPv6)

Allow the server to route traffic from VPN clients to the Internet. Create a sysctl drop-in so the setting persists across reboots.

sudo tee /etc/sysctl.d/99-wireguard-routing.conf >/dev/null <<'EOF'
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
EOF
sudo sysctl --system

3) Generate server keys

WireGuard uses public-key cryptography. Generate a private key, derive the public key, and keep the private key secret.

umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey | tee /etc/wireguard/server.pub
SERVER_PRIV=$(cat /etc/wireguard/server.key)

4) Create the server interface configuration

In this example, clients will use the subnets 10.8.0.0/24 (IPv4) and fd86:ea04:1111::/64 (IPv6). Replace eth0 with your real outbound interface. PostUp/PostDown rules enable NAT and forwarding for both stacks.

sudo tee /etc/wireguard/wg0.conf >/dev/null <<'EOF'
[Interface]
Address = 10.8.0.1/24, fd86:ea04:1111::1/64
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
# NAT and forwarding for IPv4/IPv6
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; \
         iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; \
         ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; \
         ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -A FORWARD -o %i -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; \
           iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; \
           ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; \
           ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -D FORWARD -o %i -j ACCEPT
SaveConfig = false
EOF
sudo sed -i "s|SERVER_PRIVATE_KEY|$SERVER_PRIV|" /etc/wireguard/wg0.conf

If your server uses another outbound interface name, replace eth0 in PostUp/PostDown accordingly. If you prefer nftables, you can translate these rules to nft syntax.

5) Open the firewall

Allow UDP 51820 so peers can reach your VPN. If you use UFW, run:

sudo ufw allow 51820/udp
sudo ufw status verbose

6) Start WireGuard and enable on boot

The wg-quick helper reads the configuration and brings up the interface. Enable the service to auto-start on reboot.

sudo systemctl enable --now wg-quick@wg0
sudo wg show

7) Create your first client (peer)

Generate keys for a client, define which subnets to route through the tunnel (0.0.0.0/0 and ::/0 for full-tunnel), and set DNS to prevent leaks. Replace vpn.example.com with your server’s public IP or domain. PersistentKeepalive helps mobile devices behind NATs maintain connectivity.

umask 077
wg genkey | tee ~/alice.key | wg pubkey | tee ~/alice.pub
ALICE_PRIV=$(cat ~/alice.key)
ALICE_PUB=$(cat ~/alice.pub)
SERVER_PUB=$(cat /etc/wireguard/server.pub)
SERVER_ENDPOINT="vpn.example.com:51820"

Add the client as a peer on the server and assign an IP:

sudo tee -a /etc/wireguard/wg0.conf >/dev/null <<EOF
[Peer]
# Alice
PublicKey = $ALICE_PUB
AllowedIPs = 10.8.0.2/32, fd86:ea04:1111::2/128
EOF
sudo systemctl restart wg-quick@wg0
sudo wg show

Build the client configuration file:

cat > ~/alice.conf <<EOF
[Interface]
PrivateKey = $ALICE_PRIV
Address = 10.8.0.2/32, fd86:ea04:1111::2/128
DNS = 1.1.1.1, 2606:4700:4700::1111

[Peer]
PublicKey = $SERVER_PUB
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = $SERVER_ENDPOINT
PersistentKeepalive = 25
EOF

Tip: For privacy, you can run a resolver like Unbound on the server and set DNS = 10.8.0.1, fd86:ea04:1111::1.

8) Import on mobile via QR code

The WireGuard apps for Android and iOS can import a profile from a QR code. Print it in the terminal and scan it with the app.

qrencode -t ansiutf8 < ~/alice.conf

Alternatively, transfer the file securely and import it in the desktop or mobile WireGuard client.

9) Test your connection

Connect the client and verify your public IP changes. You can use curl ifconfig.io or any IP check site. Also test DNS and IPv6.

# On the client after connecting
curl -4 ifconfig.io
curl -6 ifconfig.io
nslookup example.org
ping -c 3 10.8.0.1

Troubleshooting

If the interface fails to start, check for typos in wg0.conf and ensure the outbound interface name is correct. Review logs with: sudo journalctl -u wg-quick@wg0 -e. If clients connect but have no Internet, verify IP forwarding (sysctl), NAT rules (PostUp), and that UDP 51820 is open. For DNS leaks or resolution failures, confirm the DNS entries in the client and that your resolver is reachable through the tunnel.

Security Tips

Use a non-default port if your ISP is restrictive, limit SSH access with UFW and key-based auth, keep the kernel and packages updated, and remove peers you no longer need. Consider enabling automatic security updates: sudo apt install unattended-upgrades.

You now have a fast, dual-stack WireGuard VPN on Ubuntu 24.04 with clean routing, firewall rules, and mobile-friendly onboarding via QR codes.

3.

Deploy a Private WireGuard VPN with Docker Compose (QR Codes for Mobile)

Why this guide

WireGuard is a modern VPN that is fast, secure, and simple to manage. Running it in Docker keeps your host clean, makes upgrades trivial, and allows you to back up your configuration as plain files. In this tutorial, you will deploy a production-ready WireGuard VPN with Docker Compose on an Ubuntu server, generate QR codes for easy mobile onboarding, and enable best-practice settings like IPv6 forwarding and DNS control.

Prerequisites

You need an Ubuntu 22.04/24.04 host (cloud VM or home server), a public DNS name for the server (e.g., vpn.example.com), and permission to forward UDP port 51820 on your router if you are behind NAT. You will also need a non-root user with sudo privileges. Windows or macOS clients can connect too, but we will demonstrate mobile setup using QR codes as it is the quickest way to get started.

Step 1 — Install Docker and Compose Plugin

Update your host, install Docker, and add your user to the docker group so you can run it without sudo.

sudo apt update && sudo apt -y upgrade
sudo apt -y install docker.io docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
# Re-log or run: newgrp docker

Step 2 — Create the project structure

We will store compose files in /srv/wireguard and persist configuration in /srv/wireguard/config. The container will keep keys and peer files under this directory, which makes backups easy.

sudo mkdir -p /srv/wireguard/config
sudo chown -R $USER:$USER /srv/wireguard

Step 3 — Write docker-compose.yml

Create a Compose file that uses the well-maintained LinuxServer.io WireGuard image. Replace vpn.example.com with your DNS name and adjust timezone and peer names to your needs.

nano /srv/wireguard/docker-compose.yml

version: "3.8"
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
     - NET_ADMIN
     - SYS_MODULE
    ports:
     - 51820:51820/udp
    volumes:
     - ./config:/config
     - /lib/modules:/lib/modules:ro
    environment:
     - PUID=1000
     - PGID=1000
     - TZ=Etc/UTC
     - SERVERURL=vpn.example.com
     - SERVERPORT=51820
     - PEERS=phone,laptop
     - PEERDNS=1.1.1.1
     - INTERNAL_SUBNET=10.13.13.0
     - ALLOWEDIPS=0.0.0.0/0,::/0
    sysctls:
     - net.ipv4.conf.all.src_valid_mark=1
     - net.ipv4.ip_forward=1
     - net.ipv6.conf.all.forwarding=1
    restart: unless-stopped

A few notes: PEERS seeds the initial clients; you can add more later. ALLOWEDIPS controls routing. With 0.0.0.0/0,::/0 the client routes all traffic through the VPN (full tunnel). For a split tunnel to only reach the VPN subnet, set 10.13.13.0/24 (and optionally fd00:13:13::/64 if you use IPv6).

Step 4 — Open the firewall and forward the port

If UFW is enabled on the host, allow UDP 51820. Also forward UDP 51820 on your router to the server’s LAN IP. If you use a cloud VM, open the UDP port in your provider’s security group.

sudo ufw allow 51820/udp

Step 5 — Start the stack

Bring the container up and follow logs. On the first start, it creates server keys and peer files under config/.

cd /srv/wireguard
docker compose up -d
docker compose logs -f

Step 6 — Get peer configs and QR codes

The image includes helper scripts. To display a peer config and its QR code, run:

docker exec -it wireguard /app/show-peer phone

Install the WireGuard app on iOS or Android, tap the plus button, choose “Scan from QR code,” and scan the code from your terminal. For Windows/macOS/Linux clients, copy the text config printed by the command above into a file like phone.conf and import it in the WireGuard desktop app.

To add a new peer at any time, use:

docker exec -it wireguard /app/add-peer tablet

Step 7 — Verify the connection

Activate the tunnel on your device. From the server, confirm the handshake:

docker exec wireguard wg show

You should see latest handshake times and transfer counters increase as you pass traffic. From the client, visit https://ifconfig.io to confirm your public IP matches the server and that DNS resolves as expected.

Optional: Tune routing, MTU, and DNS

If you only want to reach resources on your home network and keep general browsing on the local internet, change ALLOWEDIPS in the peer config to the private ranges you care about (for example, 10.13.13.0/24,192.168.1.0/24). For mobile networks with strict NAT, enable a keepalive in the peer config by adding PersistentKeepalive = 25. If you notice slow speeds, set MTU = 1280 in the peer config to avoid fragmentation on cellular carriers.

For ad blocking, set PEERDNS to your Pi-hole or AdGuard Home address reachable through the tunnel, e.g., 10.13.13.2. You can also use privacy resolvers like 1.1.1.1 or 9.9.9.9.

Backups and updates

The critical state lives in /srv/wireguard/config. Back it up regularly with your favorite tool (rsync, Restic, Borg). To upgrade safely, pull the new image and recreate the container; your config remains intact.

cd /srv/wireguard
docker compose pull
docker compose up -d

Troubleshooting

No handshake? Verify the UDP port forward and make sure your DNS record points to the right public IP. On mobile networks behind Carrier Grade NAT, incoming connections may be blocked—host the server on a cloud VM or use a home ISP with a public IP. If the tunnel connects but no traffic flows, confirm IP forwarding is enabled (the Compose file includes sysctls) and that ALLOWEDIPS is correct on both ends. For double NAT routers, enable a full-cone/endpoint-independent NAT if available, or use an alternate UDP port like 51821.

You are done

With Docker Compose and WireGuard, you now have a lightweight, fast VPN that you can maintain in minutes. Add peers with one command, scan a QR code on your phone, and enjoy a private, encrypted tunnel wherever you are. Keep your system updated, back up the config folder, and you will have a reliable VPN for the long run.

WireGuard on Ubuntu 24.04: A Zero‑Trust VPN Setup with Windows and Mobile Clients

Overview

WireGuard is a modern VPN protocol that is fast, secure, and simple to deploy. In this tutorial, you will build a production-ready WireGuard server on Ubuntu 24.04 and connect Windows and mobile clients. You will configure routing, firewall rules, auto-start, and testing. The guide uses clear steps and SEO-friendly terms to help you go from zero to a working zero-trust VPN in minutes.

Prerequisites

You need an Ubuntu 24.04 server (cloud VPS or on-prem) with a public IP, sudo access, and UDP port 51820 open on any external firewall. If the server is behind a home router, forward UDP 51820 to the server’s LAN address. For clients, you need a Windows 10/11 PC and an Android or iOS device.

Step 1: Install WireGuard on Ubuntu 24.04

Update packages and install WireGuard tools:
sudo apt update && sudo apt install -y wireguard qrencode

Create a configuration directory and restrict permissions:
sudo mkdir -p /etc/wireguard && sudo chmod 700 /etc/wireguard

Step 2: Generate keys and base server config

Generate the server keypair:
cd /etc/wireguard
sudo wg genkey | sudo tee server_private.key | sudo wg pubkey | sudo tee server_public.key
sudo chmod 600 server_private.key

Set your VPN subnet and interface variables (eth0 is common on cloud VMs; adjust if yours differs):
export WG_IFACE=wg0
export WG_SUBNET=10.7.0.0/24
export SERVER_ADDR=10.7.0.1/24
export WAN_IFACE=eth0

Create the server configuration file:
sudo bash -c 'cat >/etc/wireguard/wg0.conf' <<EOF
[Interface]
Address = 10.7.0.1/24
ListenPort = 51820
PrivateKey = $(cat /etc/wireguard/server_private.key)
# Accept forwarding and NAT to the Internet
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ${WAN_IFACE} -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ${WAN_IFACE} -j MASQUERADE
EOF'

Step 3: Enable IP forwarding and open the port

Enable IPv4 forwarding persistently:
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

If you use UFW, allow the WireGuard port:
sudo ufw allow 51820/udp

Start and enable the VPN interface:
sudo systemctl enable --now wg-quick@wg0

Check status and listen port:
sudo wg show

Step 4: Add a Windows client

On the server, generate a keypair for your Windows PC (you can also generate on the PC inside the app):
sudo wg genkey | sudo tee win_private.key | sudo wg pubkey | sudo tee win_public.key

Add the Windows peer to the server:
sudo bash -c 'cat >>/etc/wireguard/wg0.conf' <<EOF
[Peer]
PublicKey = $(cat /etc/wireguard/win_public.key)
AllowedIPs = 10.7.0.2/32
EOF'

Then restart the interface:
sudo systemctl restart wg-quick@wg0

On Windows, install the WireGuard app from the official site or Microsoft Store. Create a new tunnel with this configuration (replace placeholders):
[Interface]
PrivateKey = <win_private_key>
Address = 10.7.0.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = <server_public_key>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <server_public_ip>:51820
PersistentKeepalive = 25

Copy values:
<server_public_key> is the content of /etc/wireguard/server_public.key.
<win_private_key> is the content of win_private.key if you generated it on the server, otherwise use the private key generated by the Windows app.
AllowedIPs set to 0.0.0.0/0, ::/0 routes all traffic through the VPN (full tunnel). For split tunnel, use 10.7.0.0/24 only.

Step 5: Add a mobile client (Android/iOS)

On the phone, install the WireGuard app. Creating keys on the device is the most secure method: add a new tunnel, let the app generate keys, and copy the public key.

Add the mobile peer on the server (replace with the phone’s public key and desired IP):
sudo bash -c 'cat >>/etc/wireguard/wg0.conf' <<EOF
[Peer]
PublicKey = <mobile_public_key>
AllowedIPs = 10.7.0.3/32
EOF'
sudo systemctl restart wg-quick@wg0

On the mobile app, create or import a config like this (adjust placeholders):
[Interface]
PrivateKey = <mobile_private_key>
Address = 10.7.0.3/32
DNS = 1.1.1.1

[Peer]
PublicKey = <server_public_key>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <server_public_ip>:51820
PersistentKeepalive = 25

Optional: if you prefer generating the mobile config on the server and scanning a QR code, create a file (for example /etc/wireguard/mobile1.conf) with the contents above and show a QR in the terminal:
sudo qrencode -t ansiutf8 < /etc/wireguard/mobile1.conf

Step 6: Auto-start, verify, and test

Ensure the interface starts on boot:
sudo systemctl enable wg-quick@wg0

Verify that peers handshaked and received IPs:
sudo wg show

Test connectivity from a client: open a browser and check your public IP (it should show the server’s IP if using a full tunnel). Also, ping the server’s VPN IP:
ping 10.7.0.1

Troubleshooting quick wins

No handshake? Confirm UDP 51820 is open and reachable. Use:
sudo ss -ulpn | grep 51820 on the server to see if it is listening, and sudo tcpdump -ni any udp port 51820 to check if packets arrive.

Wrong interface name? Replace eth0 with your actual outbound interface (check with ip route get 1.1.1.1). Update PostUp/PostDown accordingly and restart the service.

Double NAT issues? Set PersistentKeepalive = 25 on clients and ensure router port forwarding is correct.

Can’t access the Internet from the VPN? Confirm IPv4 forwarding is enabled and that NAT rules exist (see iptables -t nat -S). Also verify AllowedIPs values on both sides.

Security and best practices

Rotate keys periodically and remove stale peers from wg0.conf. Keep Ubuntu and WireGuard updated. Use strong SSH hygiene on the server and restrict management access by IP if possible. For compliance-driven environments, log changes to /etc/wireguard with version control (without committing private keys).

You now have a fast, modern WireGuard VPN on Ubuntu 24.04 with Windows and mobile clients. This layout is minimal yet production-ready and can scale by adding more peers with unique /32 addresses inside the same VPN subnet.

3.

How to Build a Zero-Config Mesh VPN with Tailscale for Secure Remote Access

Overview

Tired of port forwarding, dynamic DNS, and brittle VPN configs? Tailscale gives you a zero-config mesh VPN built on WireGuard, letting your devices talk to each other securely from anywhere. In this step-by-step guide, you will install Tailscale on Linux, Windows, and macOS, enable MagicDNS, set up an exit node, publish LAN subnets, and lock everything down with access controls. By the end, you will have a private, encrypted network for your home lab or remote team that takes minutes to deploy and scales without hassle.

Prerequisites

You need a Tailscale account (Google, Microsoft, GitHub, or email sign-in), admin access to your devices, and a stable internet connection. For subnet routing and exit nodes, a Linux or always-on device is recommended. Enable multi-factor authentication in your identity provider for best security.

Step 1: Create Your Tailnet

Go to the Tailscale website and sign in to create your tailnet. This is your private network. Open the Admin Console and confirm your tailnet name. Under Settings, enable device approvals if you want manual approval before new devices join. This is useful for production and shared environments.

Step 2: Install Tailscale

Linux (Debian/Ubuntu)
Run:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
When prompted, sign in to link the device. If your distro uses a service, ensure tailscaled is running.

Linux (Fedora/RHEL derivatives)
Install and start:
sudo dnf install tailscale -y
sudo systemctl enable --now tailscaled
sudo tailscale up

Windows
Download the Windows client from Tailscale, install it, and sign in. The client will assign a 100.x Tailscale IP and show your hostname in the Admin Console.

macOS
Install the app from the Mac App Store or from Tailscale’s website. Sign in to connect the Mac to your tailnet.

iOS/Android
Install the mobile app and sign in. You can toggle the VPN on/off and optionally route all traffic through an exit node.

Step 3: Turn On MagicDNS (Human-Friendly Names)

In the Admin Console, open Settings → DNS and enable MagicDNS. This lets you reach devices by name, for example builder.tailnet-name.ts.net, instead of by 100.x IPs. Keep “Override local DNS” enabled on clients so name resolution just works across platforms.

Step 4: Enable Tailscale SSH (Passwordless, Keyless)

In Settings → Tailscale SSH, enable it for your tailnet. On servers, run:
sudo tailscale up --ssh
You can now SSH between devices using identity-based auth, e.g.:
ssh ubuntu@server-name
Access is controlled by the tailnet policy (ACLs) rather than managing per-host SSH keys.

Step 5: Use an Exit Node (Full-Tunnel Internet)

An exit node routes all internet traffic from a device through a trusted peer (great for coffee shops and travel). On the machine that will be the exit node, run:
sudo tailscale up --advertise-exit-node
In the Admin Console, approve the exit node. On the client, open the Tailscale app and choose “Use exit node” → select your device. Optionally enable “Allow LAN access” to still reach your local network while tunneling the internet.

Step 6: Publish Your LAN with a Subnet Router

A subnet router lets remote devices reach a private LAN (e.g., 192.168.1.0/24) through Tailscale. On a Linux host connected to that LAN, enable IP forwarding:
sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w net.ipv6.conf.all.forwarding=1
Persist these settings in /etc/sysctl.d/99-tailscale.conf. Then advertise routes:
sudo tailscale up --advertise-routes=192.168.1.0/24
In the Admin Console → Machines, approve the advertised routes. Clients can now access printers, NAS devices, and servers on that LAN using IP or hostnames (with your DNS). If needed, add --snat=false to preserve client IPs for upstream firewall logs.

Step 7: Lock It Down with ACLs and Tags

Open the Admin Console → Access Controls and edit the policy. Use groups and tags to define who can reach what. Example: allow helpdesk to RDP to Windows servers, and engineers to SSH into Linux hosts. A minimal snippet could look like:
{ "groups": { "group:helpdesk": ["[email protected]"] }, "tagOwners": { "tag:server": ["group:helpdesk", "group:eng"] }, "acls": [ { "action": "accept", "src": ["group:helpdesk"], "dst": ["tag:server:3389"] }, { "action": "accept", "src": ["group:eng"], "dst": ["tag:server:22"] } ] }
Apply tags on devices by running:
sudo tailscale up --advertise-tags=tag:server
Only tagged and authorized devices will accept those connections.

Step 8: Headless and Auto-Join with Auth Keys

For servers and containers, create a reusable or short-lived auth key in the Admin Console → Keys. On the device, run:
sudo tailscale up --authkey=tskey-abcdef --hostname=ci-runner-01 --advertise-tags=tag:server
Use ephemeral keys for throwaway CI agents, and rotate long-lived keys on a schedule. You can also inject TS_AUTHKEY as an environment variable in Docker or systemd units.

Step 9: Troubleshooting Essentials

If a device looks offline, first check the local service:
sudo systemctl status tailscaled (Linux). Then test reachability:
tailscale status
tailscale ping device-name
tailscale netcheck
Ensure outbound UDP 41641 is open; Tailscale falls back to relays (DERP) if direct NAT traversal fails. On Linux firewalls, allow UDP/41641 and established/related traffic. If routes are not working, confirm “Accept routes” is enabled and IP forwarding is on. For deep diagnostics, run tailscale bugreport and review logs in the Admin Console.

Security Best Practices

Require SSO and MFA for all users. Enable device approval and machine key expiry. Use groups and tags to enforce least privilege in ACLs. Restrict exit node usage to trusted admins. Regularly prune unused devices, rotate auth keys, and audit connections in the logs. Avoid exposing services publicly; instead, use MagicDNS, Tailscale SSH, or consider Tailscale Funnel selectively with HTTPS for public endpoints.

What You Can Do Next

With your mesh VPN live, map drives to a NAS over the tailnet, RDP into Windows servers from anywhere, tunnel VS Code SSH to a remote lab, or back up endpoints securely to a central repository. Tailscale scales from a weekend project to a production-ready fabric without the usual VPN pain. Most changes are policy-driven, so you can iterate quickly and keep operations clean.

Popular Posts

Install Ollama and Open WebUI on Ubuntu 24.04 with NVIDIA GPU Acceleration (Step-by-Step)

Install Ollama + Open WebUI on Ubuntu 24.04 with NVIDIA GPU Acceleration (Step-by-Step)

Install a Local AI Chatbot on Ubuntu 24.04 with Ollama and Open WebUI (Step-by-Step)

Trending Now

Debian Adoption at CERN Signals Strong Momentum for Enterprise Linux

By the end of this article readers will understand the implications of CERN’s migration of 2,200 control systems to Debian 13, the performance enhancements in Firefox 155, and recent developments across several Linux distributions that affect system administration and user experience. Debian 13 Deployment at CERN: Scale and Significance The European Organization for Nuclear Research (CERN) has announced the migration of 2,200 of its control systems to Debian 13. This move represents one of the largest coordinated deployments of a Debian release in a scientific research environment. Control systems at CERN are responsible for monitoring and managing critical hardware, from accelerator components to detector subsystems. Their reliability hinges on a stable operating system with long‑term support, predictable update cycles, and a robust package ecosystem. Debian’s reputation for stability and its extensive testing process make it a natural fit for such mission‑critical workloads. Debia...