Deployment guide

wg-easy

Videos

Overview: wg-easy WireGuard VPN on Ubuntu 24.04 LTS on Azure: overview (watch on YouTube)

Launch and log in: wg-easy WireGuard VPN on Ubuntu 24.04 LTS on Azure: launch and log in (watch on YouTube)

Deep Dive: wg-easy WireGuard VPN on Ubuntu 24.04 LTS on Azure: deep dive (watch on YouTube)

Overview

wg-easy is the easiest way to run your own WireGuard VPN and manage it from a browser. Instead of hand-editing wg0.conf and generating keys on the command line, you use a clean web console to add clients, hand out configuration files and QR codes, enable or disable peers, and watch live connection status.

The SecureAnyCloud image installs Docker CE from the official Docker repository and runs wg-easy 15.3.0 as a container, managed by Docker with a restart policy. The WireGuard tunnel listens on UDP 51820. The web admin UI is bound to the loopback connector 127.0.0.1:51821 behind an nginx reverse proxy on port 80, with the WebSocket upgrade that wg-easy uses for live peer status.

wg-easy's configuration and peer database live on a dedicated Azure data disk. A unique admin password and the public WireGuard endpoint are generated on the first boot of every VM.

What you get:

  • wg-easy 15.3.0 running as a container managed by Docker
  • Docker CE preinstalled from the official Docker apt repository
  • A WireGuard VPN tunnel on UDP 51820, with the address auto-detected on first boot
  • The web admin UI on :80, fronted by nginx with the WebSocket upgrade proxied
  • A unique admin password generated on first boot and recorded in a root-only file (username admin)
  • A dedicated Azure data disk at /var/lib/wg-easy that holds the WireGuard config and peer database
  • docker.service and nginx.service as systemd units, enabled and active
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting point.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network, 80/tcp for the admin UI, and 51820/udp for the WireGuard tunnel itself. Without the UDP rule, clients cannot connect.

The admin UI serves plain HTTP on port 80. For production, terminate TLS in front of it with your own domain (see Maintenance), because the console can add and remove VPN access to your network.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for wg-easy by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80). You add the WireGuard UDP 51820 rule after creation, in Step 2.

Review the dedicated data disk on the Disks tab, then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:wg-easy-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name wg-easy \
  --image sac1647283583153:wg-easy-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
# Open the admin UI (TCP 80) and the WireGuard tunnel (UDP 51820)
az vm open-port --resource-group <your-rg> --name wg-easy --port 80 --priority 1010
az vm open-port --resource-group <your-rg> --name wg-easy --port 51820 --priority 1020

WireGuard is a UDP protocol. Make sure the 51820/udp rule reaches the VM. Without it, the web UI works but no client can establish a tunnel.

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services and tunnel are up

systemctl is-active docker.service nginx.service
sudo docker exec wg-easy wg show

Both services report active. Docker manages the wg-easy container, and wg show reports the wg0 interface listening on port 51820.

wg-easy's configuration and peer database live on the dedicated Azure data disk mounted at /var/lib/wg-easy.

Step 5 - Retrieve your admin password and endpoint

First boot generates a unique admin password for your VM and writes it to a root-only file:

sudo cat /root/wg-easy-credentials.txt

This file contains WG_EASY_USERNAME (always admin), WG_EASY_PASSWORD, the WG_EASY_URL to open, and WIREGUARD_ENDPOINT. WIREGUARD_ENDPOINT is the public address that clients dial, auto-detected on first boot.

If your VM sits behind a NAT gateway or you use a DNS name, correct the endpoint later in the web UI under Admin panel -> Host.

Step 6 - Confirm the health endpoint

nginx serves an unauthenticated health endpoint for load balancers and probes. Request it with:

curl -s http://localhost/healthz

The endpoint returns ok. It never requires authentication, so it is safe to use for an Azure Load Balancer health probe.

Step 7 - Verify authentication from the command line

wg-easy's API uses HTTP Basic authentication with the same credentials as the web UI. An unauthenticated request or a wrong password returns 401, and the per-VM password returns 200.

The command embeds your unique password, so run it interactively rather than from a script. Substitute the value of WG_EASY_PASSWORD from Step 5 for <WG_EASY_PASSWORD>:

curl -s -o /dev/null -w '%{http_code}\n' -u admin:<WG_EASY_PASSWORD> http://127.0.0.1/api/client

A correct password prints 200. An unauthenticated request or a wrong password prints 401.

Step 8 - Sign in to the console

Browse to http://<vm-public-ip>/. wg-easy shows a sign-in page. Enter the username admin and the password from Step 5.

After you sign in, the Clients dashboard opens. A fresh VM has no clients yet, so you add your first one in the next step.

Step 9 - Add a VPN client

Select New (or New Client) and give the client a name such as my-laptop. Optionally set an expiry date, then select Create Client.

The client appears in the list with its assigned VPN address. From the client row, you can enable or disable the peer, edit it, show its QR code, download its .conf file, or generate a one-time share link.

Step 10 - Connect a device

Select the QR code icon to display the client configuration.

On a phone, open the official WireGuard app, choose Add tunnel -> Scan from QR code, and point the camera at the screen. On a desktop, select the download icon to save the .conf file, then import it into the WireGuard client.

The tunnel connects to the WIREGUARD_ENDPOINT from Step 5 over UDP 51820.

Step 11 - Confirm data lives on the dedicated disk

wg-easy stores its WireGuard configuration, keys and peer database under /var/lib/wg-easy on the dedicated Azure data disk. The directory is bind-mounted into the container as /etc/wireguard, so the data survives OS changes and you can resize the disk independently. Confirm the mount:

findmnt /var/lib/wg-easy

A separate Azure data disk backs the mount. The disk is captured into the image and re-provisioned on every VM.

Maintenance

  • Password. The admin password is set on first boot. To change it, sign in and use the account menu in the console.
  • Public endpoint. Clients dial the WIREGUARD_ENDPOINT recorded on first boot. If your VM is behind a NAT gateway or you move to a DNS name, update the endpoint in the web UI under Admin panel -> Host and re-issue the client configs.
  • Upgrades. wg-easy runs as the wg-easy container from the pinned ghcr.io/wg-easy/wg-easy:15.3.0 image. To upgrade, pull a newer tag, remove the container, and re-run it with the same -v /var/lib/wg-easy:/etc/wireguard mount so that your configuration is preserved.
  • Storage. All wg-easy state lives under /var/lib/wg-easy on the data disk. Back up that volume to protect your keys and peer list.
  • Firewall. The WireGuard tunnel needs 51820/udp open to the VM, and the admin UI needs 80/tcp. Restrict 80/tcp to trusted networks where possible.
  • TLS. The admin UI serves plain HTTP on port 80. Front it with TLS (for example, certbot with your own domain) before you run it in production, because the console can grant and revoke VPN access to your network.
  • Security patches. unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.

Support

SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.

Deploy on Azure

Launch wg-easy WireGuard VPN on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure