8.8 KiB
nordvpn-client
Cross-platform NordVPN lifecycle skill for macOS and Linux.
Overview
nordvpn-client is the operator-facing VPN control skill for OpenClaw. It can:
- detect whether the host is ready for NordVPN automation
- install or bootstrap the required backend
- validate auth
- connect to a target country or city
- verify the public exit location
- disconnect and restore normal local networking state
The skill uses different backends by platform:
- Linux: official
nordvpnCLI - macOS: NordLynx/WireGuard with
wireguard-goandwireguard-tools
Commands
node skills/nordvpn-client/scripts/nordvpn-client.js status
node skills/nordvpn-client/scripts/nordvpn-client.js install
node skills/nordvpn-client/scripts/nordvpn-client.js login
node skills/nordvpn-client/scripts/nordvpn-client.js verify
node skills/nordvpn-client/scripts/nordvpn-client.js verify --country "Italy"
node skills/nordvpn-client/scripts/nordvpn-client.js verify --country "Italy" --city "Milan"
node skills/nordvpn-client/scripts/nordvpn-client.js connect --country "Italy"
node skills/nordvpn-client/scripts/nordvpn-client.js connect --city "Tokyo"
node skills/nordvpn-client/scripts/nordvpn-client.js connect --country "Japan" --city "Tokyo"
node skills/nordvpn-client/scripts/nordvpn-client.js disconnect
node skills/nordvpn-client/scripts/nordvpn-client.js status --debug
Credentials
Supported inputs:
NORDVPN_TOKENNORDVPN_TOKEN_FILENORDVPN_USERNAMENORDVPN_PASSWORDNORDVPN_PASSWORD_FILE
Default OpenClaw credential paths:
- token:
~/.openclaw/workspace/.clawdbot/credentials/nordvpn/token.txt - password:
~/.openclaw/workspace/.clawdbot/credentials/nordvpn/password.txt
Recommended setup on macOS is a token file with strict permissions:
mkdir -p ~/.openclaw/workspace/.clawdbot/credentials/nordvpn
chmod 700 ~/.openclaw/workspace/.clawdbot/credentials/nordvpn
printf '%s\n' '<your-nordvpn-token>' > ~/.openclaw/workspace/.clawdbot/credentials/nordvpn/token.txt
chmod 600 ~/.openclaw/workspace/.clawdbot/credentials/nordvpn/token.txt
Do not commit secrets into the repo or the skill docs.
Platform Backends
macOS
Current macOS backend:
- NordLynx/WireGuard
wireguard-gowireguard-tools- NordVPN DNS in the generated WireGuard config:
103.86.96.100103.86.99.100
Important behavior:
NordVPN.appmay remain installed, but the automated backend does not reuse app login state.- The skill automatically suspends Tailscale before connect if Tailscale is active.
- The skill resumes Tailscale after disconnect, or after a failed connect, if it stopped it.
- The Homebrew NordVPN app does not need to be uninstalled.
Linux
Current Linux backend:
- official
nordvpnCLI - official NordVPN installer
- token login through
nordvpn login --token ...
Install / Bootstrap
macOS
Bootstrap the automation backend:
node skills/nordvpn-client/scripts/nordvpn-client.js install
Equivalent Homebrew command:
brew install wireguard-go wireguard-tools
What install does on macOS:
- checks whether
wireguard-gois present - checks whether
wgandwg-quickare present - installs missing packages through Homebrew
Linux
node skills/nordvpn-client/scripts/nordvpn-client.js install
What install does on Linux:
- downloads NordVPN’s official installer script
- runs it
- leaves subsequent login/connect to the official
nordvpnCLI
macOS sudoers Setup
Automated macOS connect/disconnect requires passwordless sudo for the helper script that invokes wg-quick.
Installed OpenClaw helper path:
/Users/stefano/.openclaw/workspace/skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh
Edit sudoers safely:
sudo visudo
Add this exact rule:
stefano ALL=(root) NOPASSWD: /Users/stefano/.openclaw/workspace/skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh probe, /Users/stefano/.openclaw/workspace/skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh up, /Users/stefano/.openclaw/workspace/skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh down
If you run the repo copy directly instead of the installed OpenClaw skill, adjust the helper path accordingly.
Common Flows
Status
node skills/nordvpn-client/scripts/nordvpn-client.js status
Use this first to answer:
- is the correct backend available?
- is the token visible?
- is
sudoReadytrue? - is the machine currently connected?
Login
node skills/nordvpn-client/scripts/nordvpn-client.js login
On macOS this validates the token and populates the local auth cache. It does not connect the VPN.
Connect
Country:
node skills/nordvpn-client/scripts/nordvpn-client.js connect --country "Germany"
City:
node skills/nordvpn-client/scripts/nordvpn-client.js connect --country "Japan" --city "Tokyo"
Expected macOS behavior:
- stop Tailscale if active
- select a NordVPN server for the target
- bring up the WireGuard tunnel
- verify the public exit location
- return JSON describing the chosen server and final verified location
Verify
node skills/nordvpn-client/scripts/nordvpn-client.js verify --country "Germany"
Use this after connect if you want an explicit location check without changing VPN state.
Disconnect
node skills/nordvpn-client/scripts/nordvpn-client.js disconnect
Expected macOS behavior:
- attempt
wg-quick downwhenever there is active or residual NordVPN WireGuard state - remove stale local NordVPN state files after teardown
- resume Tailscale if the skill had suspended it
Output Model
Normal JSON is redacted by default.
Redacted fields in normal mode:
cliPathappPathwireguard.configPathwireguard.helperPathwireguard.authCache.tokenSource
Operational fields preserved in normal mode:
connectedwireguard.activewireguard.endpointrequestedTargetverification- public IP and location
For deeper troubleshooting, use:
node skills/nordvpn-client/scripts/nordvpn-client.js status --debug
--debug keeps the internal local paths and other low-level metadata in the JSON output.
Troubleshooting
Invalid authorization header
Meaning:
- the token file was found
- the token value is not valid for NordVPN’s API
Actions:
- generate a fresh NordVPN access token
- replace the contents of
~/.openclaw/workspace/.clawdbot/credentials/nordvpn/token.txt - run:
node skills/nordvpn-client/scripts/nordvpn-client.js login
sudoReady: false
Meaning:
- the helper script is present
- the agent cannot run
wg-quicknon-interactively
Actions:
- add the
visudorule shown above - rerun:
node skills/nordvpn-client/scripts/nordvpn-client.js status
Expected:
wireguard.sudoReady: true
WireGuard tools missing
Meaning:
- macOS backend is selected
wireguard-go,wg, orwg-quickis missing
Actions:
node skills/nordvpn-client/scripts/nordvpn-client.js install
or:
brew install wireguard-go wireguard-tools
Tailscale interaction
Expected behavior on macOS:
- Tailscale is suspended before the NordVPN connect
- Tailscale is resumed after disconnect or failed connect
If a connect succeeds but later traffic is wrong, check:
node skills/nordvpn-client/scripts/nordvpn-client.js status
/opt/homebrew/bin/tailscale status --json
Look for:
connected: trueand a foreign exit IP while NordVPN is upconnected: falseand Texas/Garland IP after disconnect
Status says disconnected after a verified connect
This was a previous macOS false-negative path and is now normalized in the connect response.
Current expectation:
- if
connectverifies the target location successfully - the returned
statesnapshot should also show:connected: truewireguard.active: true
If that regresses, capture:
connectJSONverifyJSONstatus --debugJSON
Disconnect says “no active connection” but traffic is still foreign
The current macOS disconnect path now treats residual WireGuard state as sufficient reason to attempt teardown.
Safe operator check:
node skills/nordvpn-client/scripts/nordvpn-client.js disconnect
node skills/nordvpn-client/scripts/nordvpn-client.js verify
Expected after a good disconnect:
- Texas/Garland public IP again
wireguard.configPath: nullin normal status outputwireguard.lastConnection: null
If that regresses, capture:
disconnectJSONverifyJSONstatus --debugJSON
Recommended Agent Workflow
For VPN-routed work:
statusinstallif backend tooling is missingloginif token validation has not happened yetconnect --country ...orconnect --country ... --city ...verify- run the follow-up skill such as
web-automation disconnectverifyagain if you need proof the machine returned to the normal exit path