Open-source project
wg-easy/wg-easy avatar
wg-easy/wg-easy

WireGuard Easy: a Web UI and Docker image for managing WireGuard clients

The easiest way to run WireGuard VPN + Web-based Admin UI.

27,008 stars2,592 forksTypeScriptAGPL-3.0

At a glance

What is it?
WireGuard Easy packages the WireGuard daemon with a browser-based admin UI in a single container. It suits small self-hosted setups that want peer management without hand-editing config files, and it inherits the operational weight of a VPN server.
Who is it for?
wg-easy fits a self-hoster or small team that wants WireGuard peer management through a browser and is comfortable running a container with NET_ADMIN, SYS_MODULE and a mounted /lib/modules. It is the wrong tool if you cannot open UDP 51820 to the host, if you need an audited enterprise VPN with vendor support, or if you want a mesh overlay that traverses NAT without a public endpoint.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What WireGuard Easy actually removes from the setup

Plain WireGuard is a kernel module and a set of tools. Adding a peer means editing a config file, running wg and wg-quick, generating a key pair, allocating an address inside the tunnel subnet, and reloading the interface. WireGuard Easy keeps the same daemon but moves peer management into a web UI. The README lists the operations it exposes: list, create, edit, delete, enable and disable clients, show a client QR code, download a client configuration file, and view connection statistics with Tx/Rx charts per connected client.

The audience is narrow and specific. This is for someone who runs a Linux host, wants remote access to a home or small office network, and would rather click a button than maintain a peer table by hand. It is not a managed service and it does not abstract away the network. You still own the host, the firewall, the port forward and the tunnel subnet. What you stop doing is hand-writing peer blocks and regenerating QR codes.

How the container is put together

The repository ships a Dockerfile and a docker-compose.yml, and the compose file is the clearest statement of the architecture. The service uses the image ghcr.io/wg-easy/wg-easy:15, joins a bridge network named wg with the fixed addresses 10.42.42.42 and fdcc:ad94:bacf:61a3::2a, and publishes two ports: 51820/udp for WireGuard traffic and 51821/tcp for the web UI.

Two volumes carry state and kernel access. etc_wireguard is mounted at /etc/wireguard and holds the server configuration and peer data. /lib/modules is mounted read-only so the container can load kernel modules from the host. The container is granted NET_ADMIN and SYS_MODULE capabilities, with NET_RAW commented out and marked as needed for Podman. Five sysctls are set at startup, including net.ipv4.ip_forward=1 and net.ipv6.conf.all.forwarding=1.

That combination is why the compose file matters more than the README prose. A container that loads modules, changes forwarding and manipulates interfaces is effectively a privileged network appliance, and the deployment reflects it. The Dockerfile builds the UI with pnpm in a Node alpine stage, then compiles amneziawg-tools and amneziawg-go from pinned branches, and copies the built output into a final image that also carries a healthcheck running wg show.

Installing wg-easy with Docker Compose

The README's quick start assumes Docker is already present and points at the project documentation site for the detailed walkthrough. If Docker is missing, the README gives a single install command to run as root, after which you log in again.

bash
curl -sSL https://get.docker.com | sh
exit

The compose file in the repository is the starting point. It defines the etc_wireguard volume, the wg bridge network with both an IPv4 and an IPv6 subnet, and the two published ports. The environment block is commented out, and the optional variables listed there are PORT, HOST and INSECURE.

yaml
services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy:15
    container_name: wg-easy
    ports:
      - "51820:51820/udp"
      - "51821:51821/tcp"
    volumes:
      - etc_wireguard:/etc/wireguard
      - /lib/modules:/lib/modules:ro
    cap_add:
      - NET_ADMIN
      - SYS_MODULE

After the container starts, the web UI answers on TCP 51821. The README treats the reverse proxy as optional but links a separate reverse-proxyless guide for people who skip it, which is a fair signal that exposing the UI directly is a decision the project expects you to make deliberately rather than by default.

The first real task is creating a client in the UI, then using the QR code or the downloaded configuration file on the device. That is the whole loop: create, scan, connect, and watch the Tx/Rx chart to confirm traffic is flowing.

Features that change how you operate it

Several listed features affect day-to-day operation more than the peer list does. One Time Links and Client Expiration mean a peer can be handed out temporarily and then stop working, which is useful for contractors or a device you do not fully trust. 2FA and OIDC support, with Google, GitHub, Authelia and Authentik named as examples, move authentication away from a single shared password. Per-client firewall filtering is available but the README states it requires iptables, so it is not free on every host. Prometheus metrics support means connection data can be scraped instead of only viewed in the browser.

IPv6 and CIDR support are listed, and the compose file enables IPv6 on the bridge network with an explicit subnet. If you do not want IPv6 in the tunnel, that is a configuration change on your side, not something the default compose file does for you. Multilanguage support and automatic light and dark mode are cosmetic but reduce friction for mixed teams.

Where WireGuard Easy is the wrong choice

The container needs NET_ADMIN and SYS_MODULE, a read-only mount of /lib/modules, and several sysctls. On a host where you cannot grant those, or on a platform that does not expose kernel modules to containers, this will not run. The README's own compose file is the evidence: this is not a rootless, unprivileged workload.

Port 51820/udp must be reachable from the clients. Behind carrier-grade NAT, a restrictive corporate firewall, or a network that blocks inbound UDP, a self-hosted WireGuard endpoint simply does not work, and no amount of UI polish changes that. If you need connectivity between devices that are all behind NAT with no public endpoint, a mesh overlay is the right category and this is not it.

There is also a scaling ceiling. This is a single container managing one WireGuard interface on one host. Nothing in the README describes clustering, high availability or multi-node coordination. For a handful of peers it is fine. For an organisation that needs redundancy and an audited access trail, the missing pieces are the point.

Finally, the README points to a separate migration guide for moving from the old version to the new one. Version transitions here are not guaranteed to be drop-in, so pinning the image tag, as the compose file does with :15, is the safer habit.

wg-easy compared with Tailscale and with plain WireGuard

Against plain WireGuard, the difference is where the state lives. Plain WireGuard keeps peers in text files that you edit with any tool and that you can diff in version control. WireGuard Easy keeps that state behind a web application and a database, and exposes it through a UI. You trade file-level transparency for a management interface. If your workflow is configuration-as-code, the UI is a step backwards.

Against Tailscale, the difference is architectural. Tailscale is a coordination service: devices authenticate to a control plane and the overlay handles address assignment and NAT traversal, so you generally do not need a public endpoint. WireGuard Easy is a self-hosted endpoint you must expose on a public IP and port. That means you keep full control of the keys and traffic, and you also keep the responsibility for uptime, firewall rules and certificates. The related searches show people comparing the two directly, and the honest summary is that they solve overlapping problems with opposite assumptions about who runs the coordination layer.

Licence, maintenance and upgrade cost

The project is licensed under AGPL-3.0-only, per the README and the LICENSE file. That is a strong copyleft licence with a network clause: if you modify the software and let users interact with it over a network, the AGPL's source-availability obligations are triggered. Running the unmodified container for your own access is a different situation from building a modified version into a product you host for others. This is not legal advice, and anyone in the second category should read the licence text rather than a summary.

The repository is not archived, and the last push was on 2026-09-18, three days before this writing, so this is a project under current development. The most recent release in the provided list is v15.4.0 from 2026-08-14, preceded by two betas in the same cycle. That cadence has a practical cost: the :15 image tag in the compose file is a moving target, and the existence of a dedicated migration guide implies that major-version upgrades need reading, not just pulling. Budget time for that, and keep the etc_wireguard volume in whatever backup routine covers your other stateful services.

Editorial conclusion

wg-easy fits a self-hoster or small team that wants WireGuard peer management through a browser and is comfortable running a container with NET_ADMIN, SYS_MODULE and a mounted /lib/modules. It is the wrong tool if you cannot open UDP 51820 to the host, if you need an audited enterprise VPN with vendor support, or if you want a mesh overlay that traverses NAT without a public endpoint. Before adopting it, read the basic installation and reverse-proxyless pages on the project documentation site, confirm your host kernel exposes the WireGuard module, and decide where the etc_wireguard volume will be backed up, because that volume is the entire server state.

Frequently asked questions

What is wg-easy?

It is WireGuard plus a web-based admin UI, distributed mainly as a Docker image. The README describes it as the easiest way to install and manage WireGuard on any Linux host, and lists client creation, QR codes, configuration downloads and connection statistics as its features.

How do I install wg-easy with Docker?

Install Docker if it is missing, then run the container from the repository's docker-compose.yml, which uses the image ghcr.io/wg-easy/wg-easy:15 and publishes 51820/udp and 51821/tcp. The README recommends Docker Compose and links a separate page for the docker run command.

How do I access the wg-easy web UI?

The compose file maps container port 51821 to the host on TCP, so the UI is reachable there once the container is running. The README says setting up a reverse proxy to reach it securely from the internet is optional but links a separate guide for deployments without one.

Is wg-easy secure?

The README lists 2FA and OIDC support, with Google, GitHub, Authelia and Authentik as examples, which lets you avoid relying on a single shared password. The compose file also grants the container NET_ADMIN and SYS_MODULE and mounts /lib/modules read-only, so the host-level exposure is real and the README points to a reverse-proxyless guide if you skip the proxy.

How do I update wg-easy?

The README does not document an update procedure in the text provided. It does link a migration guide for moving from the old version to the new one, which suggests major-version upgrades should be read through rather than applied blindly.

Official sources

  1. License: AGPL-3.0
  2. Project website
  3. README
  4. Releases
  5. wg-easy/wg-easy on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wg-easy-wg-easy.svg)](https://hysenlabs.com/projects/wg-easy-wg-easy)