> ## Documentation Index
> Fetch the complete documentation index at: https://help.freakhosting.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Set Up wg-easy (WireGuard VPN with a Web UI) in Docker

> Set up wg-easy with Docker: run ghcr.io/wg-easy/wg-easy:15, open UDP 51820, put the web UI behind HTTPS, create the admin and add WireGuard clients by QR code.

To set up wg-easy, download the official `docker-compose.yml` into `/etc/docker/containers/wg-easy`, change the web UI port to `127.0.0.1:51821`, and start it with `sudo docker compose up -d`. Allow UDP port `51820`, serve the web UI over HTTPS with Nginx, then use the setup wizard to create the admin and your first WireGuard client.

| Difficulty | Time | Works on | Needs |
| - | - | - | - |
| Intermediate | 20 minutes | Ubuntu 22.04 / 24.04, Debian 12 / 13, AlmaLinux / Rocky 9 / 10 (x86\_64 or arm64) | [Docker](https://help.freakhosting.com/portals/other/how-to-install-docker.md), a domain, UDP 51820 open |

## What is wg-easy?

wg-easy runs a WireGuard VPN server and a web interface in one container. WireGuard is a fast, modern VPN protocol. In the web UI you create a client per device, then scan its QR code in the WireGuard app or download its configuration file. To build WireGuard by hand instead, see [set up a WireGuard VPN server](https://help.freakhosting.com/portals/other/how-to-set-up-a-wireguard-vpn-server.md).

## Before you start

* [Install Docker](https://help.freakhosting.com/portals/other/how-to-install-docker.md) and [Nginx](https://help.freakhosting.com/portals/other/how-to-install-nginx.md). The commands use `sudo`; leave it out if you are `root`.
* Point `vpn.example.com` at your server. See [point a domain to your server](https://help.freakhosting.com/portals/other/how-to-point-a-domain-to-your-server.md).
* Use only an x86\_64 or arm64 server. wg-easy 15 does not support armv6 or armv7.
* Use a VPN in line with the law and your provider's terms.

## What changed in wg-easy 15?

Version 15 is a complete rewrite. If you follow an older tutorial, these differences matter:

| | wg-easy 14 and older | wg-easy 15 |
| - | - | - |
| Image tag | `latest` | `15` (the `latest` tag still points to 14; avoid it) |
| Settings | Environment variables such as `WG_HOST` and `PASSWORD_HASH` | Setup wizard and **Admin Panel** in the web UI |
| Web UI over plain HTTP | Allowed | Needs `INSECURE=true`; use HTTPS instead |
| Remaining variables | Many | Optional only: `PORT`, `HOST`, `INSECURE`, `DISABLE_IPV6`, `TRUSTED_PROXIES` and a few more |

To move from 14, see [How do I migrate from wg-easy 14?](#how-do-i-migrate-from-wg-easy-14) below.

## How to install wg-easy with Docker Compose

**1. Download the official compose file**

```bash theme={null}
sudo mkdir -p /etc/docker/containers/wg-easy
sudo curl -o /etc/docker/containers/wg-easy/docker-compose.yml https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml
```

**2. Keep the web UI private**

Open the file with `sudo nano /etc/docker/containers/wg-easy/docker-compose.yml` and change the web UI port line so only Nginx on this server can reach it. The `ports` section then reads:

```yaml theme={null}
    ports:
      - "51820:51820/udp"
      - "127.0.0.1:51821:51821/tcp"
```

Leave the rest as it is: the `ghcr.io/wg-easy/wg-easy:15` image, the `etc_wireguard` volume, the `NET_ADMIN` and `SYS_MODULE` capabilities, the forwarding `sysctls` and the `wg` network.

**3. Start wg-easy**

```bash theme={null}
cd /etc/docker/containers/wg-easy
sudo docker compose up -d
```

**4. Allow the VPN port**

WireGuard uses **UDP 51820**. Docker publishes it for you, but if a firewall sits in front of the server, allow UDP 51820 there. With `ufw`:

```bash theme={null}
sudo ufw allow 51820/udp
```

> [!WARNING]
>
> Use `sudo docker compose up -d` and `sudo docker compose down` to start and stop wg-easy, not `docker compose start` or `stop`. The wg-easy docs warn that `start`/`stop` leave an inconsistent state that causes problems on the next start.

## How to put the wg-easy web UI behind HTTPS

**1. Create the Nginx site**

Create `/etc/nginx/sites-available/vpn.example.com` (Ubuntu / Debian) or `/etc/nginx/conf.d/vpn.example.com.conf` (AlmaLinux / Rocky):

```nginx theme={null}
server {
    listen 80;
    listen [::]:80;
    server_name vpn.example.com;

    location / {
        proxy_pass http://127.0.0.1:51821;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

**2. Enable, test and get a certificate**

```bash theme={null}
sudo ln -s /etc/nginx/sites-available/vpn.example.com /etc/nginx/sites-enabled/   # Ubuntu / Debian only
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d vpn.example.com
```

On AlmaLinux / Rocky, run `sudo setsebool -P httpd_can_network_connect 1` before testing.

Keep `INSECURE` at its default (`false`). The session cookie is then only sent over HTTPS. wg-easy has no built-in rate limiting, so the docs suggest limiting the login paths in your proxy or with a tool such as [CrowdSec](https://help.freakhosting.com/portals/other/how-to-install-crowdsec-on-linux.md).

## How to complete the setup wizard

**1. Create the administrator**

Open `https://vpn.example.com` and select **Continue**. Enter a username (at least 2 characters) and a password (at least 12 characters), then select **Create Account**.

**2. Choose a new configuration**

When asked about an existing setup, choose **No** for a fresh install.

**3. Set the host and port**

Set **Host** to `vpn.example.com` (or your server IP, for example `203.0.113.10`) and **Port** to `51820`. Clients connect to this address. Select **Continue**.

**4. Add a client**

Select **New Client**, enter a name such as `alex-phone`, then select **Create Client**. Scan the QR code with the WireGuard app, or download the configuration file for a computer.

## How to check it worked

```bash theme={null}
sudo docker compose ps
sudo docker compose logs --tail 20
```

The `wg-easy` container shows `Up`. Connect from a device, then check that your public IP is now the server's IP. In the web UI, the client shows as **Online** after its first handshake.

## How to back up wg-easy

Everything wg-easy stores, including client keys and settings, is in the `etc_wireguard` volume, mounted at `/etc/wireguard`. Stop the container briefly and archive the volume as shown in [back up Docker volumes](https://help.freakhosting.com/portals/other/how-to-back-up-docker-volumes.md). The volume name is the project folder name plus `_etc_wireguard`; list it with `sudo docker volume ls`.

## How to update wg-easy

The `15` tag gets every 15.x release without breaking changes:

```bash theme={null}
cd /etc/docker/containers/wg-easy
sudo docker compose pull
sudo docker compose up -d
```

A future major version needs a deliberate tag change; read its release notes first.

## Frequently asked questions

### How do I migrate from wg-easy 14?

In the old web UI, click **Backup** to download `wg0.json` and note your old environment variables. Stop the old container with `docker compose down`, install version 15 as above, and in the setup wizard choose **Yes** for an existing configuration and upload `wg0.json`. Re-enter old settings in the **Admin Panel**.

### What does "Cannot find device wg0" mean?

The WireGuard kernel module isn't loaded. Run `sudo modprobe wireguard`, and add `wireguard` to `/etc/modules` to load it at boot.

### Can I change the VPN port?

Yes. Change the UDP port mapping in `docker-compose.yml`, the port under **Admin Panel > Config**, and your firewall rule so all three match. Then send updated configurations to existing clients.

### Can I reach the web UI without a domain?

The wg-easy docs call plain HTTP insecure. If you must, set `INSECURE=true` and only expose the UI to a network you trust, never to the internet.

## Related guides

> [card] [VPS and dedicated server guides](https://help.freakhosting.com/portals/other/vps-and-dedicated-server-guides.md)
>
> Every guide in this section.

> [card] [Set up a WireGuard VPN server](https://help.freakhosting.com/portals/other/how-to-set-up-a-wireguard-vpn-server.md)
>
> WireGuard without a web UI.

> [card] [Set up a firewall with UFW](https://help.freakhosting.com/portals/other/how-to-set-up-a-firewall-with-ufw.md)
>
> Allow UDP 51820.

> [card] [Nginx Proxy Manager](https://help.freakhosting.com/portals/other/how-to-set-up-nginx-proxy-manager.md)
>
> HTTPS for containers from a web UI.

> [card] [Update Docker containers](https://help.freakhosting.com/portals/other/how-to-update-docker-containers.md)
>
> Pull new images safely.

***

> [!NOTE]
>
> **Checked against the official [wg-easy README and documentation](https://wg-easy.github.io/wg-easy/latest/)** on 4 November 2026 (image `ghcr.io/wg-easy/wg-easy:15`); `docker-compose.yml` validated with `docker compose config` and the Nginx configuration syntax-tested on Ubuntu 24.04 LTS. Menu names can change between wg-easy releases.

> [!NOTE]
>
> ### Need Extra Help?
>
> If you encounter any issues, our support team is ready to assist:
>
> * **Live Chat:** Quick assistance via our website.
> * **Support Ticket:** [Open a Ticket](https://freakhosting.com/clientarea/submitticket.php)
> * **Discord:** [Join our Community](https://discord.gg/freakhosting)
> * **Email:** [support@freakhosting.com](mailto:support@freakhosting.com)

> [!TIP]
>
> ### Save on Your Hosting
>
> Ready to upgrade your hosting? Use code **KB20** at checkout for **20% off** your first order!

***

**Last Updated:** November 2026


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.