Files
ihasvpn/docker-compose.host.yml
T
jcoffey 6c006e1d4d WireGuard server with an embedded admin console
Go backend that drives kernel WireGuard over netlink (wireguard-go as the
fallback), nftables NAT with MSS clamping, forwarding and buffer sysctls,
SQLite for peers, users, sessions, traffic history and the audit log.

React console: dashboard with live rates and usage history, peer management
with QR codes and .conf downloads, disconnect, session reset, key rotation,
expiry, client-supplied keys, settings, users with admin and viewer roles,
two-factor authentication with recovery codes, audit log.

Docker image on Alpine with compose files for bridged and host networking,
CI and GHCR publish workflows, performance notes.
2026-09-12 19:56:08 -07:00

38 lines
1.5 KiB
YAML

# WGX on the host network: the fastest way to run it.
#
# With `network_mode: host` the WireGuard socket sits directly on the host's
# interfaces. There is no port mapping, no conntrack entry per client packet
# and no second NAT hop, which is worth a few percent of throughput and a
# little latency on a busy server. The trade-offs: wg0 is created in the
# host's namespace (you will see it in `ip link` and it is removed on
# shutdown), the NAT rules land in the host's nftables as a table named
# `wgx`, and the admin UI listens on the host directly -- so it is bound to
# localhost below. Put a reverse proxy in front of it or set
# WGX_TLS_SELF_SIGNED to reach it from elsewhere.
services:
wgx:
image: ghcr.io/coffey-labs/wgx:latest
container_name: wgx
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
environment:
WGX_ENDPOINT: vpn.example.com
WGX_PORT: "51820"
WGX_SUBNET: 10.8.0.0/24
WGX_DNS: 1.1.1.1, 1.0.0.1
WGX_HTTP_LISTEN: "127.0.0.1:51821"
# In host mode the forwarding sysctls are the host's own; WGX sets
# them itself since it has NET_ADMIN, but if you prefer to own them
# add `net.ipv4.ip_forward = 1` to /etc/sysctl.d/ and turn this off.
# WGX_MANAGE_SYSCTL: "false"
# Pick the interface to masquerade on if auto-detection picks the
# wrong one (it uses the default route).
# WGX_EGRESS_INTERFACE: eth0
volumes:
- wgx-data:/data
volumes:
wgx-data: