wg_docker - WireGuard Docker Orchestration¶
Overview¶
wg_docker is a Typer-based CLI for managing WireGuard server/client deployments via Docker. It renders configuration files from templates and controls lifecycle with docker compose. The tool is designed to be safe for first-time usage by bootstrapping missing keys and templates.
Prerequisites¶
Linux host with Docker and docker compose available
wgbinary available in$PATH(used for key generation)Systemd-based distributions are recommended for production
Configuration Directory¶
All generated and user-managed files live under:
/var/lib/clash_tools/wireguard
Set CLASH_TOOLS_WG_CONFIG_DIR to override the default location if you
need a custom path (for example, when running without elevated privileges).
Key files:
server_config.yml: Authoritative server-side configuration (auto-copied from packaged template on first use)server_wg0.conf: Rendered WireGuard server configserver_compose.yml: Rendered docker compose for the serverclient_wg0.conf: Rendered WireGuard client configclient_compose.yml: Rendered docker compose for the clientwg_keys.json: Pre-generated key pairs store (peer id 1 = server; 2..254 = clients)
Keys and Identity¶
On first import/run, the tool ensures a keystore exists and, if missing, generates pairs for ids 1..254 using the system wg binary.
ID 1: server private/public key
IDs 2..254: client private/public keys
Stored at
wg_keys.jsonwithin the user config directory
Command Groups and Commands¶
server¶
server upRenders
server_wg0.confandserver_compose.ymlto the user config directoryStarts the server docker stack in detached mode
server downStops the stack and removes volumes (
down -v)
server restartEquivalent to
downfollowed byup
server showExecutes
wg showinside the running container for inspection
server configManage
server_config.ymlwith options: ---edit: Open file in$VISUAL/$EDITOR(fallback tonano) ---cat: Print contents ---path: Print absolute path ---reset: Overwrite with packaged template
server get-client-config <client_id>Render and print the specific client’s
client_wg0.confto stdout (does not start any container)
client¶
client upRenders
client_compose.ymland starts the client docker stack in detached mode
client downStops the stack and removes volumes
client restartEquivalent to
downfollowed byup
client configManage
client_wg0.confwith options--edit/--cat/--path/--reset
Quick Start¶
# Install
pip install clash_tools
# Start the server (missing keys and template will be auto-bootstrapped)
python -m clash_tools.wg_docker.cli server up
# Inspect WireGuard state in the server container
python -m clash_tools.wg_docker.cli server show
# Render and display the config for client id 2
python -m clash_tools.wg_docker.cli server get-client-config 2
# Start the client stack
python -m clash_tools.wg_docker.cli client up
server_config.yml Schema¶
Top-level keys:
server: -nic(str): Outbound interface for MASQUERADE rules (defaulteth0) -server_ip(str): Public IP or DNS name for server endpoint -subnet(str): Server-side IPv4 subnet in CIDR notation (e.g.,10.9.0.0/24) -listen_port(int): UDP port for the serverclients(dict[int, client]) — keys are client ids 2..254. Each client has: -nic(str): Host interface used by client for LAN routes in PostUp/PreDown -exclude_defaults(bool): Whether to merge default private/link-local ranges intoexcludedips-allowedips(list/str): Values rendered into clientAllowedIPs(default["0.0.0.0/0"]) -excludedips(list/str): CIDRs or addresses routed outside the tunnel -snat(bool): Whether server applies SNAT for traffic destined to this client -c_to_s_ports(list): Per-entry format[client_port, server_port, [tsl_method]]wheretsl_methodistcporudp(defaults totcp)
Example:
server:
nic: eth0
server_ip: 6.6.6.6
subnet: 10.9.0.0/24
listen_port: 51820
clients:
2:
nic: eth0
exclude_defaults: true
allowedips:
- 0.0.0.0/0
excludedips: []
snat: false
c_to_s_ports:
- [22, 2222]
- [80, 8080]
- [443, 8443]
3:
nic: eth0
exclude_defaults: true
allowedips:
- 0.0.0.0/0
excludedips: []
snat: true
c_to_s_ports:
- [12345, 45678, "udp"]
Routing Behavior (Client)¶
The client template sets PostUp and PreDown commands to preserve reachability:
Always adds a specific route for the WireGuard subnet via
wg0If
excludedips(possibly merged withexclude_defaults) is non-empty, routes those destinations via the client’snicand default gateway when available
Port Forwarding and Compose Ports (Server)¶
For each client mapping in
c_to_s_ports, two things happen: 1. iptables PREROUTING/ FORWARD rules are emitted to DNAT and ACCEPT traffic destined toserver_porttowards the client’sclient_portand IP 2. The server compose file exposes a host port mappingserver_port/server_protocol
Generated Files and Templates¶
Templates (shipped):
server_wg0.conf.j2,client_wg0.conf.j2,server_compose.yml.j2,client_compose.yml.j2Outputs (rendered in user config dir):
server_wg0.conf,client_wg0.conf,server_compose.yml,client_compose.yml
Practical Examples¶
Edit server configuration in your editor:
python -m clash_tools.wg_docker.cli server config --edit
Print absolute path to the server configuration:
python -m clash_tools.wg_docker.cli server config --path
Reset the server configuration from the packaged template:
python -m clash_tools.wg_docker.cli server config --reset
Render and write the client 5 config to disk:
python -m clash_tools.wg_docker.cli server get-client-config 5 > ~/client5-wg0.conf
Troubleshooting¶
wgmissing: Install WireGuard tools (e.g.,apt install wireguard) to enable key generationDocker issues: Verify Docker service and compose functionality
Port collision: Ensure
listen_portand any forwardedserver_portvalues are not already used on the hostFirewall: Confirm that host firewall permits UDP
listen_portand any forwarded TCP/UDP portsLogs: Use
docker compose -f $(python -m clash_tools.wg_docker.cli server config --path | sed 's/server_config.yml/server_compose.yml/') logs | catto inspect runtime logs
Security Notes¶
Keep
wg_keys.jsonsecured; it contains private keysReview
excludedipsandallowedipsto avoid unintentionally leaking trafficValidate
server_ipand exposed ports before deploying to the public Internet