nostr-vpn
July 21, 2026 ยท View on GitHub
Canonical repository: git.iris.to (
htree://npub1xdhnr9mrv47kkrn95k6cwecearydeh8e895990n3acntwvmgk2dsdeeycm/nostr-vpn). GitHub is a mirror.
nostr-vpn is a Tailscale-style private mesh VPN built around a FIPS-backed data plane. It includes the nvpn CLI/daemon, a shared native app core, and native shells for desktop and mobile platforms.
Downloads
- Latest releases on git.iris.to
- GitHub mirror releases
- CLI from crates.io:
cargo install nvpn - iOS App Store
- iOS TestFlight beta
Release artifacts currently cover native Apple Silicon macOS, Linux x64, Windows x64, Android arm64, StartOS x86_64/aarch64 service packages, and headless CLI archives for Apple Silicon macOS, Windows x64, Linux x86_64, and Linux arm64. Intel macOS is source-only for now.
Quick Start
cargo install nvpn --force
nvpn init
MY_NPUB='<paste nostr_pubkey from nvpn init>'
nvpn set --participant "$MY_NPUB"
nvpn start --daemon --connect
On a new device, generate its signed join request and show it to an admin in a Nostr VPN app:
nvpn init
nvpn join-request
The admin scans or pastes that request. Approval returns an admin-signed roster to the joining device. This signed request is the only join flow.
For the background daemon flow used by desktop apps:
nvpn start --daemon --connect
nvpn status
nvpn stop
For persistent startup:
sudo nvpn service install
nvpn service status
On Windows, run nvpn service install from an elevated shell instead of using sudo.
Native Apps
The native apps share the Rust app-core state/action contract and use platform shells for macOS, Linux, Windows, Android, and iOS.
just build
just run
Use just run-macos or just run-linux when you want a specific desktop target.
What Works Today
- Generates Nostr identity keys automatically
- Enrolls devices through signed join requests and admin-signed roster delivery
- Stores multiple named networks with one active network at a time
- Brings up FIPS private mesh tunnels for private network traffic
- Routes private traffic directly when possible and through FIPS neighbors when direct UDP is blocked
- Supports MagicDNS, authenticated DNS-over-HTTPS for exit routes, route advertisement, exit-node selection, and WireGuard upstream egress
- Exposes native desktop apps, JSON status, network diagnostics, doctor bundles, desktop updates, and Linux-focused Docker e2e coverage
Platform Status
| Platform | Status |
|---|---|
| Apple Silicon macOS | Native SwiftUI/AppKit app, CLI tarball, signed/notarized release artifacts when credentials are configured |
| Linux x64 | Native GTK/libadwaita app, .deb, CLI tarballs, Docker e2e coverage |
| Windows x64 | Native WPF app, installer, CLI zip, WinTun tunnel path |
| Android arm64 | Native app-core UI, signed APK/AAB artifacts when signing is configured, VPN runtime still being hardened |
| iOS | Native SwiftUI app and NetworkExtension target available on the App Store; public TestFlight beta remains available |
| Umbrel / StartOS | Web control panels and service packages |
| Intel macOS | Source-only |
Further Reading
- Protocol: join requests, admin roster sync, and the FIPS mesh data plane
- Experiments: chronological benchmark and reliability log
- Native UI parity matrix: native app rewrite status
- Contributing: maintainer commands and package notes
- Changelog: release history
Maintainer Notes
This section is intentionally compact and command-oriented. Keep user-facing product detail above; keep agent/operator reference material here.
Config Model
nvpn init creates the config and keys automatically. By default, config lives in the OS app config directory:
- Linux:
~/.config/nvpn/config.toml - macOS:
~/Library/Application Support/nvpn/config.toml - Fallback when no config dir is available:
./nvpn.toml
The config contains global app settings, Nostr relay/identity settings, NAT settings, node settings, and a [[networks]] list. Each network has its own stable network_id; only the active network participates in the live runtime.
Validation
Normal Rust gate:
cargo fmt --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
Per-change core/contract verification:
just verify-fast
Managed native preflight and the nightly/release five-platform matrix:
just verify-health
just verify-full
See verification tiers and managed native lab.
Release gate before version bumps and tags:
just release-gate
The gate overlaps its resource-isolated Windows and Docker-build lanes with
host validation, writes each lane to artifacts/release-gate-logs, and reuses
one candidate Docker image across functional and performance checks. NAT and
the kernel/userspace WireGuard fixtures also overlap on isolated subnets.
Roaming, throughput, host-pair, physical-device, and idle-CPU measurements
remain serial so concurrency cannot skew their results.
Useful focused checks:
pnpm --dir web/control-panel check
( cd linux && cargo check )
NVPN_E2E_ROAMING_SCENARIOS=latency ./scripts/e2e-fips-roaming-docker.sh
Run the Windows build from a checkout on the configured Windows dev VM:
dotnet build windows\NostrVpn.Windows\NostrVpn.Windows.csproj -p:EnableWindowsTargeting=true
Packages and E2E
docker compose -f umbrel/docker-compose.local.yml up --build
just e2e-umbrel-web
Focused security regression kit:
just security-regressions
Docker e2e and desktop updater scripts live under scripts. The most common entrypoints are scripts/e2e-docker.sh, scripts/e2e-fips-routed-udp-docker.sh, scripts/e2e-fips-nat-safe-mtu-docker.sh, scripts/e2e-wireguard-exit-docker.sh, and scripts/e2e-update-desktop.sh.
Release
- Move
CHANGELOG.mdfrom## Unreleasedto## X.Y.Z - YYYY-MM-DD. - Bump the root
[workspace.package].versioninCargo.toml. - Run
node scripts/sync-versions.mjsand verify withnode scripts/sync-versions.mjs --check. - Run
just release-gate. - Commit, create
git tag vX.Y.Z, push the tag togithub, and pushmasterto bothgithuband htreeorigin. - Watch
.github/workflows/release.yml.
For local artifact staging, use:
cp .env.release.example .env.release.local
$EDITOR .env.release.local
just release-publish
Workspace Layout
crates/nostr-vpn-cli:nvpnCLI and daemon implementationcrates/nostr-vpn-core: config, FIPS control state, diagnostics, MagicDNS, and NAT helperscrates/nostr-vpn-app-core: native app state/action contract and UniFFI bridgemacos,linux,windows,android,ios: native platform shellsumbrel,startos: packaged service/web-control-panel targetsscripts: build, release, Docker e2e, and desktop updater entrypoints