--- navigation: true title: Wireguard main: fluid: false --- :ellipsis{left=0px width=40rem top=10rem blur=140px} # Wireguard ::alert{type="info"} 🎯 __Goals:__ - Install Wireguard - Configure clients - Access the secure network :: ## Introduction --- Using a VPN allows remote access to a server’s local resources without exposing them to the internet. It’s a clean and secure way to access services like SSH without exposing the port publicly. With a VPN, you can securely connect to your network from anywhere and make devices on different networks communicate. Here we will use [Wireguard](https://www.wireguard.com/), a secure and high-performance VPN server, using containers: - [wg-easy](https://github.com/wg-easy/wg-easy) as the server, providing a very simple web UI to manage connections and download config files (including QR codes for phones) - [Wireguard](https://docs.linuxserver.io/images/docker-wireguard/?h=wireguard) as the client for Linux systems Clients are also available for Windows, macOS, iOS, and Android. The concept: - On the internet, anyone can reach any internet box and thus any exposed server. - Your server is on your local network. It is accessible only locally unless services are explicitly exposed (as we did with Dockge). To access non-exposed resources, you must be on the same local network. - We want to securely access these unexposed services (like SSH) from anywhere. - We also want to connect services between servers, like linking two Dockge instances securely. To achieve this, we’ll create a **Virtual Private Network** (VPN), i.e., a secure tunnel that only connected machines can use. They’ll appear to be on the same private network. Additionally, you can add your phone, laptop, or other devices to the VPN and securely access your server resources wherever you are. ![picture](/img/serveex/vpn.svg) In this diagram, machine 1 is part of two networks: - Its local network (devices behind the same router, e.g. `192.168.x.x` – machines 1 and 2) - The VPN network (VPN devices with a second IP, e.g. `10.8.x.x` – machines 1 and 4) You *can* allow VPN clients to share access to their local networks, but we won’t do that here for security and subnet conflict reasons (e.g., if two remote machines use the same local IP like `192.168.1.1`). So only VPN-connected devices can communicate with each other on the VPN, not with other local devices outside the VPN. ## Server Setup --- ::alert{type="info"} πŸ“‹ **Pre-flight Checklist:** - Ensure port `51820 UDP` is free on your server and correctly forwarded from your router (`51820 UDP -> Server`). - Ensure port `51821 TCP` is free for the web UI. :: ::alert{type="warning"} :::list{type="warning"} - __Warning__: If your IP is not static, use a Dynamic DNS service ([DynDNS](https://en.wikipedia.org/wiki/Dynamic_DNS)). If your ISP uses [CGNAT](https://en.wikipedia.org/wiki/Carrier-grade_NAT), you’ll need to use an external VPS and connect your local server as a client. ::: :: ### Folder Structure ```sh root └── docker └── wg-easy β”œβ”€β”€ config β”‚ └── etc_wireguard β”œβ”€β”€ compose.yaml └── .env ``` Open Dockge, click **Compose**, and name the stack `wg_easy`. Copy the following configuration: ```yaml --- services: wg-easy: environment: - INSECURE=true image: ghcr.io/wg-easy/wg-easy:15 container_name: wg-easy networks: wg: ipv4_address: 10.42.42.42 ipv6_address: fdcc:ad94:bacf:61a3::2a volumes: - ./etc_wireguard:/etc/wireguard - /lib/modules:/lib/modules:ro ports: - "51820:51820/udp" - "51821:51821/tcp" restart: unless-stopped cap_add: - NET_ADMIN - SYS_MODULE sysctls: - net.ipv4.ip_forward=1 - net.ipv4.conf.all.src_valid_mark=1 - net.ipv6.conf.all.disable_ipv6=0 - net.ipv6.conf.all.forwarding=1 - net.ipv6.conf.default.forwarding=1 networks: wg: driver: bridge enable_ipv6: true ipam: driver: default config: - subnet: 10.42.42.0/24 - subnet: fdcc:ad94:bacf:61a3::/64 ``` ::alert{type="success"} ✨ **Tip:** - You can customize WireGuard and web UI ports. - Add a Watchtower label for automatic updates: ```yaml services: wg-easy: # ... labels: - com.centurylinklabs.watchtower.enable=true ``` :: Deploy the stack and access the local web UI at `http://server-ip:51821`. ::alert{type="danger"} :::list{type="danger"} - If the deployment fails, check your firewall rules. ::: :: Once connected, follow the web UI instructions to: - Create your admin account and password. - Set the host field (use your public IP or domain name). Then go to *Administrator β†’ Admin Panel β†’ Config*: - Change `Allowed IPs` from `0.0.0.0/24` to `10.8.0.0/24` for **split tunneling**. - Remove IPv6 (it often causes unnecessary issues). ### Retrieve Configuration Files To configure clients: 1. Access the web UI: `http://server-ip:51821` 2. Create a new client 3. Edit the client and add `10.8.0.0/24` to `Server Allowed IPs` 4. (Optional) Set `Persistent Keep Alive` to `25` if it’s a permanently connected client 5. Save, download, and rename the file to `wg0.conf` (or `wg1.conf`, etc.) ## Client Server Setup --- ::alert{type="info"} :::list{type="info"} - We assume the client server runs Linux with Docker installed. ::: :: ### Folder Structure ```sh root └── docker └── wireguard └── config β”‚ └── wg_confs └── compose.yaml ``` Create the folder: ```sh sudo mkdir -p /docker/wireguard/config/wg_confs ``` ::alert{type="success"} ✨ **Tip:** You can use [File Browser](/serveex/files/file-browser) instead of the terminal to edit and upload files. :: Create the `wg0.conf` file: ```sh sudo vi /docker/wireguard/config/wg_confs/wg0.conf ``` Enter insert mode (`i`), paste the downloaded configuration, then save (`Esc` β†’ `:x`). ::alert{type="success"} ✨ **Alternative method:** Transfer the file via SFTP and move it: ```sh sudo cp ~/wg0.conf /docker/wireguard/config/wg_confs ``` :: Create the `compose.yaml` file in `/docker/wireguard`: ```yaml services: wireguard: image: lscr.io/linuxserver/wireguard:latest container_name: wireguard network_mode: host cap_add: - NET_ADMIN - SYS_MODULE environment: - TZ=Europe/Paris volumes: - /docker/wireguard/config:/config - /lib/modules:/lib/modules restart: unless-stopped ``` Start the container: ```sh cd /docker/wireguard sudo docker compose up -d ``` ::alert{type="info"} :::list{type="info"} - Repeat this setup for each client. ::: :: ## Other Devices --- - **Mobile:** Install WireGuard and scan the QR code via the web UI (`http://server-ip:51821`) - **Desktop:** Install the WireGuard client and import the downloaded config file. ::alert{type="warning"} :::list{type="warning"} - **Note:** If the client machine is on the same local network as the server, edit the `wg0.conf` file to use the local server IP: `Endpoint = server-local-ip:51820` ::: :: And here’s the final setup overview: ![picture](/img/serveex/wireguard.svg)