SSD Nodes Learn 8GB RAM — $66/jaar
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-08-02

wg-easy: WireGuard beheren met een webinterface in Docker

Configureer wg-easy met Docker Compose: ontdek de vereiste poorten, NET_ADMIN, sysctls en QR-codes voor telefoonclients. Let op: versie 15 gebruikt geen omgevingsinstellingen.

Wat u bouwt

wg-easy is WireGuard met een webinterface, uitgevoerd als één Docker-container. Het beheert de WireGuard-interface voor u en voegt een browserinterface toe voor het aanmaken van clients. Elke client die u aanmaakt, krijgt een configuratiebestand en een QR-code. Een telefoon maakt vervolgens verbinding met de VPN door de camera op het scherm te richten.

De tunnel zelf is gewone WireGuard. De kernelmodule verplaatst de pakketten, waardoor de doorvoersnelheid gelijk is aan die van een handmatig geconfigureerde setup. U krijgt beheer van de levenscyclus van clients: peers toevoegen, uitschakelen en verwijderen zonder via SSH een configuratiebestand te bewerken. U levert directe controle over dat configuratiebestand in. Dat is het onderwerp van de handmatige WireGuard-setup op een VPS.

U hebt een KVM VPS met een openbaar IPv4-adres, Docker Engine met de Compose-plugin en root-toegang nodig. Containervirtualisatie die de kernel van de host deelt, zoals OpenVZ of LXC, kan de WireGuard-module meestal niet laden. De container kan de interface dan niet activeren.

Versie 15 heeft de instellingen uit de omgeving verwijderd

De meeste handleidingen die u vindt, zijn geschreven voor wg-easy 14. Daarin stelde u WG_HOST in op het adres van uw server en PASSWORD_HASH op een bcrypt-hash van het beheerderswachtwoord. Beide waarden werden als omgevingsvariabelen ingesteld. Versie 15 is een volledige herziening. In de officiële migratie-instructies staat duidelijk dat v15 niet dezelfde omgevingsvariabelen als v14 gebruikt en dat de meeste instellingen naar het beheerpaneel in de webinterface zijn verplaatst.

WG_HOST en PASSWORD_HASH hebben daarom geen effect meer. Als u een oud compose-bestand kopieert, start de container, worden die regels genegeerd en wordt u vervolgens in de browser gevraagd een beheerdersaccount aan te maken. Dat is geen fout. Dit is de nieuwe installatiestroom.

Vanaf juli 2026 is 15 de belangrijke tag waarop u de versie moet vastzetten. Zet de hoofdversie vast in plaats van latest te gebruiken, omdat een upgrade naar een nieuwe hoofdversie de indeling van de configuratie op schijf wijzigt en niet probleemloos kan worden teruggedraaid.

Het compose-bestand

Maak een map voor de stack en schrijf het officiële compose-bestand daarin. Dit is het upstream-bestand, ongewijzigd.

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

De inhoud ziet er als volgt uit:

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::/64

etc_wireguard is een benoemd volume met de serversleutel en elke client die u maakt. Maak een back-up van dat volume. Anders verwijdert een nieuwe build al uw peers. Als u deze bestanden liever op het hostbestandssysteem ziet, vervang het volume dan door een bind mount. Lees eerst het verschil tussen bind mounts en benoemde volumes, omdat de rechten zich anders gedragen.

Waarom NET_ADMIN, SYS_MODULE en de sysctls nodig zijn

Een container mag standaard geen wijzigingen aanbrengen in de netwerkstack. Elk van deze regels heft een specifieke beperking op.

NET_ADMIN zorgt ervoor dat de container de interface wg0 kan maken, er een adres aan kan toewijzen en routes kan schrijven. Zonder deze bevoegdheid start de container, maar stopt deze tijdens het activeren van de interface, omdat ip link add wg0 type wireguard Operation not permitted retourneert.

SYS_MODULE en de alleen-lezenkoppeling van /lib/modules zorgen ervoor dat de container de WireGuard-kernelmodule kan laden als de host deze nog niet heeft geladen. De module bevindt zich in de hostkernel, niet in de image. Daarom moet de hostdirectory zichtbaar zijn. In een moderne kernel is de module meestal ingebouwd. U kunt dit op de host bevestigen met sudo modprobe wireguard && echo ok.

net.ipv4.ip_forward=1 zorgt ervoor dat de kernel pakketten doorstuurt die niet voor de host zelf zijn bestemd. Zonder deze instelling maakt een client verbinding, slaagt de handshake en worden vervolgens alle internetpakketten verwijderd. Daardoor verloopt ping 1.1.1.1 zonder antwoord, terwijl de VPN verbonden lijkt.

net.ipv4.conf.all.src_valid_mark=1 is de instelling die vaak voor verrassingen zorgt. WireGuard markeert zijn eigen uitgaande pakketten, zodat deze niet terug de tunnel in worden gerouteerd. Strikte reverse path filtering ziet een pakket waarvan het bronadres niet overeenkomt met de verwachte route en verwijdert het. Deze sysctl vertelt de kernel dat gemarkeerde pakketten moeten worden geaccepteerd. Daardoor blijft een full tunnel werken zonder zichzelf te verbreken.

Start de service en maak het beheerdersaccount aan

cd /etc/docker/containers/wg-easy
sudo docker compose up -d
sudo docker compose logs -f

Gebruik docker compose up en docker compose down, niet start en stop. Upstream waarschuwt dat start op een container die onder andere instellingen is gemaakt, het netwerk in een inconsistente toestand achterlaat. Als u de stack na een herstart automatisch wilt herstellen, wordt dit al afgedekt door restart: unless-stopped. Het opstartgedrag van Compose-services legt uit wat dit beleid wel en niet garandeert.

De webinterface luistert op TCP-poort 51821. Bij het eerste bezoek wordt een configuratiepagina weergegeven. Daar maakt u het beheerdersaccount aan en bevestigt u het hostadres dat clients gebruiken om de server te bereiken. Dit hostadres wordt opgenomen in de regel Endpoint van elke clientconfiguratie. Het moet daarom het openbare IP-adres of de DNS-naam van de VPS zijn. Als het adres onjuist is, verwijst de QR-code die u aan een telefoon geeft naar een onbereikbare locatie en wordt de handshake niet voltooid.

Nog één punt over die poort: wg-easy 15 weigert onbeveiligd HTTP tenzij u INSECURE=true instelt. Toegang via HTTPS met een niet-vertrouwd certificaat is toegestaan. Hetzelfde geldt voor TLS-terminatie bij een reverse proxy vóór wg-easy. Toegang via http:// met de standaardinstellingen is niet toegestaan.

Publiceer de UI-poort niet op internet

Het compose-bestand publiceert poort 51821 op elke interface. Dit is een aanmeldpagina voor een systeem dat uw verkeer kan routeren. De poort mag daarom niet voor iedereen toegankelijk zijn. Wanneer Docker een poort publiceert, schrijft het regels naar de keten DOCKER. Die keten wordt vóór ufw geëvalueerd. Daarom sluit een ufw deny-regel de poort niet. Dit is een belangrijk aandachtspunt op zichzelf. waarom door Docker gepubliceerde poorten ufw negeren behandelt dit volledig.

De eenvoudige oplossing is om de UI aan loopback te binden en deze via een SSH-tunnel te benaderen:

    ports:
      - "51820:51820/udp"
      - "127.0.0.1:51821:51821/tcp"
    environment:
      - INSECURE=true

Voer dit vervolgens uit op uw laptop:

ssh -L 51821:127.0.0.1:51821 youruser@your.server.address

Open http://127.0.0.1:51821 in de browser op uw laptop. Het verkeer wordt door SSH versleuteld. De poort antwoordt aan niemand anders. INSECURE=true is hier veilig, omdat de onversleutelde HTTP-hop de loopback-interface nooit verlaat.

UDP 51820 openen en beide firewalls controleren

WireGuard vereist dat UDP 51820 bereikbaar is vanaf internet. Docker publiceert deze poort, maar veel providers plaatsen een afzonderlijke netwerkfirewall vóór de VPS die Docker niet kent. Open de poort op beide plaatsen. Als u de hostfirewall beheert met ufw, zijn de basisregels voor ufw op een VPS een kortere oplossing dan nftables handmatig te configureren.

Controleer of de container daadwerkelijk luistert:

sudo ss -ulnp | grep 51820

U moet een luisterende UDP-socket zien. Als er niets op die regel staat, heeft de container de interface niet geactiveerd en geeft sudo docker compose logs wg-easy de reden aan.

Een client maken en deze op een telefoon scannen

Maak in de UI een client en geef deze een naam die u later herkent, bijvoorbeeld de naam van het apparaat waarbij deze hoort. wg-easy wijst het volgende vrije tunneladres toe en genereert het sleutelpaar voor u. Elke clientrij bevat een QR-code en een downloadbaar .conf-bestand.

Installeer de officiële WireGuard-app op de telefoon. Kies ervoor om een tunnel via een QR-code toe te voegen en richt de camera op de code op uw scherm. De tunnel verschijnt met de naam die u hebt ingevoerd. Schakel de tunnel in. De clientrij in de UI toont vervolgens overdrachtstellers en een recent tijdstip van de handshake.

Een client waarbij na het inschakelen geen handshake wordt weergegeven, bereikt de server helemaal niet. Dit wijst op UDP 51820, bij de firewall van de provider of bij het endpointadres dat in de configuratie is opgenomen. Een client waarbij wel een handshake wordt weergegeven maar geen werkende internetverbinding heeft, wijst op een probleem met forwarding of DNS.

Download op een desktop het .conf-bestand en importeer dit in de WireGuard-client. Typ de inhoud niet opnieuw over. De private key in dit bestand wordt één keer gegenereerd en één keer weergegeven. Behandel het bestand zoals u een private SSH-key behandelt.

Wanneer u de UI ontgroeit

wg-easy is de juiste tool zolang uw peers mensen en telefoons zijn. De UI is sneller dan het bewerken van configuratiebestanden. Een verloren telefoon intrekken kost slechts één klik.

U bereikt de grenzen wanneer u iets wilt configureren dat de UI niet ondersteunt. Site-to-site-routing, waarbij de AllowedIPs van een peer een volledig extern subnet afdekt in plaats van één adres, vormt meestal de eerste beperking. Gesplitste tunnels met routeringsregels per peer of een configuratie die door uw provisioningtool wordt gegenereerd, zijn de volgende. Vanaf dat moment is de handmatig geschreven configuratie niet moeilijker. De aanpak is alleen anders. In de gewone WireGuard-handleiding ziet u hoe u dezelfde tunnel met wg0.conf opbouwt. Als u de control plane liever helemaal niet meer uitvoert, behandelt WireGuard vergeleken met Tailscale de beheerde optie.

Als de Compose-syntaxis hierboven het onbekende onderdeel was en niet WireGuard, legt De basis van Docker Compose op een VPS de bestandsindeling en de dagelijkse opdrachten uit.

FAQ

Waarom negeert wg-easy mijn WG_HOST en PASSWORD_HASH?

Die variabelen horen bij wg-easy 14. Versie 15 is volledig herschreven en upstream heeft vrijwel alle configuratie naar het beheerpaneel in de webinterface verplaatst. De container leest geen van beide variabelen en start daarom normaal. Bij het eerste bezoek vraagt de container u vervolgens een beheerdersaccount aan te maken. Stel het hostadres voor clients in op die configuratiepagina.

Heb ik SYS_MODULE nodig als mijn kernel WireGuard al bevat?

Nee. SYS_MODULE en de mount /lib/modules zijn bedoeld om de module te laden wanneer deze niet op de host aanwezig is. Op een host waarop sudo modprobe wireguard al slaagt, wordt deze mogelijkheid niet gebruikt. Het verwijderen hiervan is een redelijke hardeningmaatregel. NET_ADMIN blijft in beide gevallen vereist.

De client maakt verbinding, maar er is geen internet. Wat is er mis?

Een handshake zonder verkeer wijst vrijwel altijd op doorsturen. Controleer of net.ipv4.ip_forward=1 en net.ipv4.conf.all.src_valid_mark=1 nog in het compose-bestand staan. Een handmatig aangepaste kopie verliest deze instellingen vaak. Als doorsturen is ingeschakeld, controleert u de DNS-server die de client heeft ontvangen. Een tunnel die al het verkeer via de VPN verzendt, maar verwijst naar een DNS-server die niet meer bereikbaar is, lijkt in een browser precies op een verbroken verbinding.

Hoe maak ik een back-up van mijn clients?

Alles staat in het benoemde volume etc_wireguard, in een bestand wg0.json. De gebruikersinterface bevat ook een back-upknop die dezelfde gegevens exporteert. Kopieer dat bestand vóór elke upgrade naar een locatie buiten de server. Herstellen gebeurt door het bestand tijdens de configuratiestap naar een nieuwe container te uploaden.

Kan ik wg-easy achter een reverse proxy uitvoeren?

Ja. Plaats de proxy vóór TCP 51821, beëindig TLS daar en stel INSECURE=true in op de container, zodat deze de onbeveiligde HTTP-hop van de proxy accepteert. Publiceer UDP 51820 rechtstreeks, omdat VPN-verkeer UDP gebruikt en niet via een HTTP-proxy gaat.