ncclient CLI

This page covers the plain ncclient command from the binaries or Pip, run by hand or under your own init system. If you installed the Linux packages, the Windows MSI, or the NixOS module, use the Linux App, Windows App, or NixOS page instead. Those set up a background service that keeps its state somewhere the plain CLI doesn’t look.

Where state lives

WhatDefault location
Device tokens (one per network)The OS keyring, when there is a usable one (normally only in a logged-in desktop session). Otherwise files in ~/.nebula/tokens/, readable only by their owner. That’s what root, servers, SSH sessions, and the frozen binaries get. Set NEBULA_DEVICE_TOKEN_FILE to a file path, and the tokens go in a tokens/ folder next to it.
settings.json (each network’s server, node ID, accepted routes)~/.config/nebula-commander/ on Linux and macOS, %APPDATA%\nebula-commander\ on Windows. Set NEBULA_COMMANDER_CONFIG_DIR to change it.
Nebula config and certificatesnetworks/<id>/ under the output directory: /etc/nebula on Linux and macOS, %USERPROFILE%\.nebula on Windows. Set with --output-dir.

Before v0.8.0 there was one token (~/.nebula/device-token) and the Nebula files were directly in the output directory. ncclient moves them into this layout the first time v0.8.0 or newer runs.

~ is the home directory of whoever runs the command, so sudo ncclient … uses root’s (/root/.nebula/device-token). Run enroll, run, and routes as the same user (and with the same environment variables), or they won’t find each other’s files.

Linux setup

On Linux the client has to run as root, because Nebula needs root to create its TUN interface. Do every step as root, in this order:

  1. Enroll as root. In Nebula Commander, open Nodes, select the node, click Enroll, and copy the code. Then:

    sudo ncclient enroll --server https://YOUR_NEBULA_COMMANDER_URL --code XXXXXXXX
    
  2. Install the service. This writes a systemd unit that runs ncclient run as root, enables it, and offers to start it (see Run as a service for the prompts and options):

    sudo ncclient install
    
  3. Check that it’s running. From now on the service is the client; don’t also start ncclient run by hand.

    systemctl status ncclient
    sudo journalctl -u ncclient -f
    

Keep using sudo for everything else (sudo ncclient routes …, re-enrolling). Run as a regular user, ncclient reads that user’s own (empty) token and settings instead of the service’s, so it either says you’re not enrolled or changes nothing the service sees. As a regular user you can still check systemctl status ncclient.

If you installed with pip into a virtualenv, sudo ncclient may say command not found, because sudo resets PATH. See Pip: Linux for a setup that works with sudo.

Enroll

  1. In Nebula Commander, open Nodes, select the node for this device, and click Enroll.
  2. Copy the enrollment code.
  3. On the device, as the user that will run the daemon (root on Linux, see Linux setup):
sudo ncclient enroll --server https://YOUR_NEBULA_COMMANDER_URL --code XXXXXXXX

Run enroll again with a code from another network to add that network; one run handles all of them. List them with sudo ncclient networks list, and leave one with sudo ncclient networks remove NAME. See Several networks on one device.

Run (daemon)

After enrollment, run ncclient so it periodically pulls config and certificates and runs or restarts Nebula:

sudo ncclient run --server https://YOUR_NEBULA_COMMANDER_URL

Defaults: poll every 60 seconds, write files to /etc/nebula (or ~/.nebula on Windows), and start or restart Nebula from PATH when config changes. --server can be left out once you’ve enrolled; ncclient uses the server saved in settings.json, or NEBULA_COMMANDER_SERVER.

Linux: creating the Nebula TUN device requires root, so run run with sudo. Running it by hand like this is useful for testing. For normal use, install the service instead, and don’t run both at once.

Options

OptionDescription
--output-dir DIRWhere to write config.yaml, ca.crt, host.crt (default: /etc/nebula on Linux/macOS, ~/.nebula on Windows)
--interval NPoll interval in seconds (default: 60)
--nebula PATHPath to the nebula binary if it is not on PATH
--restart-service NAMEInstead of running nebula directly, restart this systemd service (e.g. nebula). Use only one of --nebula or --restart-service.
--accept-dnsApply split-horizon DNS. See Split-horizon DNS.

Example with nebula in a non-standard location:

sudo ncclient run --server https://nc.example.com --nebula /usr/local/bin/nebula

Example using systemd to run Nebula (ncclient only restarts the service):

sudo ncclient run --server https://nc.example.com --restart-service nebula

Certificates: if the cert was created via the server (Create certificate in the UI), the bundle includes host.key. If it was signed (Sign flow), the server doesn’t have the key, so put your host.key in the output directory.

Run as a service

Linux (ncclient install)

sudo ncclient install

This is step 2 of Linux setup. It checks that root is enrolled (if not, it prints the ncclient enroll … command to run first). It then prompts for the server URL and options, writes /etc/default/ncclient and /etc/systemd/system/ncclient.service, and enables (and optionally starts) the service. The unit runs ncclient run as root.

  • Use --no-start to enable without starting.
  • Use --non-interactive with NEBULA_COMMANDER_SERVER (and optional env vars) set for scripting.

Day-to-day:

sudo systemctl status ncclient
sudo systemctl restart ncclient
journalctl -u ncclient -f

Other platforms

Run ncclient run under your init system (launchd on macOS, Task Scheduler or NSSM on Windows). Example configs are in the repo under client/examples/. See README-startup.md for step-by-step setup on macOS and Windows. On Windows, the MSI’s service is usually the easier option.

Subnet routes and exit nodes

A subnet router or exit node that an admin assigns to this node is only offered to it. It isn’t used until you accept it on the device. Use ncclient routes, as the same user as run and with the same --output-dir:

sudo ncclient routes list                              # offered routes, and which are accepted
sudo ncclient routes accept 192.168.1.0/24             # add --via <IP> if several gateways offer it
sudo ncclient routes reject 192.168.1.0/24
sudo ncclient routes accept-exit-node --via 10.100.0.1   # --block-lan: LAN through it too
sudo ncclient routes exit-lan allow|block                # local network direct (default) or via the exit node
sudo ncclient routes reject-exit-node

You can accept several subnet routes as long as they don’t overlap, and at most one exit node, across all networks on the device. The running daemon picks up changes on its next poll; no restart needed.

With several networks, say which one with --network NAME (name or id from ncclient networks list) before the subcommand: sudo ncclient routes --network office list.

An exit node carries all of the device’s traffic. From v0.7.2, ncclient keeps Nebula’s own traffic out of the tunnel, blocks IPv6 the gateway can’t route, and on Linux drops internet traffic while Nebula is down instead of letting it bypass the tunnel. See Using an exit node.

Split-horizon DNS

When the server has DNS enabled for the network, pass --accept-dns to run. ncclient then fetches the DNS config (domain and lighthouse IPs) and configures the host to resolve the Nebula domain via the network’s DNS. On Linux the client detects how the host manages DNS and configures it to match:

  • systemd-resolved (on its own, or behind NetworkManager): per-link DNS on the Nebula interface, so only the Nebula domain goes to its servers.
  • NetworkManager without systemd-resolved (e.g. Debian desktops): NetworkManager’s dnsmasq plugin with a rule for the Nebula domain. If NetworkManager is writing /etc/resolv.conf itself, the client switches it to the plugin; that needs dnsmasq (Debian: dnsmasq-base) installed.
  • A standalone dnsmasq service: a rule in /etc/dnsmasq.d/.
  • Plain /etc/resolv.conf: last resort, not true split-horizon.

It also keeps NetworkManager from taking over the Nebula interface, re-checks the DNS on every poll (re-applying it if something undid it), and removes everything when it stops or DNS is turned off. If none of these can work, the client logs why and what to install. On Windows it uses NRPT. Applying DNS needs root (Linux) or Administrator (Windows). To remove the DNS override, stop ncclient normally (e.g. Ctrl+C or systemctl stop).

Re-enroll

Get a new code from Nodes → Enroll, then run enroll again as the same user, with the same environment variables as the daemon:

sudo ncclient enroll --server https://YOUR_NEBULA_COMMANDER_URL --code NEWCODE

With a code for the same node on the same server, this overwrites that network’s token. The running daemon switches to the new token on its next poll.

A code for a different node or server adds a network instead. If you’re moving the device, remove the old network afterwards with sudo ncclient networks remove NAME, and update NEBULA_COMMANDER_SERVER in /etc/default/ncclient for an ncclient install service.

If enroll succeeds but the daemon keeps logging Token invalid or expired, the two are using different token locations (usually one ran with sudo and the other didn’t). See Where state lives.

Troubleshooting

  • No TUN device / cannot ping Nebula IP: on Linux, run with sudo. For the Sign flow, make sure host.key is in the output directory. Check Nebula’s error output (e.g. “failed to get tun device”, “no such file”).
  • Nebula starts then exits: often a missing host.key (Sign flow), a wrong config path, or on Linux not running as root. Check the Nebula lines ncclient prints.
  • Token not found. Run 'ncclient enroll' first.: this user has no token. Enroll as the same user that runs the daemon (root, on Linux).
  • Use --network <name or id>: the device is in several networks, so the command needs to know which one. Add --network NAME before the subcommand.
  • enroll fails with KeyringLocked or NoKeyringError (0.7.0 and earlier): see the Linux setup note. Get a new code, since the old one was used.

macOS notes

Default output dir: /etc/nebula; for non-root use --output-dir ~/.nebula. Nebula: use PATH or --nebula /opt/homebrew/bin/nebula (Apple Silicon) or /usr/local/bin/nebula (Intel). Don’t use --restart-service; use launchd for background runs.

Windows notes

Default output dir: %USERPROFILE%\.nebula. Use --nebula if nebula.exe is not on PATH. Don’t use --restart-service. The plain CLI’s token and settings are separate from the shared %ProgramData%\nebula-commander\ location used by the MSI’s app and service. If you installed the MSI, use the Windows App to enroll instead.