Skip to content

Instantly share code, notes, and snippets.

@skylerwlewis
Last active April 28, 2025 18:36
Show Gist options
  • Save skylerwlewis/f009741cd20d8ab86ce65d67accccc3f to your computer and use it in GitHub Desktop.
Save skylerwlewis/f009741cd20d8ab86ce65d67accccc3f to your computer and use it in GitHub Desktop.
Routing wg-easy container traffic through Gluetun container
# https://gist.github.com/skylerwlewis/f009741cd20d8ab86ce65d67accccc3f
#
# This is a Gluetun + wg-easy docker compose setup based on instructions I found here:
# https://lemmy.max-p.me/post/midwest.social/14630711
#
# In addition to the logic in the link above, I added:
# - wg-easy to simplify client setup and PostUp & PostDown modifications
# - Auto-restart capability for wg-easy container if Gluetun goes down
#
# If you are using 172.22.0.0/24 already, simply change "172.22" to a different subnet.
#
# If you use a different local network (other than 192.168.1.0/24),
# replace "192.168.1.0/24" in the config below with your local network
#
# If you need to run on different ports, or want to run multiple copies of the setup below:
# Use a different gluetun healthcheck port (default 9999):
# - Under gluetun's ports, change "9999:9999/tcp" to "<updated port>:9999/tcp"
# - Replace all other instances of 9999 in this file with the updated port
# Use a different wireguard port (default 51820):
# - Replace all instances of 51820 in this file with the updated port
# Use a different wg-easy UI port (default 51821):
# - Replace all instances of 51821 in this file with the updated port
#
# A version of this setup using Wireguard-UI can be found here:
# https://gist.github.com/skylerwlewis/50dd3dd628a5198ea29cfbcbf21783ac
networks:
default:
ipam:
config:
- subnet: 172.22.0.0/24
services:
gluetun:
image: qmcgaw/gluetun
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
environment:
PUID: 1000
PGID: 1000
TZ: "America/Chicago"
# See https://github.com/qdm12/gluetun-wiki/tree/main/setup/providers
# for information on how to setup gluetun for different VPN providers.
# An example of a Mullvad Wireguard setup is below
VPN_SERVICE_PROVIDER: mullvad
VPN_TYPE: wireguard
WIREGUARD_PRIVATE_KEY: <PrivateKey_value_from_cilent_.conf_file>
OWNED_ONLY: yes # if uncommented, gluetun will use only Mullvad-owned servers
WIREGUARD_ADDRESSES: <Addresses_value_from_cilent_.conf_file>
SERVER_CITIES: "Amsterdam"
UPDATER_PERIOD: 24h
volumes:
- ./data/gluetun/conf:/gluetun
sysctls:
# Disables ipv6
- net.ipv6.conf.all.disable_ipv6=1
restart: unless-stopped
networks:
default:
ipv4_address: 172.22.0.100
ports:
# port of the gluetun healthcheck server
- 9999:9999/tcp
configs:
# allows wireguard to send traffic through gluetun
# https://github.com/qdm12/gluetun-wiki/blob/main/setup/options/firewall.md#custom-iptables-rules
- source: post-rules.txt
target: /iptables/post-rules.txt
wg-easy:
environment:
# Change Language:
# (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi, ja, si)
- LANG=en
# ⚠️ Required:
# Change this to your host's public address
- WG_HOST=wireguard.example.com
# Optional:
# - PASSWORD_HASH=$$2y$$10$$hBCoykrB95WSzuV4fafBzOHWKu9sbyVa34GJr8VV5R/pIelfEMYyG # (needs double $$, hash of 'foobar123'; see "How_to_generate_an_bcrypt_hash.md" for generate the hash)
- PORT=51821
- WG_PORT=51820
# - WG_CONFIG_PORT=92820
# - WG_DEFAULT_ADDRESS=10.8.0.x
- WG_DEFAULT_DNS=172.22.0.100
# - WG_MTU=1420
# - WG_ALLOWED_IPS=192.168.15.0/24, 10.0.1.0/24
# - WG_PERSISTENT_KEEPALIVE=25
# - WG_PRE_UP=echo "Pre Up" > /etc/wireguard/pre-up.txt
- WG_POST_UP=iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE; wg set wg0 fwmark 51820; ip -4 rule add not fwmark 51820 table 51820; ip -4 rule add table main suppress_prefixlength 0; ip -4 route add 0.0.0.0/0 via 172.22.0.100 table 51820; ip -4 route add 192.168.1.0/24 via 172.22.0.1
# - WG_PRE_DOWN=echo "Pre Down" > /etc/wireguard/pre-down.txt
- WG_POST_DOWN=iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE
# - UI_TRAFFIC_STATS=true
# - UI_CHART_TYPE=0 # (0 Charts disabled, 1 # Line chart, 2 # Area chart, 3 # Bar chart)
# - WG_ENABLE_ONE_TIME_LINKS=true
# - UI_ENABLE_SORT_CLIENTS=true
# - WG_ENABLE_EXPIRES_TIME=true
# - ENABLE_PROMETHEUS_METRICS=false
# - PROMETHEUS_METRICS_PASSWORD=$$2a$$12$$vkvKpeEAHD78gasyawIod.1leBMKg8sBwKW.pQyNsq78bXV3INf2G # (needs double $$, hash of 'prometheus_password'; see "How_to_generate_an_bcrypt_hash.md" for generate the hash)
image: ghcr.io/wg-easy/wg-easy
container_name: wg-easy
volumes:
- ./data/wireguard:/etc/wireguard
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
healthcheck:
# check health of gluetun container, and auto-restart if gluetun is unhealthy
test: "nc -z 172.22.0.1 9999 || kill 1"
interval: 1m
timeout: 1m
restart: unless-stopped
networks:
default:
ipv4_address: 172.22.0.2
cap_add:
- NET_ADMIN
- SYS_MODULE
# - NET_RAW # ⚠️ Uncomment if using Podman
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
configs:
post-rules.txt:
content: |
iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE
iptables -t filter -A FORWARD -d 172.22.0.2 -j ACCEPT
iptables -t filter -A FORWARD -s 172.22.0.2 -j ACCEPT
@tomorrow-nf
Copy link

Going to share this here too. I've been trying to do use WG and Gluetun to make a single wireguard connection that'll route outgoing traffic through Mullvad, while also allowing me to access my LAN. This compose was working for the former, but not the latter. I found someone else's example which gave me the same results.

After bashing my head against the wall for a bit and learning more than I expected to about iptables, I have a version that does exactly what I want:

qdm12/gluetun#1192 (reply in thread)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment