Wireguard, WG-Easy and Nginx Docker Compose File using Traefik

Run Wireguard, wg-easy and Nginx in a single docker compose file, using Traefik and configure SSL using letsencrypt. This post aims to improve on this wiki post by allowing you to run a website on port 443 rather than wg-easy.

Replace your-domain.com and yourpassword10000 and [email protected] with your domain, password and email, optionally also change the port for your wg-easy configuration using WG_HOST. You can access the wg-easy admin panel at https://your-domain.com:4748.

If you would like to use the Traefik admin UI, uncomment the port 8080 and api. entries.

Save as docker-compose.yml and then run the command docker network create traefik_network followed by docker compose up -d. This will make the nginx folder to place your website files in as required.

services:
  wg-easy:
    labels:
      # traefik
      - "traefik.enable=true"
      - "traefik.http.services.WireGuardService.loadbalancer.server.port=51821"
      # http to https
      - "traefik.http.routers.WireGuardRoute.service=WireGuardService"
      # https
      - "traefik.http.routers.WireGuardRouteSSL.service=WireGuardService"
      - "traefik.http.routers.WireGuardRouteSSL.rule=Host(`your-domain.com`)"
      - "traefik.http.routers.WireGuardRouteSSL.entrypoints=wireguardWGEasyPanel"
      - "traefik.http.routers.WireGuardRouteSSL.tls.certresolver=MainCertResolver"
    environment:
      - WG_HOST=your-domain.com
      - PASSWORD=yourpassword10000
      - UI_TRAFFIC_STATS=true
      - WG_HOST=4748

    container_name: wg-easy
    image: ghcr.io/wg-easy/wg-easy
    networks:
      - traefik_network
    volumes:
      - .:/etc/wireguard
    ports:
      - "51820:51820/udp"
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1

  nginx:
    image: nginx:latest
    restart: unless-stopped
    labels:
      # traefik
      - traefik.enable=true
      - traefik.http.routers.nginx.rule=Host(`your-domain.com`)
      - traefik.http.routers.nginx.entrypoints=websecure
      - traefik.http.routers.nginx.tls=true
      - traefik.http.routers.nginx.tls.certresolver=MainCertResolver
    networks:
      - traefik_network
    volumes:
      - ./nginx:/usr/share/nginx/html/:ro

  traefik:
    image: traefik:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik_letsencrypt_data:/letsencrypt
    networks:
      - traefik_network
    ports:
      - "80:80"
      - "443:443"
      - "4748:4748"
      # - "8080:8080"
    command:
      - "--providers.docker"
      - "--providers.docker=true"
      # - "--api.dashboard=true"
      # - "--api.insecure=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=traefik_network"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
      - "--entrypoints.wireguardWGEasyPanel.address=:4748"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.MainCertResolver.acme.tlschallenge=true"
      - "--certificatesresolvers.MainCertResolver.acme.email=youremail@example.com"
      - "--certificatesresolvers.MainCertResolver.acme.storage=/letsencrypt/acme.json"
      # - "--log.level=DEBUG"

networks:
  traefik_network:
    external: true

volumes:
  traefik_letsencrypt_data:

You may also want to limit the administration portal to just IP whitelisted addresses, you can do this by adding the following to the wg-easy labels, replacing 1.2.3.4 with your IP address and adding any other required addresses using a comma to separate. You could also whitelist clients inside your container by adding the network range.

      - "traefik.http.middlewares.my-ipwhitelist.ipallowlist.sourcerange=1.2.3.4"
      - "traefik.http.routers.WireGuardRouteSSL.middlewares=my-ipwhitelist@docker"

Please feel free to use this post under the terms of the original licence which you can access here.


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.