Skip to content

About

Run NymVPN in Docker and expose it as a local SOCKS5 proxy for app-selective routing.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

docker-nymvpn-socks5

Run NymVPN in Docker and expose it as a local SOCKS5 proxy on 127.0.0.1:1090.

This gives applications an opt-in routing path: applications that support SOCKS5 can use NymVPN, while the rest of the host keeps using the normal network. It is not kernel-level split tunneling, but it is a practical split-tunneling-like workflow for proxy-aware applications.

Lineage

This repository is an evolution of the earlier Dockerized NymVPN gist:

https://gist.github.com/cs224/1d01536c89f2fb0419674fc9152a977c

That gist was connected to the blog post:

https://weisser-zwerg.dev/posts/digital-civil-rights-networking-nym-node-operator-guide-2026/

The old gist followed an older NymVPN CLI/daemon behavior. This repository was originally updated and tested on 2026-04-23 with:

nym-vpnc 1.28.0
nym-vpnd Build Version: 1.28.0
nym-vpnd Commit SHA: 882cc06d9988459937d77fa16c63cd0749819ce1

The image now defaults to matching nym-vpnc and nym-vpnd packages at 2026.11.3. Override NYMVPN_VERSION at build time only after validating a new release:

NYMVPN_VERSION=2026.11.3 docker compose build --pull

The packages come from the current official repository bootstrap at https://apt-ppa.nym.com/nym-repo-setup.deb.

How It Works

The Compose stack has three services:

  • nymvpn1 runs nym-vpnd, connects to NymVPN, and owns the network namespace.
  • ssserver1 runs a local-only Shadowsocks server inside the nymvpn1 network namespace.
  • sslocal1 exposes a SOCKS5 listener, also inside the nymvpn1 network namespace.

The host only sees:

127.0.0.1:1090 -> sslocal1 -> ssserver1 -> NymVPN tunnel

ssserver1 and sslocal1 use Shadowsocks method none with an empty password intentionally because that hop stays inside the local Docker network namespace. The host port is bound to 127.0.0.1 only. Compose waits for NymVPN's connect --wait to complete before starting either Shadowsocks service.

Why D-Bus And Polkit Are Included

With NymVPN 1.28.0, Linux RPC access from nym-vpnc to nym-vpnd is authenticated through the Polkit action:

com.nymvpn.vpnd.unix-access

Running nym-vpnc as root inside the container is not enough. The container must also provide a system dbus-daemon, polkitd, and a rule allowing the intended container user to access that daemon socket. This repo keeps those pieces inside Docker instead of depending on host D-Bus/Polkit.

Prerequisites

  • Linux host with Docker and Docker Compose.
  • /dev/net/tun available on the host.
  • Docker permissions sufficient for NET_ADMIN, /dev/net/tun, and the configured security_opt entries.
  • A valid NymVPN account mnemonic.

Setup

Create the runtime directories if they do not exist:

mkdir -p config/nymvpn1/{etc,lib,logs}

Create the local secret file from the example:

cp secrets.env.example secrets.env

Edit secrets.env and put the real account mnemonic on one line:

MNEMONIC_SECRET=word1 word2 word3 ... word24

Do not commit secrets.env. It is ignored by .gitignore.

The first successful run imports the mnemonic into persisted NymVPN account state under config/nymvpn1/lib/. Later starts skip account import if persisted account state already exists, but secrets.env should still exist because Compose references it.

Gateway Selection

The Compose file exposes gateway selection in one-line presets. For entry and exit, set either an explicit gateway ID or a country:

environment: { ENTRY_GATEWAY_ID: "${ENTRY_GATEWAY_ID:-DBBCDYsgAAj7g4FLQkSxXZAcdG5m9Hx8vMreqRaX1Yqo}", ENTRY_GATEWAY_COUNTRY: "${ENTRY_GATEWAY_COUNTRY:-}", EXIT_GATEWAY_ID: "${EXIT_GATEWAY_ID:-7DfXy5Ucptc5AbMWL9gHzEJ7f688a5B2eRESw9EZcsP4}", EXIT_GATEWAY_COUNTRY: "${EXIT_GATEWAY_COUNTRY:-}" }
# environment: { ENTRY_GATEWAY_COUNTRY: "${ENTRY_GATEWAY_COUNTRY:-AT}", EXIT_GATEWAY_COUNTRY: "${EXIT_GATEWAY_COUNTRY:-CH}" }
# environment: { ENTRY_GATEWAY_ID: "${ENTRY_GATEWAY_ID:-entry-gateway-id-here}", EXIT_GATEWAY_COUNTRY: "${EXIT_GATEWAY_COUNTRY:-CH}" }

Accepted variables:

  • ENTRY_GATEWAY_ID
  • ENTRY_GATEWAY_COUNTRY
  • EXIT_GATEWAY_ID
  • EXIT_GATEWAY_COUNTRY

Each side must have either an ID or a country. If both are set for the same side, the country takes precedence. The script maps those variables to the NymVPN 2026.11.3 flags --entry-id, --entry-country, --exit-id, and --exit-country.

Keep exactly one preset uncommented. You can also override the same values from the shell or a Compose .env file:

ENTRY_GATEWAY_COUNTRY=AT EXIT_GATEWAY_COUNTRY=CH docker compose up

Run

Build and start:

docker compose build --pull
docker compose up

Or run detached:

docker compose up -d

Check status:

docker compose exec -T nymvpn1 /usr/bin/nym-vpnc status

Test traffic through the local SOCKS5 endpoint:

curl -s --max-time 20 --socks5-hostname 127.0.0.1:1090 https://ifconfig.me/ip

Stop the stack:

docker compose down

Secret And State Hygiene

This repo intentionally does not include real secrets or persisted runtime state.

Ignored local files include:

  • secrets.env
  • Compose .env
  • config/nymvpn1/etc/*
  • config/nymvpn1/lib/*
  • config/nymvpn1/logs/*
  • common key, database, and log file extensions

Treat config/nymvpn1/lib/ as sensitive. It can contain NymVPN account/device state, keys, databases, and identifiers. Treat logs as potentially sensitive as well because they can include gateway, device, or account-related metadata.

Avoid docker compose config when sharing output because it expands secrets.env into the rendered Compose output.

Troubleshooting

If startup fails with:

Authentication is required to access the daemon

then nym-vpnc could not authenticate to nym-vpnd. Check the dbus, polkitd, and vpnd logs under config/nymvpn1/logs/.

If ssserver1 and sslocal1 remain in the Created state, inspect the nymvpn1 logs. Compose deliberately waits for nymvpn1 to become healthy, which happens only after the VPN tunnel connects successfully.

If NymVPN reports firewall/sysctl errors, verify that the nymvpn1 service still has:

cap_add:
  - NET_ADMIN
security_opt:
  - apparmor=unconfined
  - systempaths=unconfined

Those settings are narrower than full Docker privileged: true, but they are needed by the current daemon's tunnel/firewall setup.

About

Run NymVPN in Docker and expose it as a local SOCKS5 proxy for app-selective routing.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages