Portainer Templates logo

Portainer Templates

nord-vpn nord-vpn

Container

Other

This is an OpenVPN client docker container that uses recommended NordVPN server. It makes routing containers traffic through OpenVPN easy.

Image details

Pulls: 3.3M
Architecture: amd64, arm64, arm/v7, arm/v6, 386, ppc64le, s390x, riscv64
Image size: 15 MB
Latest: 7.2.0
User: azinchen
Created: May 06, 2018
Updated: 4 days ago
Status: active

Source details

Stars: 125
Forks: 19
Language: Shell
License: AGPL-3.0
Updated: 4 days ago

Configuration

Type
Container
Platform
linux
Image
azinchen/nordvpn:latest
Privileged
Yes
Ports
8080:80/tcp
Env vars
[email protected]PASS=passwordCOUNTRY=Spain;Hong Kong;IE;131GROUP=Standard VPN serversRANDOM_TOP=10RECREATE_VPN_CRON=5 */3 * * *CHECK_CONNECTION_URL=https://www.google.comNETWORK=192.168.1.0/24;192.168.2.0/24OPENVPN_OPTS=--mute-replay-warnings
Restart
unless-stopped

Template by novaspirit

Notes

Template created by Pi-Hosted Series
Check our Github page: https://github.com/pi-hosted/pi-hosted

Official Webpage: https://github.com/azinchen/nordvpn
Official Docker Documentation: https://hub.docker.com/r/azinchen/nordvpn


Standalone Install

Select an install method, to see config/commands for deploying nord-vpn

Installation method

Install on Portainer

Import all app templates into your Portainer instance, for easy 1-click deploys

  1. Ensure both Docker and Portainer are installed, and up-to-date
  2. Log into your Portainer web UI
  3. Under Settings → App Templates, paste the below URL
  4. Head to Home → App Templates, and the list of apps will show up
  5. Select nord-vpn, fill in any config options, and hit Deploy

Template Import URL

https://raw.githubusercontent.com/Lissy93/portainer-templates/main/templates.json
Show Me demo

More install options in our documentation, or see azinchen/nordvpn for app-specific guidance.

logo

NordVPN OpenVPN Docker Container

!GitHub releasegithub-releasegithub-releases !GitHub release dategithub-releasedategithub-releases !GitHub buildgithub-buildgithub-actions
!GitHub starsgithub-starsgithub-link !GitHub forksgithub-forksgithub-link !Open issuesgithub-issuesgithub-issues-link !GitHub last commitgithub-lastcommitgithub-link
!Docker pullsdockerhub-pullsdockerhub-link !Docker starsdockerhub-starsdockerhub-link !Docker image sizedockerhub-sizedockerhub-link
!Multi-archmultiarch-badgewiki-platforms
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.

✨ Key Features

  • 🚀 Easy Setup — Route any container's traffic through VPN with --net=container:vpn
  • 🌍 Smart Server Selection — Auto-select servers by country, city, group, or specific hostname (detailswiki-server)
  • ⚖️ Load Balancing — Intelligent sorting by server load when multiple locations specified
  • 🔄 Auto-Reconnection — Periodic server switching and health monitoring (detailswiki-reconnect)
  • 🕵️ XOR Obfuscation — Built-in XOR patches disguise OpenVPN traffic to bypass DPI (detailswiki-xor)
  • 🛡️ Kill Switch — Default-deny firewall blocks all traffic when VPN is down (detailswiki-security)
  • 🏠 Local/LAN Access — Allow specific CIDRs with NETWORK=... (detailswiki-network)
  • 🧭 Custom DNS — Resolve through the tunnel; override with DNS=... (detailswiki-custom-dns)
  • 📵 IPv6 Firewall — Built-in chains default to DROP (detailswiki-ipv6)
  • 🧱 iptables Compatibility — Auto-selects nft or legacy backend (detailswiki-firewall)
  • 🚪 VPN Gateway Mode — Route downstream subnets through the tunnel with FORWARD_FROM (detailswiki-gateway)

📖 Full documentation on the Wikiwiki-home — configuration guides, examples, troubleshooting, FAQ, and architecture.

Quick Start

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

Requirements

  • Docker with --cap-add=NET_ADMIN and --device /dev/net/tun
  • NordVPN service credentials or an access token (not regular account credentials)

Getting Service Credentials

  1. Log into your Nord Account Dashboard
  2. Click on NordVPNAdvanced SettingsSet up NordVPN manually
  3. Go to the Service credentials tab
  4. Copy the Username and Password shown there

Note: These are different from your regular NordVPN login credentials.

Alternative — access token: instead of copying the service credentials, generate an access token (Nord Account DashboardNordVPNAdvanced SettingsGenerate 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.

Docker Compose Example

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 Composewiki-compose · Docker Runwiki-run

Environment Variables

List values (countries, cities, CIDRs, URLs, IPs) accept ; or , as separators; whitespace around separators is ignored.

Credentials

NordVPN service credentials, set directly or fetched automatically with an access token — see Getting Service Credentials above.
VariableDetails
USERNordVPN service credentials username. Required unless TOKEN is set.
PASSNordVPN service credentials password. Required unless TOKEN is set.
TOKENNordVPN access token; the service credentials are fetched from the NordVPN API at startup. Ignored when USER/PASS are set.

Server Selection

Pick which servers to connect to; filters combine to narrow the pool. See Server Selectionwiki-server.
VariableDetails
COUNTRYFilter by countries: names, codes, IDs, or server hostnames (listnordvpn-countries).
CITYFilter by cities: names, IDs, or server hostnames (listnordvpn-cities).
GROUPFilter by server group (listnordvpn-groups, detailswiki-groups).
RANDOMTOPRandomize top N servers. Default: 0

OpenVPN Connection

Protocol, port, and traffic obfuscation. See Technologieswiki-tech.
VariableDetails
TECHNOLOGYOpenVPN protocol: name, identifier, or ID (listnordvpn-technologies). Default: openvpnudp
PORTForce a specific port for the VPN connection. Must be supported by the server. Default: auto
DNSDNS servers written to resolv.conf; resolution goes through the tunnel (detailswiki-custom-dns). off leaves resolv.conf untouched. Default: server‑pushed resolvers
XORKEYXOR scramble obfuscation key for openvpnxor technologies (detailswiki-xor-key). Default: NordVPN's built-in key
OPENVPNOPTSAdditional OpenVPN parameters (detailswiki-openvpn-opts).

Reconnection & Health Monitoring

Rotate servers on a schedule and verify the tunnel actually works. See Automatic Reconnectionwiki-reconnect.
VariableDetails
RECREATEVPNCRONServer switching schedule (cron). Default: disabled
CHECKCONNECTIONCRONHealth monitoring schedule (cron). Default: disabled
CHECKCONNECTIONURLURLs to test connectivity. Default: https://www.google.com
CHECKCONNECTIONATTEMPTSConnection test retry count. Default: 5
CHECKCONNECTIONATTEMPTINTERVALSeconds between retries. Default: 10
HEALTHCHECKENABLEDEnable the Docker HEALTHCHECK probe (checks tun0 + connectivity via CHECKCONNECTIONURL). When false, the container always reports healthy. Default: false

Local Network & VPN Gateway

Open the kill‑switch firewall for LAN access and downstream routing. See Local Network Accesswiki-network and VPN Gateway Modewiki-gateway.
VariableDetails
NETWORKLAN/inter‑container CIDRs to allow. Default: none
FORWARDFROMDownstream CIDRs allowed to route OUT through the tunnel (gateway mode). Traffic must arrive already SNATed into these nets. Default: none
GATEWAYDNSDNS interception for FORWARDFROM 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 GATEWAYDNSSERVER, reached directly over the uplink — not through the tunnel), off. Default: off
GATEWAYDNSSERVERExternal IPv4 resolver(s) for GATEWAYDNS=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

Advanced

Low‑level settings; the defaults work for most setups.
VariableDetails
NORDVPNAPIIPIPs used for all NordVPN API access (no DNS involved). Default: 104.16.208.203;104.19.159.190
NETWORKDIAGNOSTICENABLEDEnable network diagnostics on connect (detailswiki-diagnostics). Default: false

Issues

If you have any problems with or questions about this image, please contact me through a GitHub issuegithub-issues-link or emailemail-link.
Check the Troubleshootingwiki-troubleshoot and FAQwiki-faq wiki pages first.



Serve nord-vpn on your own domain behind Caddy, Nginx or Traefik. Fill in your domain and copy the result. It's a starting point, some apps need their own base URL or extra headers set too.

Proxying nord-vpn.example.com to http://nord-vpn:80

Add this to your Caddyfile

nord-vpn.example.com {
	reverse_proxy http://nord-vpn:80
}

Check the logs first

Nine times out of ten the logs tell you exactly what went wrong.

  • In Portainer, go to Containers, click the container, then Logs. Or run docker logs nord-vpn
  • Exit codes help too: 137 means killed, usually out of memory. 126 or 127 means the command inside the image is broken.

Port already in use

If deployment fails with "Bind for 0.0.0.0:8080 failed: port is already allocated", something else on your server is using that port.

  • Find what's using it: sudo ss -tlnp | grep :8080
  • Stop the other service, or pick a different host port. In 8080:80 only the left number is yours to change, the right one belongs to the app.

Running but the page won't load

The container is up but nothing appears in your browser.

  • Use your server's real IP: http://your-server-ip:8080. The 0.0.0.0 link Portainer shows isn't a real address.
  • Give it a minute after first deploy, nord-vpn can take a while to initialise.
  • Make sure your firewall allows the port, e.g. sudo ufw allow 8080

Image won't pull

Test the pull directly on the host: docker pull azinchen/nordvpn:latest

  • "manifest unknown" means the tag no longer exists. This template uses latest, so try pinning a specific version instead.
  • "toomanyrequests" is the Docker Hub rate limit. Log in with docker login to raise it.
  • "no space left on device" means a full disk. Reclaim space with docker system prune

"exec format error"

This means the image was built for a different CPU architecture than your server.

  • This image supports: amd64, arm64, arm/v7, arm/v6, 386, ppc64le, s390x, riscv64
  • Check yours with uname -m: x86_64 is amd64, aarch64 is arm64. Raspberry Pi and other ARM boards are the usual culprits.

Container keeps restarting

The unless-stopped restart policy relaunches the app after every crash, so the real error can scroll past.

  • Check the logs right after a restart, the last few lines before it died are the useful ones.
  • Get the exit code with docker inspect nord-vpn --format '{{.State.ExitCode}}'
  • Still stuck? Redeploy once with the restart policy set to no so the failure stays visible.

Data disappears when the container is recreated

This template doesn't define any volumes, so everything nord-vpn saves lives inside the container and is lost on update or recreate.

  • Add a volume mapping for nord-vpn's data folder before storing anything you care about.

Privileged mode

This template runs the container in privileged mode, giving it full access to your host.

  • Only deploy it if you trust the app.
  • If deployment is blocked, your Portainer security settings or hardened host may not allow privileged containers.

Raise an issue

Found something which isn't working as it should? Here's how to report it.

A single container

nord-vpn runs as one container, the simplest kind of app here. Just the one image to pull and nothing else wired up alongside it.

The app image

An image is the app packed up ready to go, everything nord-vpn needs bundled into one download. This template pulls azinchen/nordvpn:latest, which Docker fetches once (about 15 MB) and then starts your own copy from.

Where the image comes from

Docker pulls its images from registries, public libraries of ready-built apps. nord-vpn's comes from Docker Hub, published by azinchen.

Version tags

The bit after the colon in the image name is the version tag. Here it's latest, which always points at the newest build, so a redeploy can bump you to a newer release without you asking. Newest right now is 7.2.0. Pin a specific tag if you would rather stay on one version.

Which machines it runs on

Every image is built for particular CPU types. This one ships for amd64, arm64, arm/v7, arm/v6, 386, ppc64le, s390x, riscv64, so it runs on both regular x86 servers and ARM boards like a Raspberry Pi.

Ports

A port is the door the app answers on. A mapping like 8080:80 means it's reachable on port 8080 of your server, where the left number is yours to change and the right one belongs to the app. Once it's running, open http://your-server-ip:8080 in a browser. It opens:

  • 8080:80, likely the web interface

No stored data

This template doesn't mount any storage, so whatever nord-vpn writes stays inside the container and is wiped if it's recreated or updated. That's fine for something stateless, but add a volume before trusting it with anything you want to keep.

Environment variables

Environment variables are the settings you hand over when you deploy, things like a password or a timezone. nord-vpn takes 9 of them, all with defaults you can leave alone or tweak:

  • USER, defaults to [email protected]. NordVPN user
  • PASS, defaults to password. NordVPN password
  • COUNTRY, defaults to Spain;Hong Kong;IE;131. Countries to connect to (see webpage readme)
  • GROUP, defaults to Standard VPN servers. Group name filter to which to connect to
  • RANDOM_TOP, defaults to 10. Range of servers to pick from the top
  • RECREATE_VPN_CRON, defaults to 5 */3 * * *. Define when to look again for new defined servers
  • CHECK_CONNECTION_URL, defaults to https://www.google.com. URL to check internet connection is working to
  • NETWORK, defaults to 192.168.1.0/24;192.168.2.0/24. Subnet to define network access (read Local Network access to services connecting to the internet through the VPN readme to get the right subnet!)
  • OPENVPN_OPTS, defaults to --mute-replay-warnings. Used to pass extra parameters to openvpn

Restart policy

The restart policy here is unless-stopped, so Docker restarts nord-vpn after a crash or reboot, but leaves it off when you stop it on purpose. You can change this on the deploy screen. The choices are no (never restart), on-failure (only after a crash), unless-stopped (restart unless you stop it), and always (bring it back no matter what).

Networking

Nothing custom is set, so nord-vpn sits on Docker's default bridge network: its own private space that reaches the outside world only through the ports it publishes.

Container name

Once it's deployed, Portainer names the container nord-vpn. That's what you'll spot in the containers list and use in commands like docker logs nord-vpn.

Privileged mode

This template runs nord-vpn in privileged mode, which gives it nearly as much access to your server as the system itself. Some apps genuinely need it to reach hardware or manage the host, so it's one to run only if you trust the source.

Platform

The platform is linux, the kind of system the container is built to run on. Docker and Portainer handle this on a normal Linux server.

Open source license

nord-vpn is open source, released under the AGPL-3.0 license. In plain terms the code is out in the open, so you're free to run it and change it to fit what you need.

Portainer app templates

Zooming out, this whole page comes from a Portainer app template: a short recipe telling Portainer how to set nord-vpn up. Add the template list to Portainer once, then deploying nord-vpn is a click rather than a wall of config.