nostr-vpn · git:20261026.795d96b · 2026-10-26 · sha256 78ac00e7aa353893
nostr-vpn git:20261026.795d96bA
Immutable. This exact content never changes and is served at /api/v1/blob/78ac00e7aa353893.
--- name: nostr-vpn description: Connect an authorized machine to a Nostr VPN private mesh, review device join requests, and verify access with the nvpn CLI. Use for account-free private networking between agent hosts, people, and servers. --- # Nostr VPN Use the `nvpn` CLI for private networking without a VPN provider account. Every device retains its own identity; network membership still needs an administrator's approval. This workflow does not require paid exits. ## Establish the execution context - Run `nvpn --version`, `nvpn join-requests --help`, and `nvpn join-request --help`. CLI approval and JSON join-request output are currently source-only and have not yet shipped in a release. Install a matching binary from https://github.com/mmalmi/nostr-vpn/releases/latest or use `cargo install nvpn`. Check the release's supported architecture. - Choose an explicit, persistent absolute config path and pass `--config` on every command, including elevated ones. Reuse a designated profile; never overwrite an existing one with `init --force`. - A Linux tunnel needs network privileges, `/dev/net/tun`, and `iproute2`; containers need `NET_ADMIN` and the TUN device. macOS/Windows need elevated platform networking setup. A cloud terminal or plugin does not confer this access. If unavailable, report that specific limitation and use an authorized machine with those capabilities. - Persist config and key sidecars privately. Give separate devices separate keys. Do not print private keys, copy the admin identity to a joining device, or put join links into public output. ## Create or join On a new admin host, run `nvpn init --config "$NVPN_CONFIG"`, then use the printed public `nostr_pubkey` with `nvpn set --config "$NVPN_CONFIG" --device "$ADMIN_DEVICE_ID"`. Start it with `nvpn start --config "$NVPN_CONFIG" --daemon --connect`. On the joining host, initialize its own config and start its daemon the same way, then run `nvpn join-request --config "$NVPN_CONFIG" --json`. The `join_request` field contains the link to share with the intended admin through the user's selected channel. JSON output returns immediately and does not resume a paused daemon. Keep the daemon connected; obtain a fresh link if a macOS/Linux joining daemon restarts. On the admin host, save the received link in a private file and run: ```sh nvpn join-requests inspect --request-file "$REQUEST_FILE" --json ``` Inspection is read-only. Check the returned device ID with the intended joiner; the supplied name alone is not proof. When admission of that device to the config's active network is authorized, run: ```sh nvpn join-requests approve --config "$NVPN_CONFIG" \ --request-file "$REQUEST_FILE" --json ``` This signs the roster, queues delivery, and resumes an already-running paused admin daemon. If it is stopped, start it. `delivery: queued` is not a delivery receipt. Keep both daemons connected until the joiner receives approval. For inbound manual-join requests, use `nvpn join-requests list --config "$NVPN_CONFIG" --json`, then approve exactly the selected pending ID with `join-requests approve --device "$DEVICE_ID"` and the same config. Shared links need not appear in that list. If the installed CLI lacks `join-requests` or `join-request --json`, use the interactive `join-request` and the native admin app's **Devices → Add Join Request**, or build current source with `cargo install --locked --path crates/nostr-vpn-cli` from its checkout. Do not substitute private-key sharing or manual signed-roster edits. ## Verify the requested result Run `nvpn status --config "$NVPN_CONFIG" --json`. Interpret readiness only when `status_source` is `daemon`; config-only readiness is unknown. Use `nvpn ip --config "$NVPN_CONFIG" --peer --json` and `nvpn ping --config "$NVPN_CONFIG" "$PEER_TUNNEL_IP"`, then access the actual service the user requested using its normal authentication. Report queued approval, mesh reachability, DNS, and service access separately when they differ. Avoid changing default routes, selecting paid exits, or spending funds unless that is part of the user's request. Stop only a daemon started for a temporary task with `nvpn stop --config "$NVPN_CONFIG"`; preserve existing services. Detailed guide: https://github.com/mmalmi/nostr-vpn/blob/master/docs/agents.md