wg-easy docker-compose generator
Fill in your server and how you want to reach the admin panel. You get a docker-compose.yml that matches the current wg-easy v15 image, a Caddyfile if you want HTTPS, and the exact commands to start it. Everything is built in your browser.
Everything is generated in your browser. Nothing you type, including the password, is sent to our servers.
The address WireGuard clients connect to.
An A record for this name must point to the server, with ports 80 and 443 open.
- Click « New » to generate the admin password.
- Enter the panel domain: Caddy needs it to obtain the certificate.
# wg-easy v15 - generated on vpnsmith.com/en/tools/wg-easy-compose-generator
# Host: vpn.example.com - WireGuard port: 51820/udp - panel: https://wg.example.com
volumes:
etc_wireguard:
caddy_data:
caddy_config:
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:15
container_name: wg-easy
environment:
- PORT=80
- TRUSTED_PROXIES=10.42.42.43,fdcc:ad94:bacf:61a3::2b
- INIT_ENABLED=true
- INIT_USERNAME=admin
- INIT_PASSWORD=GENERATE-A-PASSWORD
- INIT_HOST=vpn.example.com
- INIT_PORT=51820
- INIT_DNS=1.1.1.1,9.9.9.9
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" # WireGuard: the only port clients need
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
caddy:
image: caddy:2-alpine
container_name: caddy
ports:
- "80:80/tcp"
- "443:443/tcp"
- "443:443/udp"
networks:
wg:
ipv4_address: 10.42.42.43
ipv6_address: fdcc:ad94:bacf:61a3::2b
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
restart: unless-stopped
networks:
wg:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
- subnet: 10.42.42.0/24
- subnet: fdcc:ad94:bacf:61a3::/64
wg.example.com {
reverse_proxy wg-easy:80
}
# 1. Firewall: SSH first, then the WireGuard port
sudo ufw allow OpenSSH
sudo ufw allow 51820/udp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
sudo ufw enable
# Note: ports published by Docker bypass ufw. Also open/close them in your provider firewall.
# 2. Create the folder and paste the generated file(s)
sudo mkdir -p /etc/docker/containers/wg-easy
cd /etc/docker/containers/wg-easy
sudo nano docker-compose.yml
sudo nano Caddyfile
# 3. Start wg-easy
sudo docker compose up -d
# Watch the logs (Ctrl+C to quit)
sudo docker compose logs -f wg-easy
# 4. Open the panel: https://wg.example.com
# 5. Once logged in, remove the INIT_* lines and run docker compose up -d again
This file needs a server with a public IP
A Contabo Cloud VPS gives you a dedicated IPv4, Docker-ready Linux images and unlimited traffic, which is all wg-easy needs.
Affiliate link: we earn a commission at no extra cost to you.
Why your old wg-easy compose file stopped working
wg-easy v15 is a full rewrite. Most environment variables from v14 tutorials are simply ignored by the new image: the container starts, but your host, password and DNS are not applied. The official migration guide states that most settings moved to the admin panel. This is how the old variables map to v15:
| v14 variable | v15 equivalent |
|---|---|
| WG_HOST | INIT_HOST (first start only), then the admin panel |
| PASSWORD / PASSWORD_HASH | INIT_USERNAME + INIT_PASSWORD, or the setup wizard |
| WG_PORT | INIT_PORT, plus the matching UDP port mapping |
| WG_DEFAULT_DNS | INIT_DNS |
| WG_DEFAULT_ADDRESS | INIT_IPV4_CIDR together with INIT_IPV6_CIDR |
| Panel over plain HTTP | INSECURE=true is now required |
Three ways to reach the admin panel
The panel can create VPN clients, so whoever reaches it controls your VPN. Only the WireGuard UDP port has to face the internet.
HTTPS with Caddy is the setup the wg-easy documentation recommends: Caddy obtains a real certificate for a sub-domain that points to your server, and the panel is never served over plain HTTP. The generator puts both containers on the same network, gives Caddy a fixed address and declares it in TRUSTED_PROXIES, so failed logins are logged with the real client IP.
The SSH tunnel publishes the panel on 127.0.0.1 only. Nothing is exposed; you open it with ssh -L when you need it. It is the simplest safe option when you have no domain.
LAN mode is for a home server: the panel is published over HTTP with INSECURE=true. Docker publishes ports through its own iptables rules, so ufw does not filter them; keep that port closed on your router or provider firewall.