Installation Guide
Connect any device to your NetFlux network in under 60 seconds. One command handles everything — WireGuard installation, network join, and systemd service setup.
Quick start
The fastest path from zero to a connected device is three steps:
10.10.0.0/24. You'll get a network ID and join token.curl -fsSL https://api.net-flux.com/install.sh | sudo bash -s -- \ --token YOUR_JOIN_TOKEN \ --network YOUR_NETWORK_ID \ --controller https://api.net-flux.com
✓ NetFlux connected! Virtual IP: 10.10.0.2 Peers: 1 online Planet: Singapore (14ms) # Test connectivity to another device ping 10.10.0.1 PING 10.10.0.1: 56 data bytes 64 bytes from 10.10.0.1: icmp_seq=0 ttl=64 time=18.4 ms
How it works
NetFlux creates a WireGuard virtual network interface (rnet0) on each device and assigns it a private virtual IP (e.g. 10.10.0.x). Devices communicate directly peer-to-peer when possible, or through a relay node when NAT traversal fails.
| Component | What it does |
|---|---|
| Agent | Runs on your device. Creates the WireGuard interface, polls the controller for peers, manages keys. |
| Controller | REST API at api.net-flux.com. Manages networks, assigns IPs, authenticates join tokens. |
| Planet node | UDP rendezvous server. Helps peers find each other's real IP and port. Falls back to relay when P2P fails. |
Requirements
| Requirement | Details |
|---|---|
| OS | Linux kernel 5.6+ (WireGuard built-in), Raspberry Pi OS Bullseye+, Ubuntu 20.04+, Debian 11+ |
| Architecture | x86_64 (AMD64), ARM64, ARMv7 (Raspberry Pi) |
| Root access | Required — the agent creates a kernel network interface |
| Outbound UDP | Port 51820 (WireGuard) and 7447 (planet) — falls back to TCP 443 if blocked |
| Python | 3.8+ (installed automatically if missing) |
| macOS | Supported via WireGuard App — see macOS section |
| Windows | Supported via WSL2 — see Windows section |
Linux / Ubuntu
Works on Ubuntu, Debian, and any distribution with apt. The installer detects your OS, installs WireGuard if needed, and configures a systemd service that starts automatically on boot.
# Run as root or with sudo curl -fsSL https://api.net-flux.com/install.sh | sudo bash -s -- \ --token YOUR_JOIN_TOKEN \ --network YOUR_NETWORK_ID \ --controller https://api.net-flux.com # Expected output: · Detecting OS: Ubuntu 22.04 (x86_64) · Installing WireGuard... · Connecting to nearest planet: Frankfurt (8ms) · Joining network... ✓ Connected! Virtual IP: 10.10.0.2
Manage the service
# Check status systemctl status netflux # View live logs journalctl -u netflux -f # Restart after config change sudo systemctl restart netflux # Uninstall curl -fsSL https://api.net-flux.com/install.sh | sudo bash -s -- --uninstall
Raspberry Pi
Tested on Raspberry Pi 3, 4, and 5 running Raspberry Pi OS (64-bit and 32-bit). The install command is identical — the installer auto-detects ARM architecture.
# Same command as Linux — works on RPi OS Bullseye and Bookworm curl -fsSL https://api.net-flux.com/install.sh | sudo bash -s -- \ --token YOUR_JOIN_TOKEN \ --network YOUR_NETWORK_ID \ --controller https://api.net-flux.com
sudo apt install wireguard first, then run the NetFlux install command.Docker
Run the agent in a Docker container. Requires --privileged and --network host so the container can create the WireGuard interface on the host.
docker run -d \ --name netflux-agent \ --privileged \ --network host \ --restart unless-stopped \ -e NETFLUX_TOKEN=YOUR_JOIN_TOKEN \ -e NETFLUX_NETWORK=YOUR_NETWORK_ID \ -e NETFLUX_CONTROLLER=https://api.net-flux.com \ ghcr.io/alicia-bots/netflux-agent:latest
Docker Compose
# docker-compose.yml services: netflux: image: ghcr.io/alicia-bots/netflux-agent:latest privileged: true network_mode: host restart: unless-stopped environment: - NETFLUX_TOKEN=YOUR_JOIN_TOKEN - NETFLUX_NETWORK=YOUR_NETWORK_ID - NETFLUX_CONTROLLER=https://api.net-flux.com
Windows (WSL2)
Run the Linux agent inside WSL2 (Windows Subsystem for Linux). Requires WSL2 with Ubuntu 22.04.
# In Windows PowerShell (run as Administrator) wsl --install -d Ubuntu-22.04 # Then open WSL Ubuntu and run the standard install command curl -fsSL https://api.net-flux.com/install.sh | sudo bash -s -- \ --token YOUR_JOIN_TOKEN \ --network YOUR_NETWORK_ID \ --controller https://api.net-flux.com
Create a network
You can create networks via the dashboard or the REST API.
Via dashboard
Go to api.net-flux.com → click + New network → enter a name → click Create. The network ID and join token are shown immediately. Save the join token — it's only shown once.
Via API
curl -s -X POST https://api.net-flux.com/api/v1/networks \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "My Network", "ip_pool": "10.10.0.0/24"}' # Response: { "network_id": "c935163e6bac957e", "name": "My Network", "ip_pool": "10.10.0.0/24", "join_token": "5487c2cb89979873..." }
Join tokens
A join token is a one-time secret that authorises a device to join a specific network. Any device with a valid token can join — share tokens carefully.
# Create a new join token for a network curl -s -X POST https://api.net-flux.com/api/v1/networks/NETWORK_ID/tokens \ -H "Authorization: Bearer YOUR_API_KEY" {"join_token": "7a26797531929275..."}
NetFlux CLI — headless Linux servers
The NetFlux CLI lets you connect any Linux server or robot without a web UI. Install it once, then use simple commands to join networks, check status, and manage peers.
Install the CLI
curl -fsSL https://api.net-flux.com/netflux -o /usr/local/bin/netflux && chmod +x /usr/local/bin/netflux
Join a network
Get your network ID and join token from the dashboard, then run:
sudo netflux join YOUR_NETWORK_ID --token YOUR_JOIN_TOKEN # Optional: set a display name for this device sudo netflux join YOUR_NETWORK_ID --token YOUR_JOIN_TOKEN --name "Warehouse Robot 3" # Expected output: · WireGuard found · Joining network abc123... · Starting interface... ╔════════════════════════════════════════╗ ║ NetFlux connected! ║ ╚════════════════════════════════════════╝ Virtual IP: 10.10.0.3 Peers: 2 connected Network: YOUR_NETWORK_ID
Commands
| Command | Description |
|---|---|
| netflux join <id> --token <token> | Join a network. Installs WireGuard if needed, sets up auto-reconnect on boot. |
| netflux status | Show current virtual IP, WireGuard interface status, and connected peers. |
| netflux peers | List all devices currently connected to the same network. |
| netflux update | Fetch the latest peer list from the controller and update WireGuard config. |
| netflux leave | Disconnect from the network and stop all NetFlux services. |
| netflux uninstall | Remove NetFlux completely — WireGuard config, services, and identity files. |
netflux join, the WireGuard interface is registered with systemd so it reconnects automatically on every reboot. The dashboard poller also runs as a systemd service to keep the device showing Online.Check it's working
# Show virtual IP and WireGuard tunnel netflux status NetFlux status: interface: rnet0 public key: abc123... listening port: 51820 Virtual IP: 10.10.0.3 # List peers on your network netflux peers 2 peer(s): · 10.10.0.1 warehouse-robot-1 Online · 10.10.0.2 dev-laptop 14s ago # Ping another device ping 10.10.0.1 64 bytes from 10.10.0.1: icmp_seq=0 ttl=64 time=12.3 ms # SSH into another device on the network ssh user@10.10.0.1
CLI reference
All flags can also be set via environment variables.
| Flag | Env var | Description |
|---|---|---|
| --token | NETFLUX_TOKEN | Join token from the dashboard (required) |
| --network | NETFLUX_NETWORK | Network ID (required) |
| --controller | NETFLUX_CONTROLLER | Controller URL (default: https://api.net-flux.com) |
| --planet | NETFLUX_PLANET | Override planet server address (host:port) |
| --iface | — | WireGuard interface name (default: rnet0) |
| --identity | — | Identity file path (default: /etc/netflux/identity.json) |
| --uninstall | — | Remove NetFlux and clean up all files |
ROS2 setup
After connecting your devices, configure ROS2 to use the NetFlux virtual network for discovery. Without this, ROS2 uses multicast which doesn't work over VPN.
# Set on every ROS2 machine in the network export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp export ROS_DOMAIN_ID=42 export ROS_IP=10.10.0.X # your NetFlux virtual IP # Tell CycloneDDS to discover peers by IP, not multicast export CYCLONEDDS_URI='<CycloneDDS><Domain><Discovery><Peers> <Peer address="10.10.0.1"/> <Peer address="10.10.0.2"/> </Peers></Discovery></Domain></CycloneDDS>' # Test it ros2 topic list /cmd_vel /odom /scan /tf
Safety watchdog
The safety watchdog monitors the VPN link and publishes a zero Twist message to /cmd_vel if the connection drops for more than 500ms. This stops your robot from continuing the last command indefinitely.
# Run the watchdog node alongside your robot control stack ros2 run netflux watchdog \ --ros-args \ -p timeout_ms:=500 \ -p monitored_peer:=10.10.0.1 \ -p cmd_vel_topic:=/cmd_vel # Output when link drops: [netflux_watchdog]: Link to 10.10.0.1 lost (523ms) — publishing STOP
REST API reference
All endpoints require a Bearer token in the Authorization header.
| Endpoint | Description |
|---|---|
| POST /api/v1/auth/signup | Create a new account |
| POST /api/v1/auth/login | Sign in, returns JWT token |
| GET /api/v1/networks | List all networks |
| POST /api/v1/networks | Create a new network |
| GET /api/v1/networks/:id | Get network + device list |
| POST /api/v1/networks/:id/join | Device joins network (agent calls this) |
| GET /api/v1/networks/:id/peers | Get current peer list (agent polls this) |
| POST /api/v1/networks/:id/tokens | Create a new join token |
| DELETE /api/v1/networks/:id/members/:node_id | Remove a device |
| GET /api/v1/billing/usage | Get device usage and plan info |
| GET /health | Health check |
Troubleshooting
Device shows offline in dashboard
The dashboard marks devices as offline if not seen in the last 2 minutes. Check the agent is running:
systemctl status netflux journalctl -u netflux -n 50
Can't ping another device
# Check the WireGuard interface is up ip addr show rnet0 # Check peers are configured sudo wg show rnet0 # Check there's a route ip route show | grep rnet0
Behind a strict corporate firewall
If UDP port 51820 and 7447 are blocked, NetFlux falls back to TCP/443 automatically. If the connection still fails, check that outbound TCP 443 is allowed.
Invalid join token error
Join tokens are single-use per device. If a token was already used by a different device or the command was run twice, create a new token from your dashboard.