wg-easy: WireGuard Web UI sa Docker
Patakbuhin ang WireGuard gamit ang wg-easy at Docker Compose. Alamin ang ports, NET_ADMIN, mahahalagang sysctl, at QR code onboarding para sa phones.
Ang ginagawa mo
Ang wg-easy ay WireGuard na may web interface at tumatakbo bilang isang Docker container. Pinamamahalaan nito ang WireGuard interface para sa iyo at nagdaragdag ng browser UI para gumawa ng mga client. Ang bawat client na gagawin mo ay magkakaroon ng config file at QR code, kaya makakasali ang isang phone sa VPN kapag itinapat ang camera nito sa screen.
Ordinaryong WireGuard ang tunnel mismo. Inililipat ng kernel module ang mga packet, kaya kapareho ang throughput ng setup na manu-manong ginawa. Ang makukuha mo ay client lifecycle: pagdaragdag, pagdi-disable, at pagtanggal ng mga peer nang hindi nag-e-edit ng config file sa SSH. Ang isinusuko mo ay direktang kontrol sa config na iyon. Ito ang paksa ng manu-manong WireGuard setup sa isang VPS.
Kailangan mo ng KVM VPS na may public IPv4 address, Docker Engine na may Compose plugin, at root access. Ang container virtualization na gumagamit ng kernel ng host, gaya ng OpenVZ o LXC, ay karaniwang hindi makakapag-load ng WireGuard module. Dahil dito, mabibigo ang container na i-activate ang interface.
Inilipat ng Version 15 ang mga setting mula sa environment
Karamihan sa mga guide na makikita mo ay isinulat para sa wg-easy 14, kung saan itinatakda mo ang WG_HOST sa address ng server at ang PASSWORD_HASH sa bcrypt hash ng admin password, at parehong environment variable ang mga ito. Rewrite ang Version 15. Malinaw na sinasabi sa opisyal na migration notes na hindi ginagamit ng v15 ang kaparehong environment variable ng v14 at na karamihan sa mga ito ay inilipat sa admin panel ng web UI.
Kaya wala nang epekto ang WG_HOST at PASSWORD_HASH. Kung kokopyahin mo ang lumang compose file, magsisimula ang container, babalewalain ang mga linyang iyon, at hihilingin sa iyo na gumawa ng admin account sa browser. Hindi ito bug. Ito ang bagong setup flow.
Noong July 2026, ang major tag na dapat i-pin ay 15. I-pin ang major version sa halip na gamitin ang latest, dahil binabago ng major upgrade ang on-disk config format at hindi ito malinis na makakapag-rollback.
Ang compose file
Gumawa ng directory para sa stack at isulat dito ang opisyal na compose file. Ito ang upstream file at hindi ito binago.
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.ymlGanito ang hitsura ng mga laman nito:
volumes:
etc_wireguard:
services:
wg-easy:
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::/64Ang etc_wireguard ay isang named volume na naglalaman ng server key at ng bawat client na gagawin mo. I-back up ang volume na ito. Kung hindi, mabubura ang lahat ng peer kapag nag-rebuild ka. Kung mas gusto mong makita ang mga file na iyon sa filesystem ng host, palitan ito ng bind mount. Basahin muna ang pagkakaiba ng bind mount at named volume bago mo gawin ito, dahil magkaiba ang pag-uugali ng permissions.
Bakit kailangan nito ang NET_ADMIN, SYS_MODULE at mga sysctl
Hindi maaaring direktang galawin ng isang container ang network stack bilang default, at inaalis ng bawat line na ito ang isang partikular na harang.
Ang NET_ADMIN ay nagbibigay-daan sa container na gumawa ng wg0 interface, magtalaga rito ng address, at magsulat ng mga route. Kung wala ito, mag-uumpisa ang container at mamamatay habang inaakyat ang interface, dahil ibinabalik ng ip link add wg0 type wireguard ang Operation not permitted.
Ang SYS_MODULE, kasama ang read-only na /lib/modules mount, ay nagbibigay-daan sa container na i-load ang WireGuard kernel module kung hindi pa ito na-load ng host. Nasa host kernel ang module, hindi sa loob ng image. Kaya kailangang visible ang directory ng host. Sa modern kernel, karaniwang built in na ang module. Makukumpirma mo ito gamit ang sudo modprobe wireguard && echo ok sa host.
Ang net.ipv4.ip_forward=1 ang nag-uutos sa kernel na mag-forward ng mga packet na hindi nakalaan mismo sa box. Kung wala ito, kumokonekta ang client, nagtatagumpay ang handshake, at pagkatapos ay dini-drop ang bawat packet papunta sa internet. Dahil dito, nagti-time out ang ping 1.1.1.1 habang mukhang konektado ang VPN.
Ang net.ipv4.conf.all.src_valid_mark=1 ang karaniwang nakapagtataka sa mga user. Minamarkahan ng WireGuard ang sarili nitong outgoing packet para hindi ito ma-route pabalik sa tunnel. Nakikita ng strict reverse path filtering ang packet na may source address na hindi tumutugma sa inaasahang route, kaya dini-drop ito. Sinasabi ng sysctl na ito sa kernel na tanggapin ang mga marked packet. Ito ang pumipigil sa full tunnel na masira ang sarili nitong routing.
Simulan ito at gawin ang admin account
cd /etc/docker/containers/wg-easy
sudo docker compose up -d
sudo docker compose logs -fGamitin ang docker compose up at docker compose down, hindi ang start at stop. Nagbabala ang upstream na ang start sa isang container na ginawa gamit ang ibang settings ay nag-iiwan sa network sa hindi pare-parehong estado. Kung gusto mong awtomatikong bumalik ang stack pagkatapos ng reboot, saklaw na ito ng restart: unless-stopped, at ipinapaliwanag ng gawi sa pag-boot ng mga serbisyo ng compose kung ano ang ipinapangako at hindi ipinapangako ng policy na iyon.
Nakikinig ang web UI sa TCP 51821. Sa unang pagbisita, ipinapakita nito ang setup page kung saan gagawin mo ang admin account at kukumpirmahin ang host address na gagamitin ng mga client para maabot ang server. Napupunta ang host address na iyon sa linyang Endpoint ng bawat client config, kaya dapat itong public IP o DNS name ng VPS. Kung mali ito, ang QR code na ibibigay mo sa telepono ay tuturo sa address na hindi maaabot, at hindi makukumpleto ang handshake.
Isa pang mahalagang detalye tungkol sa port na iyon: tumatanggi ang wg-easy 15 sa plain HTTP maliban kung ise-set mo ang INSECURE=true. Maaaring maabot ito gamit ang HTTPS na may untrusted certificate, o maaaring i-terminate ang TLS sa reverse proxy na nasa harap nito. Hindi maaaring maabot ito gamit ang http:// kapag default settings ang gamit.
Huwag i-publish sa internet ang UI port
Ini-publish ng compose file ang 51821 sa bawat interface. Login page ito para sa isang box na maaaring mag-route ng iyong traffic, kaya hindi ito dapat bukas sa lahat. Kapag nag-publish ng port ang Docker, nagsusulat ito ng mga rule sa DOCKER chain, na sinusuri bago ang ufw. Dahil dito, hindi ito isinasara ng ufw deny rule. Mahalagang maunawaan ang trap na ito, at ganap itong ipinapaliwanag ng kung bakit hindi sinusunod ng mga Docker published port ang ufw.
Ang simpleng ayos ay i-bind ang UI sa loopback at i-access ito sa pamamagitan ng SSH tunnel:
ports:
- "51820:51820/udp"
- "127.0.0.1:51821:51821/tcp"
environment:
- INSECURE=truePagkatapos, mula sa iyong laptop:
ssh -L 51821:127.0.0.1:51821 youruser@your.server.addressBuksan ang http://127.0.0.1:51821 sa browser ng iyong laptop. Naka-encrypt ng SSH ang traffic, walang ibang makakasagot sa port, at ligtas gamitin ang INSECURE=true dito dahil hindi lumalabas sa loopback interface ang plain HTTP hop.
Buksan ang UDP 51820 at suriin ang parehong firewall
Kailangang reachable mula sa internet ang UDP 51820 para sa WireGuard. Ipinapublish ito ng Docker, ngunit maraming provider ang naglalagay ng hiwalay na network firewall sa harap ng VPS na walang nalalaman tungkol sa Docker. Buksan ang port sa parehong firewall. Kung pinamamahalaan mo ang host firewall gamit ang ufw, mas maikling paraan ang mga pangunahing ufw rule para sa isang VPS kaysa manu-manong magsulat ng nftables.
Suriin kung aktuwal na nakikinig ang container:
sudo ss -ulnp | grep 51820Dapat kang makakita ng listening UDP socket. Kung walang lumabas sa linyang iyon, hindi naitaas ng container ang interface, at sasabihin ng sudo docker compose logs wg-easy ang dahilan.
Gumawa ng client at i-scan ito sa phone
Sa UI, gumawa ng client at bigyan ito ng pangalang makikilala mo sa susunod, gaya ng device na pagmamay-ari nito. Inilalaan ng wg-easy ang susunod na available na tunnel address at awtomatikong ginagawa ang key pair para sa iyo. May QR code at mada-download na .conf file ang bawat client row.
I-install ang opisyal na WireGuard app sa phone. Piliing magdagdag ng tunnel mula sa QR code, at itutok ang camera sa code sa screen. Lalabas ang tunnel gamit ang pangalang inilagay mo. I-on ito. Magsisimulang magpakita ang client row sa UI ng mga transfer counter at pinakabagong handshake time.
Ang client na walang handshake matapos itong i-enable ay hindi talaga nakakarating sa server. Tumutukoy ito sa UDP 51820, maaaring sa provider firewall o sa endpoint address na nakalagay sa config. Ang client na may handshake ngunit walang gumaganang internet ay may problema sa forwarding o sa DNS.
Sa desktop, i-download ang .conf file at i-import ito sa WireGuard client sa halip na muling i-type ang config. Isang beses lang ginagawa at ipinapakita ang private key sa file na iyon. Ingatan ang file na parang SSH private key.
Kailan lalampas sa UI
Ang wg-easy ay angkop habang mga tao at phone ang iyong mga peer. Mas mabilis ang UI kaysa sa manu-manong pag-edit ng mga config file, at isang click lang ang kailangan para bawiin ang access ng nawawalang phone.
Maaabot mo ang mga limitasyon nito kapag kailangan mo ng bagay na hindi nito kayang i-model ng UI. Karaniwang unang limitasyon ang site-to-site routing, kung saan ang AllowedIPs ng isang peer ay sumasaklaw sa buong remote subnet sa halip na isang address lang. Kasunod nito ang split tunnel na may mga routing rule bawat peer, o isang config na ginagawa ng provisioning tool mo. Sa puntong iyon, hindi mas mahirap ang manu-manong setup; iba lang ito, at ipinapakita ng simpleng WireGuard guide ang parehong tunnel na ginawa mula sa wg0.conf. Kung mas gusto mong tuluyang ihinto ang pagpapatakbo ng control plane, tinatalakay ng Paghahambing ng WireGuard at Tailscale ang managed na opsyon.
Kung ang compose syntax sa itaas ang hindi pamilyar na bahagi, sa halip na ang WireGuard, ipinapaliwanag ng Mga pangunahing kaalaman sa Docker Compose sa isang VPS ang format ng file at mga karaniwang command.
FAQ
Bakit binabalewala ng wg-easy ang aking WG_HOST at PASSWORD_HASH?
Ang mga variable na iyon ay para sa wg-easy 14. Ang Version 15 ay muling isinulat, at inilipat ng upstream ang halos lahat ng configuration sa admin panel ng web UI. Hindi binabasa ng container ang alinman sa mga variable, kaya normal itong nagsisimula at pagkatapos ay hinihiling sa iyong gumawa ng admin account sa unang pagbisita. Itakda ang host address na gagamitin ng client sa setup page na iyon.
Kailangan ko ba ang SYS_MODULE kung mayroon nang WireGuard ang aking kernel?
Hindi. Umiiral ang SYS_MODULE at ang /lib/modules mount upang ma-load ng container ang module kapag wala ito sa host. Sa host na matagumpay nang tumatakbo ang sudo modprobe wireguard, hindi ginagamit ang capability na ito. Makatuwirang alisin ito bilang hardening step, at kailangan pa rin ang NET_ADMIN sa alinmang paraan.
Kumokonekta ang client pero walang internet. Ano ang mali?
Ang handshake na walang traffic ay halos palaging nangangahulugan ng problema sa forwarding. Tiyaking nasa compose file pa rin ang net.ipv4.ip_forward=1 at net.ipv4.conf.all.src_valid_mark=1, dahil madalas mawala ang mga ito sa kinopyang mano-manong ine-edit. Kung naka-enable ang forwarding, tingnan ang DNS server na natanggap ng client. Ang tunnel na ipinapadaan ang lahat ng traffic sa VPN pero gumagamit ng DNS server na hindi na nito maabot ay eksaktong magmumukhang patay na koneksyon sa browser.
Paano ko iba-back up ang aking mga client?
Nasa etc_wireguard named volume ang lahat, sa isang wg0.json file. May backup button din ang UI na nag-e-export ng parehong data. Kopyahin ang file sa isang lokasyon sa labas ng server bago ang anumang upgrade. Ang pag-restore ay ginagawa sa pamamagitan ng upload sa setup step ng bagong container.
Maaari ko bang patakbuhin ang wg-easy sa likod ng reverse proxy?
Oo. Ilagay ang proxy sa harap ng TCP 51821, tapusin doon ang TLS, at itakda ang INSECURE=true sa container upang tanggapin nito ang plain HTTP hop mula sa proxy. Panatilihing direktang naka-publish ang UDP 51820, dahil UDP ang VPN traffic at hindi ito dumadaan sa HTTP proxy.