# 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 `nordvpn` CLI - macOS: NordLynx/WireGuard with `wireguard-go` and `wireguard-tools` ## Commands ```bash 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_TOKEN` - `NORDVPN_TOKEN_FILE` - `NORDVPN_USERNAME` - `NORDVPN_PASSWORD` - `NORDVPN_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: ```bash mkdir -p ~/.openclaw/workspace/.clawdbot/credentials/nordvpn chmod 700 ~/.openclaw/workspace/.clawdbot/credentials/nordvpn printf '%s\n' '' > ~/.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-go` - `wireguard-tools` - NordVPN DNS in the generated WireGuard config: - `103.86.96.100` - `103.86.99.100` Important behavior: - `NordVPN.app` may 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 `nordvpn` CLI - official NordVPN installer - token login through `nordvpn login --token ...` ## Install / Bootstrap ### macOS Bootstrap the automation backend: ```bash node skills/nordvpn-client/scripts/nordvpn-client.js install ``` Equivalent Homebrew command: ```bash brew install wireguard-go wireguard-tools ``` What `install` does on macOS: - checks whether `wireguard-go` is present - checks whether `wg` and `wg-quick` are present - installs missing packages through Homebrew ### Linux ```bash 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 `nordvpn` CLI ## macOS sudoers Setup Automated macOS connect/disconnect requires passwordless `sudo` for the helper script that invokes `wg-quick`. Installed OpenClaw helper path: ```text /Users/stefano/.openclaw/workspace/skills/nordvpn-client/scripts/nordvpn-wireguard-helper.sh ``` Edit sudoers safely: ```bash sudo visudo ``` Add this exact rule: ```sudoers 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 ```bash node skills/nordvpn-client/scripts/nordvpn-client.js status ``` Use this first to answer: - is the correct backend available? - is the token visible? - is `sudoReady` true? - is the machine currently connected? ### Login ```bash 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: ```bash node skills/nordvpn-client/scripts/nordvpn-client.js connect --country "Germany" ``` City: ```bash 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 ```bash 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 ```bash node skills/nordvpn-client/scripts/nordvpn-client.js disconnect ``` Expected macOS behavior: - attempt `wg-quick down` whenever 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: - `cliPath` - `appPath` - `wireguard.configPath` - `wireguard.helperPath` - `wireguard.authCache.tokenSource` Operational fields preserved in normal mode: - `connected` - `wireguard.active` - `wireguard.endpoint` - `requestedTarget` - `verification` - public IP and location For deeper troubleshooting, use: ```bash 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: 1. generate a fresh NordVPN access token 2. replace the contents of `~/.openclaw/workspace/.clawdbot/credentials/nordvpn/token.txt` 3. run: ```bash node skills/nordvpn-client/scripts/nordvpn-client.js login ``` ### `sudoReady: false` Meaning: - the helper script is present - the agent cannot run `wg-quick` non-interactively Actions: 1. add the `visudo` rule shown above 2. rerun: ```bash node skills/nordvpn-client/scripts/nordvpn-client.js status ``` Expected: - `wireguard.sudoReady: true` ### WireGuard tools missing Meaning: - macOS backend is selected - `wireguard-go`, `wg`, or `wg-quick` is missing Actions: ```bash node skills/nordvpn-client/scripts/nordvpn-client.js install ``` or: ```bash 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: ```bash node skills/nordvpn-client/scripts/nordvpn-client.js status /opt/homebrew/bin/tailscale status --json ``` Look for: - `connected: true` and a foreign exit IP while NordVPN is up - `connected: false` and 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 `connect` verifies the target location successfully - the returned `state` snapshot should also show: - `connected: true` - `wireguard.active: true` If that regresses, capture: - `connect` JSON - `verify` JSON - `status --debug` JSON ### 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: ```bash 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: null` in normal status output - `wireguard.lastConnection: null` If that regresses, capture: - `disconnect` JSON - `verify` JSON - `status --debug` JSON ## Recommended Agent Workflow For VPN-routed work: 1. `status` 2. `install` if backend tooling is missing 3. `login` if token validation has not happened yet 4. `connect --country ...` or `connect --country ... --city ...` 5. `verify` 6. run the follow-up skill such as `web-automation` 7. `disconnect` 8. `verify` again if you need proof the machine returned to the normal exit path