Skip to main content

ncclient – Nebula Commander device client

License: GNU GPLv3 or later. See LICENSE in this directory.

A small client that works like Defined.net's dnclient and dnclientd: enroll once with a code from Nebula Commander, then run as a daemon to pull config and certificates and optionally orchestrate the Nebula process (start/restart it when config changes).

Install

From PyPI (recommended):

pip install nebula-commander

This installs the ncclient command. Requires Python 3.10+.

From source (e.g. repo clone):

pip install -r client/requirements.txt
# then run as: python -m client --server URL enroll --code XXX

Or install the package in development mode from the client/ directory: pip install -e . to get the ncclient command.

Enroll (one-time)

  1. In Nebula Commander, open Nodes, find your node, and click Enroll.
  2. Copy the enrollment code and run on the device:
ncclient enroll --server https://YOUR_NEBULA_COMMANDER_URL --code XXXXXXXX

This saves the device token to your OS credential store (e.g. Windows Credential Manager, macOS Keychain, Linux Secret Service) and saves the server URL so you can run ncclient run without --server next time.

Upgrading from an older version: If you previously used a token file, you must re-enroll once after upgrading. You can then delete the old token file if it exists (~/.config/nebula-commander/token or /etc/nebula-commander/token).

Run (daemon)

Poll for config and certs every 60 seconds, write them to /etc/nebula (or another directory), and run Nebula (from your PATH) when config changes. If you have already enrolled, you can omit --server (the URL is saved at enrollment):

ncclient run
# or: ncclient run --server https://YOUR_NEBULA_COMMANDER_URL

ncclient assumes nebula is on your PATH and will start/restart it by default. Options:

  • --output-dir DIR – where to write config.yaml, ca.crt, host.crt (default: /etc/nebula on Linux/macOS, ~/.nebula on Windows)
  • --interval N – poll interval in seconds (default: 60)
  • --nebula PATH – path to the nebula binary only if it's not in PATH (e.g. --nebula /opt/homebrew/bin/nebula). Omit this when nebula is already on your PATH.
  • --restart-service NAME – instead of running nebula directly, restart this systemd service after config updates (e.g. nebula). Use only one of --nebula or --restart-service.
  • --accept-dns – enable split-horizon DNS: fetch DNS config from the server, write dns-client.json, and apply it so the Nebula domain is resolved via the network’s DNS (e.g. lighthouse). On Linux the client tries, in order: systemd-resolved, dnsmasq, NetworkManager, systemd-networkd (with resolved), then /etc/resolv.conf. The resolv.conf fallback is best-effort only (no guaranteed split-horizon). Install systemd-resolved or dnsmasq for proper split-horizon. On Windows it uses NRPT. Run as root (Linux) or Administrator (Windows) to apply.

Example – nebula in a non-standard location:

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

Example – use systemd to run Nebula; ncclient only restarts the service:

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

When the certificate was created via the server (Create certificate in the Nebula Commander UI), the bundle includes host.key and no manual copy is needed. For certificates created via Sign (betterkeys, client-generated key), the server does not have the key; place your own host.key in the same directory as the generated certs.

Linux: Creating the Nebula TUN device requires root. Run ncclient as root so the Nebula process can create the interface, e.g. sudo ncclient run --server https://... (or use --output-dir ~/.nebula and run as root so nebula reads from a dir that has host.key).

Split-horizon DNS (Linux)

With --accept-dns, ncclient applies split-horizon DNS so the Nebula domain (e.g. *.nebula.example.com) is resolved by the network’s DNS server. Backends are tried in order until one succeeds:

  1. systemd-resolved – drop-in under /etc/systemd/resolved.conf.d/
  2. dnsmasq – snippet under /etc/dnsmasq.d/ (requires dnsmasq installed and used as resolver)
  3. NetworkManager – per-connection DNS for the Nebula interface via nmcli
  4. systemd-networkd – .network file for the Nebula interface (only when systemd-resolved is active)
  5. /etc/resolv.conf – append nameserver and search domain (best-effort; not true split-horizon; first nameserver often gets all queries)

If no backend succeeds, ncclient reports the failure. The resolv.conf fallback does not guarantee that only the Nebula domain is sent to the Nebula DNS server; for proper split-horizon, use a system with systemd-resolved or dnsmasq. Manual apply/remove scripts (for when ncclient itself isn't run with enough privilege to self-apply): client/contrib/dns-apply-linux.sh and client/contrib/dns-apply-windows.ps1. Note: the Linux fallback script only covers the systemd-resolved, dnsmasq, and resolv.conf backends (not NetworkManager or systemd-networkd) - on those setups, run ncclient --accept-dns directly instead.

Subnet router / exit node (Linux)

When a node is set up in the admin UI as a subnet router or exit node (Routing section on the node's details panel), ncclient on Linux automatically enables IP forwarding and installs the nftables rules that make it actually work - no manual host setup needed. See ../docs/unsafe-routes.md for how routing is selected per consumer node, and what to do instead on Windows/macOS/Docker or a bare nebula install, where this automation doesn't run.

Troubleshooting

  • No network device (tun) created / can't ping Nebula IP
    On Linux, Nebula needs root to create the TUN interface. Run sudo ncclient run --server ....
    If the certificate was created via the server (Create certificate in the UI), the bundle includes host.key and no manual copy is needed. If it was created via Sign (betterkeys), put your host.key in the output dir (e.g. /etc/nebula). Nebula will exit or fail without host.key.
    Nebula's errors are printed to the same terminal; look for messages like "failed to get tun device" (permission) or "no such file" (missing host.key).

  • Nebula starts then exits
    Check the Nebula error lines ncclient prints. Common causes: missing host.key (for Sign flow; Create flow includes it in the bundle), wrong config path, or (Linux) need to run as root.

Running at startup

Quick install (Linux)

On Linux you can install the systemd service with one command:

sudo ncclient install

This checks that you have already enrolled (token is stored in the OS credential store). If not, it prints the exact ncclient enroll --server URL --code XXXXXXXX command to run first (get the code from the Nebula Commander UI: Nodes → Enroll). Then it prompts for the server URL and optional settings (output directory, poll interval, nebula path, restart-service), writes /etc/default/ncclient and /etc/systemd/system/ncclient.service, enables the service, and optionally starts it. Use --no-start to enable without starting; use --non-interactive with NEBULA_COMMANDER_SERVER (and optional env vars) set for scripting.

Manual setup (all platforms)

Run ncclient run under systemd (or your init system) so config and certs stay up to date. ncclient runs nebula from your PATH by default; use --restart-service if you prefer to have systemd run Nebula and ncclient only restart the service. Example configs are in examples/; see examples/README-startup.md for step-by-step install on macOS and Windows.

macOS

ncclient works on macOS (Intel and Apple Silicon). Use Python 3.10+ and install with pip install nebula-commander.

  • Token is stored in the OS credential store (Keychain).
  • Default output dir is /etc/nebula (same as Linux). If you run as a normal user, use --output-dir ~/.nebula so you don't need sudo to write config/certs.
  • Nebula: ncclient runs nebula from your PATH by default. After brew install nebula, you usually don't need --nebula. Use --nebula /opt/homebrew/bin/nebula (Apple Silicon) or --nebula /usr/local/bin/nebula (Intel) only if it's not on PATH. Do not use --restart-service; macOS uses launchd, not systemd.
  • To run ncclient in the background, use launchd (e.g. a LaunchAgent in ~/Library/LaunchAgents or a LaunchDaemon in /Library/LaunchDaemons).

Windows 11

ncclient works on Windows 11. Use Python 3.10+ and install with pip install nebula-commander.

  • Token is stored under %USERPROFILE%\.config\nebula-commander\token.
  • Default output dir for config and certs is %USERPROFILE%\.nebula. Override with --output-dir (e.g. C:\ProgramData\Nebula if you run as Administrator).
  • Nebula: ncclient runs nebula from your PATH by default. If nebula.exe is not on PATH, use --nebula "C:\Path\To\nebula.exe". Do not use --restart-service; there is no systemd on Windows.
  • Run ncclient in a terminal or install it as a Windows service (e.g. with NSSM or Task Scheduler) so it keeps running.

Windows tray app

A system-tray app for Windows provides the same enroll-and-poll flow with a GUI: tray icon, Enroll and Settings dialogs, Start/Stop polling, optional bundled Nebula binary, and Start at login (Registry Run). See client/windows/README.md for how to run from source and how to build ncclient-tray.exe (with optional bundled nebula.exe) using PyInstaller.

Release files for nebula-commander 0.3.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nebula-commander 0.3.9
File Size Uploaded
nebula_commander-0.3.9.tar.gz 80.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nebula-commander 0.3.9
File Interpreter ABI Platform
nebula_commander-0.3.9-py3-none-any.whl Python 3 none any Details

Total release size: 141.8 kB

Release files / nebula_commander-0.3.9.tar.gz

Download URL nebula_commander-0.3.9.tar.gz
Size 80.2 kB
Tags Source
SHA-256 checksum
How to use checksums
670f20a58749dc6cd3b3b684ed38ca71417f389b4086a94515b677eb1c10c674
BLAKE2b-256 checksum
How to use checksums
a46ce2d22bc528b4c3dd23c6977da21a8a726a06456c2bc3a69207546a700a1e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / nebula_commander-0.3.9-py3-none-any.whl

Download URL nebula_commander-0.3.9-py3-none-any.whl
Size 61.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9e901ac5afc28f89d5c85eab452b9d03bdd3a539b617847385deacbb27e25e2a
BLAKE2b-256 checksum
How to use checksums
146d5557cb1210324ebd346b91a15ab0a1dcdd8d130e27f99bd04527b3f39418
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

This release

0.3.9 This release

2 release files

0.3.8

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.22

2 release files

0.2.21

2 release files

0.2.20

2 release files

0.2.19

2 release files

0.2.18

2 release files

0.2.17

2 release files

0.2.16

2 release files

0.2.15

2 release files

0.2.14

2 release files

0.2.13

2 release files

0.2.12

2 release files

0.2.11

2 release files

0.2.10

2 release files

0.1.8

2 release files

0.1.6

1 release file

0.1.4

2 release files

0.1.3

2 release files

0.1.2

1 release file

0.1.1

1 release file

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page