- Dockerfile 59.2%
- Shell 40.8%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| .dockerignore | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| LICENSE | ||
| README.md | ||
AmneziaWG Client Docker
A lightweight Docker container for running AmneziaWG VPN client tunnels. Built from the latest amneziawg-tools and amneziawg-go sources with full support for all obfuscation parameters (Jc, Jmin, Jmax, S1-S4, H1-H4, I1-I5).
Quick Start
services:
azwg-client:
image: git.redteam.sh/dan/azwg-client:latest
restart: unless-stopped
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- ./config:/etc/amnezia/amneziawg:ro
Usage
- Place one or more AmneziaWG
.conffiles in the root of the directory mounted to/etc/amnezia/amneziawg(subdirectories are not scanned) - Start the container - each config file creates an interface named after the file (
azwg0.conf->azwg0) - Mount as
:rofor immutable configs, or rw if usingSaveConfig = trueto persist runtime changes
Config Example
[Interface]
PrivateKey = <your-private-key>
Address = 10.0.0.2/32
DNS = 1.1.1.1
Jc = 5
Jmin = 49
Jmax = 998
S1 = 17
S2 = 110
H1 = 769445522
H2 = 87389456
H3 = 111129251
H4 = 1623403840
[Peer]
PublicKey = <server-public-key>
AllowedIPs = 0.0.0.0/0
Endpoint = server.example.com:51820
PersistentKeepalive = 25
PresharedKey = <your-pre-shared-key>
Requirements
- Kernel module (recommended): Install amneziawg-linux-kernel-module on the host. If the module is already loaded on the host, no extra container config is needed. To let the container load it via
modprobe, addSYS_MODULEcapability and mount/lib/modules:/lib/modules:ro - Userspace fallback: If the kernel module is not available, the container automatically falls back to
amneziawg-go(slower)
Healthcheck
No healthcheck is built into the image since VPN tunnels vary widely (full tunnel, split tunnel, private networks without internet, etc.). Define one in your compose file based on your setup:
# Full internet tunnel (AllowedIPs = 0.0.0.0/0)
healthcheck:
test: ["CMD-SHELL", "ping -c1 -W3 1.1.1.1 >/dev/null 2>&1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
# Split tunnel to a private subnet
healthcheck:
test: ["CMD-SHELL", "ping -c1 -W3 10.0.0.1 >/dev/null 2>&1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
# Just verify the interface is up (any tunnel type)
healthcheck:
test: ["CMD-SHELL", "awg show interfaces | grep -q ."]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
Capabilities & Volumes
Only NET_ADMIN is strictly required. Everything else depends on your environment:
| Item | Required? | When needed |
|---|---|---|
cap_add: NET_ADMIN |
Always | Create and manage network interfaces |
cap_add: SYS_MODULE |
No | Only if the container needs to load the amneziawg kernel module (not needed if already loaded on host) |
/lib/modules:/lib/modules:ro |
No | Same as above - provides module files for modprobe |
/dev/net/tun:/dev/net/tun |
Recommended | Required for the amneziawg-go userspace fallback (TUN device). Not technically needed when using the kernel module (which creates its own interface type), but strongly recommended since the container falls back to userspace silently if the module isn't loaded. |
net.ipv4.conf.all.src_valid_mark=1 |
No | Only needed if your config routes all traffic (AllowedIPs = 0.0.0.0/0). awg-quick sets this automatically, but declaring it as a sysctl ensures it is set before interface creation. Not needed for split-tunnel configs. |
Full example (all options included)
services:
azwg-client:
image: git.redteam.sh/dan/azwg-client:latest
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- ./config:/etc/amnezia/amneziawg:ro
- /lib/modules:/lib/modules:ro
Routing Other Containers Through the VPN
Use Docker's network_mode: service: to route another container's traffic through the VPN tunnel. The dependent container shares the VPN container's network stack, so all its traffic goes through AmneziaWG.
services:
azwg-client:
image: git.redteam.sh/dan/azwg-client:latest
restart: unless-stopped
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
volumes:
- ./config:/etc/amnezia/amneziawg:ro
healthcheck:
test: ["CMD-SHELL", "awg show interfaces | grep -q . && ping -c1 -W3 1.1.1.1 >/dev/null 2>&1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
myapp:
image: myapp:latest
network_mode: "service:azwg-client"
depends_on:
azwg-client:
condition: service_healthy
restart: unless-stopped
Note: When using
network_mode: service:, any ports you need to access on the dependent container must be published on the VPN container instead, since they share the same network namespace.
How It Works
- On startup, all
.conffiles from/etc/amnezia/amneziawg/are brought up viaawg-quick awg-quickadds policy routing rules whenAllowedIPs = 0.0.0.0/0(fwmark-based routing to prevent loops), but does not add NAT/masquerade rules — usePostUp/PostDownin your config if you need those- On
SIGTERM/SIGINT, all interfaces are cleanly torn down viaawg-quick down
Building
docker build -t azwg-client:latest .
License
This project is licensed under the GPL-3.0 License - see the LICENSE file for details.