Sign inSign up

azinchen/nordvpn-wg

By azinchen

•Updated 9 days ago

NordVPN WireGuard (NordLynx) client in Docker: fail-closed kill switch, gateway mode, token auth

Image
0

10K+

azinchen/nordvpn-wg repository overview

⁠NordVPN WireGuard Docker Container

GitHub release GitHub release date GitHub build
GitHub stars GitHub forks Open issues GitHub last commit
Docker pulls Docker stars Docker image size
Multi-arch

WireGuard (NordLynx) client docker container that routes other containers' traffic through NordVPN servers automatically.

Prefer OpenVPN? This has a sibling project, azinchen/nordvpn⁠ — the same auto-routing NordVPN container over OpenVPN (including XOR traffic obfuscation). Both share the same configuration model and feature set.

⁠✨ Key Features

  • 🚀 Easy Setup — Route any container's traffic through VPN with --net=container:vpn
  • ⚡ NordLynx (WireGuard) — Fast, modern tunnel to NordVPN's WireGuard servers
  • 🔑 Access Token — Pass TOKEN and the container fetches your WireGuard key itself (details⁠)
  • 🌍 Server Selection — Auto-select servers by country, city, group, or specific hostname (details⁠)
  • ⚖️ Load Balancing — Sorts by server load when multiple locations are given (details⁠)
  • 🔄 Automatic Reconnection — Periodic server switching and health monitoring (details⁠)
  • 🛡️ Kill Switch — Default-deny firewall blocks all traffic when VPN is down (details⁠)
  • 🏠 Local Network Access — Allow specific CIDRs with NETWORK=... (details⁠)
  • 🧭 Custom DNS — Resolve through the tunnel; override with DNS=... (details⁠)
  • 📵 IPv6 Configuration — Built-in chains default to DROP (details⁠)
  • 🧱 Firewall Backends — Auto-selects nft or legacy backend, binds wg-quick to it (details⁠)
  • 🧬 Userspace Fallback — wireguard-go when the kernel lacks WireGuard (details⁠)
  • 🚪 VPN Gateway Mode — Route downstream subnets through the tunnel with FORWARD_FROM (details⁠)
  • 🪜 TTL Tuning — TTL_SET / TTL_INC hide cascade hops from client traceroutes (details⁠)
  • 🩺 Docker Health Status — Opt-in HEALTHCHECK reports tunnel state to Docker (details⁠)
  • 🔎 Network Diagnostics — Built-in network diagnostic tool and status.json status file (details⁠)

📖 Full documentation on the Wiki⁠ — configuration guides, examples, troubleshooting, FAQ, and architecture.


⁠🚀 Quick Start

docker run -d --name vpn \
           --cap-add=NET_ADMIN \
           --sysctl net.ipv4.conf.all.src_valid_mark=1 \
           -e TOKEN=your_nordvpn_token_here \
           azinchen/nordvpn-wg

Route other containers through VPN:

docker run --net=container:vpn -d your/application

Also available from GitHub Container Registry: ghcr.io/azinchen/nordvpn-wg

⁠Getting a Token
  1. Log into your Nord Account Dashboard⁠
  2. Click NordVPN → Manual setup and complete verification
  3. Generate a new access token and copy it
  4. Pass it as TOKEN — the container reads your NordLynx (WireGuard) key from the NordVPN API on every connect

Note: The token is different from your regular NordVPN login. It is used only to fetch your WireGuard key; the key lives only in the container-private WireGuard config (root-owned, mode 0600), is removed when the service stops, and is re-fetched on every connect — it is never logged and never stored in the image or a volume. See the wiki⁠ for the API one-liner if you prefer to inspect it yourself.

⁠🐳 Docker Compose Example

services:
  vpn:
    image: azinchen/nordvpn-wg:latest
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    environment:
      - TOKEN=your_nordvpn_token_here
      - COUNTRY=United States;CA
      - RANDOM_TOP=10
      - RECREATE_VPN_CRON=0 */6 * * *
      - NETWORK=192.168.1.0/24
    ports:
      - "8080:80"                  # host:container — use your app's listening port
    restart: unless-stopped

  app:
    image: nginx:alpine
    network_mode: "service:vpn"
    depends_on:
      - vpn
    restart: unless-stopped

More examples: Docker Compose⁠ · Docker Run⁠

⁠⚙️ Environment Variables

Grouped by feature; every variable is one line here — the linked wiki pages have the full descriptions. List values (countries, cities, CIDRs, URLs, IPs) accept ; or , as separators; whitespace around separators is ignored.

⁠Credentials — details⁠
VariableDefaultDescription
TOKEN— (required)NordVPN access token; your WireGuard key is fetched from the NordVPN API on every connect (how to get one⁠).
⁠Server selection — details⁠
VariableDefaultDescription
COUNTRY—Countries to pick servers from: names, codes, IDs, or specific server hostnames (list⁠).
CITY—Cities: names, IDs, or specific server hostnames (list⁠).
GROUP—Server group, e.g. legacy_p2p or legacy_double_vpn (list⁠, details⁠).
RANDOM_TOP0Shuffle the top N servers of the filtered pool before picking one.
⁠DNS — details⁠
VariableDefaultDescription
DNS103.86.96.100;103.86.99.100Resolvers written to resolv.conf after the tunnel comes up; resolution goes through the tunnel.
⁠Reconnection and health — details⁠
VariableDefaultDescription
RECREATE_VPN_CRON(disabled)Cron schedule for switching to a new server, e.g. 0 */6 * * *.
CHECK_CONNECTION_CRON(disabled)Cron schedule for the connectivity check that reconnects on failure.
CHECK_CONNECTION_URLhttps://www.google.comURL(s) probed through the tunnel by the check and by the Docker HEALTHCHECK.
CHECK_CONNECTION_ATTEMPTS5Failed attempts before the check declares the tunnel dead and reconnects.
CHECK_CONNECTION_ATTEMPT_INTERVAL10Seconds between attempts.
HEALTHCHECK_ENABLEDfalsetrue = the Docker HEALTHCHECK probes wg0 and CHECK_CONNECTION_URL instead of always reporting healthy (details⁠).
⁠Local network access — details⁠
VariableDefaultDescription
NETWORK—LAN / inter-container IPv4 CIDRs allowed to bypass the tunnel (routes + firewall), e.g. 192.168.1.0/24.
⁠Gateway mode — details⁠
VariableDefaultDescription
FORWARD_FROM—Downstream IPv4 CIDRs allowed to route out through the tunnel; traffic must arrive already SNATed into these nets.
GATEWAY_DNSoffClient DNS interception for FORWARD_FROM sources: redirect (the DNS resolvers, through the tunnel) | local (co-located resolver) | forward (GATEWAY_DNS_SERVER) | off (details⁠).
GATEWAY_DNS_SERVER—External IPv4 resolver(s) for GATEWAY_DNS=forward, reached directly over the uplink, not through the tunnel; the first one answering a probe at startup is used.
TTL_SET(unset)Rewrite the TTL of traffic leaving through the tunnel (1–255, e.g. 64); hides every hop behind this container from client traceroutes (details⁠).
TTL_INC(unset)Add to the TTL of traffic arriving on eth0 (1–255, e.g. 1) so this container disappears from client traceroutes; needs FORWARD_FROM (details⁠).
⁠Diagnostics and advanced
VariableDefaultDescription
NETWORK_DIAGNOSTIC_ENABLEDfalseRun the built-in network diagnostic after every connect (details⁠).
NORDVPNAPI_IP104.16.208.203;104.19.159.190IPs used for all NordVPN API access (no DNS involved); each also gets a host route out eth0 so the API stays reachable with the tunnel down.
ALLOW_MISSING_IPTABLES_RULESfalseTolerate failures applying wg-quick's anti-leak iptables rules on kernels lacking the netfilter modules (e.g. Synology DSM); the container's own kill switch stays active (details⁠).

⁠📋 Runtime Requirements

  • --cap-add=NET_ADMIN and --sysctl net.ipv4.conf.all.src_valid_mark=1 (or privileged: true) — see Permissions⁠
  • a kernel with WireGuard support (5.6+ built in, or the wireguard module); without it the container falls back to userspace wireguard-go, which additionally needs --device /dev/net/tun and is slower (details⁠)
  • a NordVPN access token, not your regular account login — see Getting a Token⁠
  • a kernel with iptables support; the nft or legacy backend is picked automatically (details⁠)
  • for gateway mode: net.ipv4.ip_forward=1 on this container and on the downstream one (details⁠)

⁠🐛 Issues

If you have any problems with or questions about this image, please open a GitHub issue⁠.

Check the Troubleshooting⁠ and FAQ⁠ wiki pages first. For how the container works under the hood, see Architecture and Internals⁠.

⁠📄 License

AGPL-3.0⁠

Tag summary

Content type

Image

Digest

sha256:860b8771e…

Size

16.2 MB

Last updated

9 days ago

docker pull azinchen/nordvpn-wg