# lightscale-client Minimal control-plane client for Lightscale. It registers nodes, sends heartbeats, fetches netmaps, and can manage the WireGuard data plane (kernel or userspace) with basic NAT traversal. This client already uses profile-scoped state files so multiple networks can be supported later by running separate profiles. ## Configure a profile ```sh cargo run -- --profile default init http://127.0.0.1:8080 ``` Multiple control URLs (failover): ```sh cargo run -- --profile default init http://10.0.0.1:8080,http://10.0.0.1:8081 ``` ## Register a node ```sh cargo run -- --profile default register --node-name laptop ``` Register a node with an auth URL flow: ```sh cargo run -- --profile default register-url --node-name laptop ``` The command prints a one-time approval URL. Open it in a browser (or curl it) to approve the node. ## Admin actions Set an admin token when the control plane is protected (CLI flag or env var): ```sh export LIGHTSCALE_ADMIN_TOKEN= ``` List nodes in a network (use `--pending` to show only unapproved nodes): ```sh cargo run -- --profile default admin nodes --pending ``` Update a node's name or tags (admin): ```sh cargo run -- --profile default admin node update --name laptop --tags dev,lab ``` Clear tags: ```sh cargo run -- --profile default admin node update --clear-tags ``` Approve a node by ID: ```sh cargo run -- --profile default admin approve ``` Create an enrollment token: ```sh cargo run -- --profile default admin token create --ttl-seconds 3600 --uses 1 --tags lab ``` Revoke an enrollment token: ```sh cargo run -- --profile default admin token revoke ``` ## Heartbeat ```sh cargo run -- --profile default heartbeat \ --endpoint 203.0.113.1:51820 \ --route 192.168.10.0/24 ``` Optionally include your WireGuard listen port so the server can add the observed public endpoint from the heartbeat connection: ```sh cargo run -- --profile default heartbeat --listen-port 51820 ``` Use STUN to discover a public endpoint (best effort): ```sh cargo run -- --profile default heartbeat --stun --stun-server stun.l.google.com:19302 ``` Advertise exit node routes: ```sh cargo run -- --profile default heartbeat --exit-node ``` ## Fetch netmap ```sh cargo run -- --profile default netmap ``` ## Show status ```sh cargo run -- --profile default status ``` Include WireGuard peer info (handshake age + endpoint): ```sh cargo run -- --profile default status --wg ``` ## Configure WireGuard (Linux) Bring up an interface using the latest netmap: ```sh sudo cargo run -- --profile default wg-up --listen-port 51820 ``` Use boringtun (userspace WireGuard) instead of the kernel module: ```sh sudo cargo run -- --profile default wg-up --listen-port 51820 --backend boringtun ``` This runs the userspace tunnel inside the client process. Keep the command running (or use `agent`) to keep the tunnel alive. Apply advertised subnet/exit routes at the same time: ```sh sudo cargo run -- --profile default wg-up --listen-port 51820 --apply-routes --accept-exit-node ``` Optionally probe peers to trigger NAT traversal (UDP probe, no ICMP): ```sh sudo cargo run -- --profile default wg-up --listen-port 51820 --probe-peers ``` Conflicting routes are skipped by default; use `--allow-route-conflicts` to force them. Select a specific exit node by ID or name: ```sh sudo cargo run -- --profile default wg-up --listen-port 51820 --apply-routes --accept-exit-node \ --exit-node-id ``` Remove the interface: ```sh sudo cargo run -- --profile default wg-down ``` If you used the boringtun backend, stop the process that created the tunnel (for example `Ctrl+C` in the foreground or stopping the agent). The command below attempts to remove the interface if needed. ```sh sudo cargo run -- --profile default wg-down --backend boringtun ``` ## Run the agent loop Keep WireGuard and routes updated using long-polling + periodic heartbeats: ```sh sudo cargo run -- --profile default agent --listen-port 51820 --apply-routes --accept-exit-node \ --heartbeat-interval 30 --longpoll-timeout 30 ``` Tune endpoint rotation (stale seconds + max rotations before relay fallback): ```sh sudo cargo run -- --profile default agent --listen-port 51820 \ --endpoint-stale-after 15 --endpoint-max-rotations 2 ``` Use boringtun backend in the agent: ```sh sudo cargo run -- --profile default agent --listen-port 51820 --backend boringtun ``` Enable STUN discovery in the agent: ```sh sudo cargo run -- --profile default agent --listen-port 51820 --stun \ --stun-server stun.l.google.com:19302 ``` Enable stream relay signaling (peer probe via relay): ```sh sudo cargo run -- --profile default agent --listen-port 51820 --stream-relay ``` With `--stream-relay`, the agent also maintains local relay tunnels that can be used as a fallback when direct endpoints stop handshaking. Probe peers when netmap updates arrive (UDP probe to endpoints, no ICMP): ```sh sudo cargo run -- --profile default agent --listen-port 51820 --probe-peers ``` ## Enable subnet/exit routing (Linux) Configure IP forwarding and (optionally) SNAT for a subnet router or exit node. This uses nftables via `libmnl`/`libnftnl` (the Nix dev shell installs them): ```sh sudo cargo run -- --profile default router enable --interface ls-default --out-interface eth0 ``` Disable SNAT to require return routes on the LAN: ```sh sudo cargo run -- --profile default router enable --interface ls-default --out-interface eth0 --no-snat ``` Remove forwarding/NAT rules: ```sh sudo cargo run -- --profile default router disable --interface ls-default --out-interface eth0 ``` ## DNS and relay info Export host-style DNS entries: ```sh cargo run -- --profile default dns ``` Export DNS info as JSON (debug output): ```sh cargo run -- --profile default dns --format json --output /tmp/lightscale-dns.json ``` Show relay configuration (STUN/TURN/stream relay/UDP relay): ```sh cargo run -- --profile default relay ``` ## UDP relay (best effort) Send a test message via the UDP relay: ```sh cargo run -- --profile default relay-udp send "hello" ``` Listen for relay messages: ```sh cargo run -- --profile default relay-udp listen ``` ## Stream relay (best effort) Send a test message via the stream relay: ```sh cargo run -- --profile default relay-stream send "hello" ``` Listen for relay messages: ```sh cargo run -- --profile default relay-stream listen ```