OpenVPN client docker container that routes other containers' traffic through NordVPN servers automatically.
Prefer WireGuard? This has a sibling project, azinchen/nordvpn-wg — the same auto-routing NordVPN container over WireGuard (NordLynx). Both share the same configuration model and feature set.
--net=container:vpnNETWORK=... (details)DNS=... (details)FORWARD_FROM (details)📖 Full documentation on the Wiki — configuration guides, examples, troubleshooting, FAQ, and architecture.
docker run -d --cap-add=NET_ADMIN --device /dev/net/tun --name vpn \
-e USER=service_username -e PASS=service_password \
azinchen/nordvpn
Route other containers through VPN:
docker run --net=container:vpn -d your/application
Also available from GitHub Container Registry: ghcr.io/azinchen/nordvpn
--cap-add=NET_ADMIN and --device /dev/net/tunNote: These are different from your regular NordVPN login credentials.
Alternative — access token: instead of copying the service credentials, generate an access token (Nord Account Dashboard → NordVPN → Advanced Settings → Generate new token) and pass it as TOKEN; the container then fetches the service credentials from the NordVPN API at startup. If USER/PASS are also set, they take priority over the token.
services:
vpn:
image: azinchen/nordvpn:latest
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
environment:
- USER=service_username
- PASS=service_password
# - TOKEN=access_token # alternative to USER/PASS
- 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
List values (countries, cities, CIDRs, URLs, IPs) accept
;or,as separators; whitespace around separators is ignored.
NordVPN service credentials, set directly or fetched automatically with an access token — see Getting Service Credentials above.
| Variable | Details |
|---|---|
| USER | NordVPN service credentials username. Required unless TOKEN is set. |
| PASS | NordVPN service credentials password. Required unless TOKEN is set. |
| TOKEN | NordVPN access token; the service credentials are fetched from the NordVPN API at startup. Ignored when USER/PASS are set. |
Pick which servers to connect to; filters combine to narrow the pool. See Server Selection.
| Variable | Details |
|---|---|
| COUNTRY | Filter by countries: names, codes, IDs, or server hostnames (list). |
| CITY | Filter by cities: names, IDs, or server hostnames (list). |
| GROUP | Filter by server group (list, details). |
| RANDOM_TOP | Randomize top N servers. Default: 0 |
Protocol, port, and traffic obfuscation. See Technologies.
| Variable | Details |
|---|---|
| TECHNOLOGY | OpenVPN protocol: name, identifier, or ID (list). Default: openvpn_udp |
| PORT | Force a specific port for the VPN connection. Must be supported by the server. Default: auto |
| DNS | DNS servers written to resolv.conf; resolution goes through the tunnel (details). off leaves resolv.conf untouched. Default: server‑pushed resolvers |
| XOR_KEY | XOR scramble obfuscation key for openvpn_xor_* technologies (details). Default: NordVPN's built-in key |
| OPENVPN_OPTS | Additional OpenVPN parameters (details). |
Rotate servers on a schedule and verify the tunnel actually works. See Automatic Reconnection.
| Variable | Details |
|---|---|
| RECREATE_VPN_CRON | Server switching schedule (cron). Default: disabled |
| CHECK_CONNECTION_CRON | Health monitoring schedule (cron). Default: disabled |
| CHECK_CONNECTION_URL | URLs to test connectivity. Default: https://www.google.com |
| CHECK_CONNECTION_ATTEMPTS | Connection test retry count. Default: 5 |
| CHECK_CONNECTION_ATTEMPT_INTERVAL | Seconds between retries. Default: 10 |
| HEALTHCHECK_ENABLED | Enable the Docker HEALTHCHECK probe (checks tun0 + connectivity via CHECK_CONNECTION_URL). When false, the container always reports healthy. Default: false |
Open the kill‑switch firewall for LAN access and downstream routing. See Local Network Access and VPN Gateway Mode.
| Variable | Details |
|---|---|
| NETWORK | LAN/inter‑container CIDRs to allow. Default: none |
| FORWARD_FROM | Downstream CIDRs allowed to route OUT through the tunnel (gateway mode). Traffic must arrive already SNATed into these nets. Default: none |
| GATEWAY_DNS | DNS interception for FORWARD_FROM clients: redirect (DNAT port 53 to the tunnel resolvers — server‑pushed, or DNS when set), local (DNAT port 53 to this container, for a co‑located resolver such as AdGuard Home), forward (DNAT port 53 to GATEWAY_DNS_SERVER, reached directly over the uplink — not through the tunnel), off. Default: off |
| GATEWAY_DNS_SERVER | External IPv4 resolver(s) for GATEWAY_DNS=forward (e.g. an AdGuard Home on your LAN). With a list, the first resolver answering a DNS probe at startup is used. Default: none |
Low‑level settings; the defaults work for most setups.
| Variable | Details |
|---|---|
| NORDVPNAPI_IP | IPs used for all NordVPN API access (no DNS involved). Default: 104.16.208.203;104.19.159.190 |
| NETWORK_DIAGNOSTIC_ENABLED | Enable network diagnostics on connect (details). Default: false |
If you have any problems with or questions about this image, please contact me through a GitHub issue or email.
Check the Troubleshooting and FAQ wiki pages first.
Content type
Image
Digest
sha256:4696c50ff…
Size
15 MB
Last updated
about 24 hours ago
docker pull azinchen/nordvpn