Installing NSClient++¶
This is a growing process before it was all manual but slowly we are getting a more “automated” installation process so hopefully this will keep improving in the future as well and some of the steps might go away.
See Supported platforms for the Windows and Linux version matrix, including the difference between the standard and legacy Windows editions.
Table of Contents¶
- Introduction
- Configuration
- Windows Firewall
- Installing on Linux (.deb / .rpm)
- Debian / Ubuntu
- Rocky / RHEL / Fedora-family
- Installing the web UI bundle
- Offline / air-gapped UI install
- Installing on macOS (.pkg)
- What the installer does
- Managing the service
- File locations (macOS)
- Uninstalling
- What is not in the macOS build yet
- Verifying the download
- Step 1: Check that the file came from this project
- Step 2: Get the SBOM for that file
- Step 3: List the third-party components
- Step 4: Check a component against its upstream project
- Step 5 (optional): Read how the build used them
- Checking the files you installed
- What this proves, and what it does not
- Automated installation (Windows MSI)
- Basic command line
- MSI Options
- On-disk layout (LAYOUT)
- Features
- Silent install
- Debugging
- Specifying your monitoring tool
- Enrolling with a fleet server
- Fleet MSI properties
- Running the installer with fleet arguments
- Checking the enrollment
- What the installer does
- Enrolling after installation
- Copy configuration from a HTTP server
- Use configuration from a HTTP server
Introduction¶
NSClient++ comes with an interactive installer (MSI) which is the preferred method of installation. There is also a command line option for registering (and de-registering) the service but as the Installer is the preferred way.
More detailed information on how to do silent installs and automated installs in large environments can be found below. For most people installing NSClient++ is simply running the MSI entering some options and clicking next. BUT this is only where the fun begins. After installing NSClient++ you need to configure it.
Configuration¶
NSClient++ support multiple configuration storage backends but here we will assume you are using the ini file which is the default.
To check where the configuration is stored, you can run the following command:
$ nscp settings --show
INI settings: (ini://${shared-path}/nsclient.ini, C:\source\build\x64\dev/nsclient.ini)
Now this configuration can include other configuration backends and files so your setup might be more complicated. For details on the configuration options check the the reference documentation
Windows Firewall¶
- Windows firewall exception for NRPE and check_nt is installed (optionally) by the installer. If you have another firewall then the built-in one you might have to manually add exceptions to all incoming traffic if you which to use check_nrpe and/or check_nt.
- External Firewall (optional)
Firewall configuration should be pretty straight forward:
- If you use NRPEServer (check_nrpe, NRPEListener) you need the NRPE port open (usually 5666) from the Nagios server towards the client.
- If you use the NSClientServer (check_nt, NSClientListener) you need the (modified) NSClient port open (usually 12489) from the Nagios server towards the client.
- If you use the NSCA Module (passive checks) you need the NSCA port open from the client towards the Nagios server. client:* -> Nagios:5667
- Also be aware that ports are configurable so if you override the defaults you obviously need to update the firewall rules accordingly.
- There a multitude of other protocol which you can also use with NSClient++ (including, NRPE, NSCA, Syslog, SMTP, etc etc) so please review what your firewall setup in conjunction with you NSClient++ design.
| Protocol | Source | Source port | Destination | Destination port | Comment |
|---|---|---|---|---|---|
| NRPE | Nagios | client | 5666 | The nagios server initiates a call to the client on port 5666 | |
| NSClient | Nagios | client | 12489 | The nagios server initiates a call to the client on port 12489 | |
| NSCA | client | Nagios | 5667 | The client initiates a call to the Nagios server on port 5667 | |
| NRPE-proxy | client | remote-client | 5666 | The client initiates a call to the remote client on port 5666 |
- Nagios is the IP/host of the main monitoring server
- client is the Windows computer where you have installed NSClient++
- remote-client is the “other” client you want to check from NSClient++ (using NSClient++ as a proxy)
All these ports can be changed so be sure to check your nsclient.ini for your ports.
Installing on Linux (.deb / .rpm)¶
On Linux NSClient++ ships as a standard .deb (Ubuntu / Debian) or .rpm
(Rocky / RHEL / AlmaLinux / Fedora) package. See the package matrix in
README.md for the
file to download from the
releases page.
Important
The Linux packages do not include the web management UI. The daemon,
REST API, NRPE/NSCA listeners and all check modules are bundled in the
.deb/.rpm as usual; only the React/Vite frontend lives in a separate
release artifact (NSCP-Web-<version>.zip). Run sudo nscp web
install-ui after installing the package to fetch the matching UI bundle.
See Installing the web UI bundle below.
This split is driven by Debian/Fedora packaging policy (no npm install
during package builds) and only applies to the Linux packages. The
Windows MSI keeps bundling the UI inline.
Debian / Ubuntu¶
# Replace the file name with the one matching your release / arch from
# the README package matrix.
sudo apt install ./NSCP-<version>-ubuntu-24.04-amd64.deb
postinst enables and starts the nsclient systemd service. The first-install
output also reminds you that the UI hasn’t been fetched yet:
NSClient++: web UI is not installed. Run 'nscp web install-ui' as root to fetch it.
Until you run that command, hitting the web port in a browser will show a small built-in placeholder page that repeats the instruction. The REST API, NRPE, NSCA and all other listeners work normally without the UI bundle.
Rocky / RHEL / Fedora-family¶
sudo dnf install ./NSCP-<version>-rocky-10-x86_64.rpm
Same as above: the service starts immediately, and the UI bundle needs a
separate sudo nscp web install-ui step.
File locations¶
The official .deb/.rpm packages install under the standard FHS prefix
/usr:
| What | Location |
|---|---|
| Daemon | /usr/sbin/nscp |
| Check modules | /usr/lib/nsclient/modules |
| Private libraries | /usr/lib/nsclient |
| Scripts / web | /usr/lib/nsclient/{scripts,web} |
| Shipped certificates | /usr/lib/nsclient/security (NRPE DH parameters, server TLS certificate) |
| Configuration | /etc/nsclient |
| Fleet identity | /var/lib/nsclient/security/agent-state.json |
| Fleet-managed config | /var/lib/nsclient/fleet |
| State / cache | /var/lib/nsclient |
| Logs | /var/log/nsclient |
| systemd unit | /lib/systemd/system/nsclient.service |
The split matters: /usr/lib/nsclient belongs to the package and is not written
at runtime, while everything the service rewrites lives under /var. The
service runs as the unprivileged nsclient user, so it cannot write into the
package directory - and /usr has to stay mountable read-only. See
File layout for the whole picture.
These are derived from the build’s install prefix; a package built for a
different prefix (e.g. /opt/nsclient) places everything under that prefix and
the daemon resolves its paths accordingly. To point an already-built daemon at
a boot.ini in a non-standard location, start it with
--path-override boot-conf=/path/to/boot.ini. See
Choosing an install prefix
in the build guide for building against a custom prefix.
Installing the web UI bundle¶
Once the package is installed, fetch the matching UI bundle:
sudo nscp web install-ui
This downloads NSCP-Web-<version>.zip and its .sha256 companion from the
project’s GitHub release that matches your installed daemon version, verifies
the checksum, and unpacks the bundle into the configured web-path (usually
/usr/lib/nsclient/web). sudo is required because that directory is
root-owned.
Companion commands:
sudo nscp web install-ui --force # overwrite an existing install
sudo nscp web ui-status # show installed version, size, source URL
sudo nscp web uninstall-ui # remove only the files this command installed
After install-ui succeeds you can reload the daemon and the UI replaces the
placeholder. If WEBServer is already running, an immediate browser refresh
picks up the new files — no restart needed.
Offline / air-gapped UI install¶
For hosts without outbound internet access, download NSCP-Web-<version>.zip
(and optionally NSCP-Web-<version>.sha256) on a machine that has access,
copy them to the target, and point the installer at the local file:
sudo nscp web install-ui --from /tmp/NSCP-Web-<version>.zip
When a sibling .zip.sha256 (or <basename>.sha256) is present next to the
zip, the installer verifies it. Without one, it skips verification and prints
a warning — you opted into trusting a local path.
Installing on macOS (.pkg)¶
macOS support is experimental
It ships a smaller set of check modules than the Windows and Linux builds - read What is not in the macOS build yet before deploying it - and the packaging may still change between releases. The same sense of “experimental” a young check command carries: it works, but what it looks like is not settled yet.
macOS builds are Apple silicon (arm64) only and are distributed as a
standard installer package, NSCP-<version>-macos-arm64.pkg, on the
releases page. The package is
self-contained: everything it links against is inside it, so the target Mac
does not need Homebrew or any other prerequisite.
sudo installer -pkg NSCP-<version>-macos-arm64.pkg -target /
Install from the command line, not the Finder. The release builds are not
signed or notarized yet, so Gatekeeper refuses a double-click with “cannot be
opened because Apple cannot check it for malicious software”. installer does
not go through that check, which is also why it is what CI installs with.
To go through the Finder anyway, clear the quarantine flag your browser set on the download, then open it:
xattr -d com.apple.quarantine NSCP-<version>-macos-arm64.pkg
Or attempt the install once and approve it under System Settings → Privacy & Security, where a blocked package gets an Open Anyway button. The older right-click → Open route has been narrowed on recent macOS and may not offer the bypass at all.
Note
An Intel Mac will be refused by the installer rather than silently installing something that cannot run. Rosetta 2 does not help: the package contains arm64 code only.
A plain NSCP-<version>-macos-arm64.tar.gz of the same install tree is published
alongside it, for anyone who would rather unpack than install. It is rolled from
the very tree the .pkg installs, so it carries the same bundled libraries and
needs no Homebrew either:
sudo tar -xzf NSCP-<version>-macos-arm64.tar.gz -C /
What it does not do is any of the work the installer scripts do: no
_nsclient account is created, nothing is chowned, and the launchd job is laid
down but never loaded. You would be doing that by hand. Use the .pkg unless
you have a specific reason not to.
What the installer does¶
- Stops and unloads any running agent, so the payload does not overwrite a binary that is currently mapped.
- Creates a hidden system account and group,
_nsclient, with a UID in Apple’s 200-400 range for third-party daemons. The agent runs as that account, not as root. - Lays down the program files under
/usr/localand the launchd job description in/Library/LaunchDaemons. - Hands the writable directories (state, logs) to
_nsclient, and locksnsclient.inidown toroot:_nsclientmode0640- it holds the web admin password and the NRPE/NSCA credentials in plaintext. - Loads and starts the launchd job, which also makes it start at boot.
As on Linux, the web UI is a separate download; the installer prints a reminder.
sudo /usr/local/sbin/nscp web install-ui
Managing the service¶
macOS has no systemctl. The equivalent commands are:
| What | Command |
|---|---|
| Status | sudo launchctl print system/com.nsclient.nscp |
| Restart | sudo launchctl kickstart -k system/com.nsclient.nscp |
| Stop (until reboot) | sudo launchctl kill SIGTERM system/com.nsclient.nscp |
| Stop and disable | sudo launchctl bootout system/com.nsclient.nscp |
| Start again | sudo launchctl bootstrap system /Library/LaunchDaemons/com.nsclient.nscp.plist |
launchctl print reports state = running when the agent is up. If the job is
loaded but keeps restarting, the agent is failing at startup: look at
/usr/local/var/log/nsclient/nsclient.log first, and at
/usr/local/var/log/nsclient/launchd.err.log for anything that happened before
the logger existed (a module that failed to load, a configuration file it could
not read).
File locations (macOS)¶
The prefix is /usr/local, because macOS mounts the system volume read-only and
reserves /usr for the OS. The layout underneath mirrors the Linux packages:
| What | Location |
|---|---|
| Daemon | /usr/local/sbin/nscp |
| Uninstaller | /usr/local/sbin/uninstall-nsclient |
| Check modules | /usr/local/lib/nsclient/modules |
| Private libraries | /usr/local/lib/nsclient |
| Scripts / web | /usr/local/lib/nsclient/{scripts,web} |
| Shipped certificates | /usr/local/lib/nsclient/security |
| Configuration | /usr/local/etc/nsclient |
| State / cache | /usr/local/var/lib/nsclient |
| Logs | /usr/local/var/log/nsclient |
| launchd job | /Library/LaunchDaemons/com.nsclient.nscp.plist |
Uninstalling¶
An installer package has no uninstall verb, so one ships in the payload:
sudo /usr/local/sbin/uninstall-nsclient # keep configuration and logs
sudo /usr/local/sbin/uninstall-nsclient --purge # remove them, and the account
What is not in the macOS build yet¶
Two modules are not built for macOS, because their data sources are Linux kernel interfaces rather than portable code:
| Module | Why | Checks affected |
|---|---|---|
CheckDisk |
Enumerates mounts through <mntent.h> and reads /proc/diskstats |
check_drivesize, check_mount, check_disk_io, check_disk_health, and the storage facts. check_files, check_single_file and check_disk_write are portable code, but they ship inside the same module |
CheckLogFile |
Its real-time mode watches files with inotify |
check_logfile (itself portable, but in the same module) and the real-time log filters |
CheckSystem is built and carries all 21 of its Linux commands, the host,
network and software facts, the real-time filters and the system metrics. Its
data comes from sysctl, the Mach host statistics, libproc, IOKit and
launchctl instead of procfs, and a few values have no Darwin counterpart.
Those are reported as absent - the keyword renders unknown, never satisfies
a threshold and emits no performance data - or the check returns UNKNOWN,
rather than a zero that was never measured:
| Check | On macOS |
|---|---|
check_process |
For processes owned by another user, virtual, working_set, rss, page_faults, user, kernel and time are unknown and command_line is empty: macOS gives that information only to the owner and root. peak_virtual and peak_working_set are always unknown. |
check_service |
Checks launchd jobs in the system domain by label (service=com.apple.logd). An idle job launchd starts on demand has start_type on-demand and state static; a job counts as failed when it crashed, or when it is meant to be running and exited non-zero. rss, vms, cpu and tasks read 0 for a job the agent may not inspect; has_metrics says which. |
check_installed_software |
Lists installer receipts (manager pkgutil), the applications in /Applications (bundle) and Homebrew formulae and casks (homebrew). |
check_os_updates |
Reads the list macOS cached at its last background check (manager softwareupdate); live=true asks Apple’s server instead, which takes 10 to 60 seconds. last_checked is when the cached list was refreshed. |
check_cpu_utilization |
iowait, irq, softirq, steal and guest are 0: Darwin does not account for them. |
check_kernel_memory |
No slab allocator, so the slab* keywords are unknown; wired and compressed report the Darwin memory states instead. |
check_kernel_stats |
Only the threads row. type=ctxt and type=processes are UNKNOWN: Darwin keeps no unprivileged count of context switches or forks. |
check_load |
procs_running is unknown; procs_total is the thread count. |
check_temperature, check_cpu_frequency |
Always UNKNOWN. The sensors and per-core clocks are reachable only through private, version-specific interfaces. |
check_memory |
cached counts file-backed and purgeable pages as free. Swap is created on demand, so its total can be 0. |
The process counters are the one gap an operator can close. The launchd job
runs the agent as _nsclient through the UserName and GroupName keys in
/Library/LaunchDaemons/com.nsclient.nscp.plist; without them it runs as root
and check_process sees every process. That also runs every check, external
script and listener as root, and a package upgrade reinstalls the plist, so it
is a deliberate choice rather than a default.
Two CheckNet checks are present but reduced:
check_connectionsreads/proc/neton Linux; on macOS it answers “not implemented on this platform”.check_pingopens a raw ICMP socket, which macOS only lets root do. The agent runs as_nsclient, so the check reports that it cannot open its socket rather than a round-trip time.
Everything else is present: the REST API and web server, NRPE/NSCA/NSCP/check_mk
listeners and clients, CheckHelpers, CheckExternalScripts, CheckNet,
CheckSecurity, CheckDocker, the Lua script engine, the scheduler, and the
Graphite/Elastic/Syslog/SMTP/collectd forwarders.
Two smaller gaps:
- The bundled
check_nsclientplugin is not shipped, because mickem/check_nsclient publishes Linux and Windows binaries only. PythonScriptandCheckMySQLare not built, because the macOS CI job does not install Boost.Python or the MariaDB connector. They build from source if you provide those.
Verifying the download¶
A Windows release comes with enough evidence for you to check where it came from, and where the third-party code inside it came from, without taking our word for it. The checks below answer three questions:
- Was this file built by this project’s release workflow, and from which commit?
- Which third-party components does it contain, and exactly which upstream files were they built from?
- Do those upstream files match what the upstream projects themselves publish?
You need the GitHub CLI (gh) for the first two,
plus jq, git, and sha256sum or PowerShell’s Get-FileHash. The examples
use the x64 MSI; replace the file name with the one you downloaded. Releases
published before the SBOM was introduced have no .cdx.json and no
attestations, so only the Authenticode signature applies to them.
Step 1 works for every release asset, including the Linux and macOS packages. Steps 2 to 4 are for the Windows builds, the only ones with an SBOM: the Linux packages link the distribution’s own libraries, and the macOS package bundles libraries from Homebrew, which both verify their packages themselves.
Step 1: Check that the file came from this project¶
Every release asset carries a GitHub artifact attestation: a statement, signed through Sigstore by the release workflow’s own identity, that names the file’s SHA-256 and the commit it was built from.
gh attestation verify NSCP-<version>-x64.msi --repo mickem/nscp \
--signer-workflow mickem/nscp/.github/workflows/release.yml
Verification fails for a file this workflow did not produce, and for one that was changed after it was produced. To see which commit and which workflow run built it:
gh attestation verify NSCP-<version>-x64.msi --repo mickem/nscp --format json \
--jq '.[].verificationResult.statement.predicate
| .buildDefinition.resolvedDependencies[0].digest.gitCommit, .runDetails.metadata.invocationId'
The MSI and every executable, DLL and Python extension it installs are also
Authenticode-signed, which Windows shows under Properties > Digital
Signatures, or Get-AuthenticodeSignature in PowerShell. A third-party file
that already carries its publisher’s signature, such as the Python runtime,
keeps that signature. Releases up to 0.23.0 signed only the MSI and the
executables.
Step 2: Get the SBOM for that file¶
Each Windows release publishes a software bill of materials (SBOM) in
CycloneDX 1.6 JSON: NSCP-<version>-<platform>.cdx.json
on the release page, and the same file as sbom.cdx.json inside the zip. The
MSI does not install it.
The SBOM is itself attested against the zip and the MSI of its platform, so the simplest way to get one you can trust is to take it out of the signed attestation for the file you have:
gh attestation verify NSCP-<version>-x64.msi --repo mickem/nscp \
--predicate-type https://cyclonedx.org/bom --format json \
--jq '.[0].verificationResult.statement.predicate' > sbom.cdx.json
This fails unless the SBOM was published for exactly this file. The same
command with NSCP-<version>-x64.zip gives the same SBOM.
Step 3: List the third-party components¶
For every component the build compiled in or bundled, the SBOM records the version, the upstream URL the build fetched, and either the SHA-256 of the downloaded file or the git commit of a cloned tag. The build checked each of these values against the ones recorded in the repository before it used the file, and the SBOM is written from those recorded values, not from what the download returned.
jq -r '.components[] | select(.purl | startswith("pkg:npm/") | not)
| [.name, .version, (.hashes[0].content // ([.properties[] | select(.name == "nscp:git-commit").value][0]) // "-"),
.externalReferences[0].url] | join(" ")' sbom.cdx.json
Each component also has an nscp:verification property:
| Value | Meaning |
|---|---|
sha256 |
A downloaded file, checked against the recorded SHA-256. |
git-commit |
A git tag, cloned and checked to resolve to the recorded commit (tags can be moved, commits cannot). |
nuget-restore |
A NuGet package, listed with the SHA-512 NuGet recorded when it restored the package. |
npm-integrity |
A web UI package, listed with the SHA-512 pinned in package-lock.json. |
none |
Not digest-checked by the build. Currently only the embedded Python runtime. |
GoogleTest is listed with "scope": "excluded": only the unit tests link it,
so it is not in anything you install.
check_nsclient publishes an SBOM of its own with each release, and the build
nests it under the check_nsclient component: the Rust crates it is built from,
each with its version and SHA-256. The build checks that SBOM against the
release’s SHA256SUMS before nesting it. To list them:
jq -r '.components[] | select(.name == "check_nsclient") | .components[]
| "\(.name) \(.version) \(.hashes[0].content)"' sbom.cdx.json
Step 4: Check a component against its upstream project¶
Download the file the SBOM names and hash it yourself. The value must match the SBOM and, where the upstream project publishes one, the upstream checksum:
curl -sSfLO https://github.com/openssl/openssl/releases/download/openssl-3.5.9/openssl-3.5.9.tar.gz
sha256sum openssl-3.5.9.tar.gz
curl -sSfL https://github.com/openssl/openssl/releases/download/openssl-3.5.9/openssl-3.5.9.tar.gz.sha256
| Component | Where upstream publishes the checksum |
|---|---|
| OpenSSL | A .sha256 file next to the tarball: the URL with .sha256 appended. |
| Boost | The release notes page for the version, e.g. Boost 1.86.0. |
| Lua | The checksum column of lua.org/ftp. |
| check_nsclient | SHA256SUMS on its release page, itself attested (see below). |
| Protocol Buffers, Crypto++, miniz | Nowhere. The SBOM digest then only shows that the file has not changed since the project recorded it. |
check_nsclient attests its releases the same way this project does, so its binary can be traced to its own release workflow:
gh attestation verify check_nsclient-<version>-windows-x64.exe --repo mickem/check_nsclient \
--signer-workflow mickem/check_nsclient/.github/workflows/release.yml
For a component cloned from git, ask the upstream repository which commit the
tag points at. The SBOM’s nscp:git-ref property names the tag, and the
commit must equal nscp:git-commit. For an annotated tag it is the line
ending in ^{}:
git ls-remote https://github.com/mariadb-corporation/mariadb-connector-c.git 'refs/tags/v3.4.9*'
For a web UI package, npm view <name>@<version> dist.integrity prints the
same SHA-512 in base64.
Step 5 (optional): Read how the build used them¶
The commit from step 1 lets you read the exact build that produced the file.
At that commit, .github/dependency-checksums.txt holds the values the SBOM
lists, the actions under .github/actions/ download each dependency and check
it against that file before building it, and build/python/sbom.py writes the
SBOM from it:
https://github.com/mickem/nscp/blob/<commit>/.github/dependency-checksums.txt
Checking the files you installed¶
The zip holds SHA256SUMS, the SHA-256 of every file in it. In the folder you
unpacked the zip into:
sha256sum -c SHA256SUMS
or in PowerShell:
Get-Content SHA256SUMS | ForEach-Object {
$hash, $file = $_ -split ' ', 2
if ((Get-FileHash $file -Algorithm SHA256).Hash -ne $hash) { "MISMATCH: $file" }
}
An MSI install carries neither file. The MSI and the zip of a release are
packaged from the same signed build, so take SHA256SUMS from the zip of the
same version and platform and compare single files against it:
(Get-FileHash "C:\Program Files\NSClient++\libcrypto-3-x64.dll").Hash
What this proves, and what it does not¶
These checks show that the file was built by this project’s release workflow from a named commit, that the SBOM describes that exact file, and that every upstream file the SBOM names is the one upstream published. They do not show that the shipped binaries were compiled from those upstream files: the build is not reproducible, and signing changes the bytes, so compiling the same sources yourself gives different hashes. That last link rests on the GitHub-hosted runner having run the workflow as it is written at that commit, which step 5 lets you read.
Automated installation (Windows MSI)¶
The NSClient++ installer for windows is a standard MSI installer which means it can be installed using pretty much all deployment techniques available on the windows platform.
Basic command line¶
To customize the installation you can use the standard MSI options to add/remove features and set properties. An example of this is shown below.
$ msiexec /i NSCP-VERSION-x64.msi ADDLOCAL=ALL REMOVE=PythonScript INSTALLLOCATION=c:\FooBar
MSI Options¶
A list of all the MSI options can be found below.
| Keyword | Description |
|---|---|
| INSTALLLOCATION | Folder where NSClient++ is installed. |
| ADD_DEFAULTS | Add default values to the configuration file. |
| ALLOWED_HOSTS | Set allowed hosts value |
| ALLOW_CONFIGURATION | If set to 1 allows configuration changes. If set to 0 disable all configuration support in the installer |
| CONFIGURATION_TYPE | Configuration context to use |
| CONF_CHECKS | Enable default check plugins |
| CONF_NRPE | Enable NRPE server |
| CONF_NSCA | Enable NSCA Collection /OU probably need scheduler as well) |
| CONF_NSCLIENT | Enable NSClient Server (check_nt) |
| CONF_SCHEDULER | Enable Scheduler (required by NSCA) |
| CONF_WEB | Enabled WEB Server |
| NRPEMODE | NRPE Mode (LEGACY, SECURE for using ceretificates) |
| NSCLIENT_PWD | Password to use for check_nt (and web server). Stored hashed when given here or typed into the dialog; a value already on disk, or one the installer generated itself, is left in clear text |
| CONF_INCLUDES | Additional files to include in the config syntax: |
| NSCA_SERVER | Address of the machine running the nsca daemon to submit passive results to. Setting it enables NSCAClient |
| NSCA_PORT | Port that daemon listens on (5667 unless it was changed) |
| NSCA_PASSWORD | The NSCA shared key, matching password in the daemon’s nsca.cfg. Stored in clear text - NSCA encrypts with it, so a hash is not a key - and never written to the MSI log |
| NSCA_ENCRYPTION | Cipher, matching the daemon’s decryption_method (e.g. aes256) |
| NSCA_HOSTNAME | Host name to submit results as, as Nagios/Icinga knows this host (auto uses the computer name) |
| OP5_SERVER | OP5 Server if you want to automatically submit passive checks via Op5 northbound API. |
| OP5_USER | The username to login with on the OP5_SERVER |
| OP5_PASSWORD | The password to login with on the OP5_SERVER |
| OP5_HOSTGROUPS | Additional hostgroups to add to the host. |
| OP5_CONTACTGROUP | Additional contactgroups to add to the host. |
| NO_SERVICE | Set to 1 to disable installing the service (then you can manually create and activate the service when needed) |
| TLS_VERSION | The TLS version to use (1.0, 1.1, 1.2, 1.3) |
| TLS_VERIFY_MODE | The TLS verify mode to use (none, peer, fail_if_no_peer_cert) |
| TLS_CA | The CA file to use for TLS connections (defaults to the Windows ROOT store) |
| CERTIFICATE | PEM file to install as the agent’s TLS server certificate - see Installing your own TLS certificates |
| CERTIFICATE_KEY | PEM file with the private key for CERTIFICATE, when the key is not embedded in the certificate file |
| CERTIFICATE_CA | PEM file (bundle) to install as the CA the servers use to verify client certificates |
| CONF_SET | Set a configuration value in the form of section1;key1;value1;section2;key2;value2… |
| IMPORT_CONFIG | URL or file path to a configuration file to copy during install and use as the configuration for NSClient++ |
| FLEET_SERVER | Fleet server url (https://fleet.example.com) to enroll this host with during install |
| FLEET_TOKEN | The one-time bootstrap token from the install command generated by the fleet server (required with FLEET_SERVER) |
| FLEET_HOSTNAME | Host name to report to the fleet server (defaults to this machine’s host name) |
| FLEET_CA | CA bundle used to verify the fleet server certificate (defaults to the Windows ROOT store) |
| FLEET_VERIFY_MODE | TLS verify mode for the enrollment call (certificate, none). none requires FLEET_INSECURE=1 |
| FLEET_INSECURE | Set to 1 to allow an unauthenticated enrollment: a plain http:// FLEET_SERVER, or FLEET_VERIFY_MODE=none |
| FLEET_BUNDLE_KEY | Bundle encryption key(s) for sealed bundles, as shown once by the fleet server; several separated by commas |
| FLEET_REQUIRE_ENCRYPTED_BUNDLES | Set to 1 to refuse every bundle that is not sealed with one of the bundle keys |
| LAYOUT | On-disk layout: modern keeps the writable state in %ProgramData%\NSClient++ restricted to SYSTEM and administrators, legacy (default) keeps it in the install folder. Omit it to keep whatever the host already uses. Experimental - see below |
| USER_WRITABLE_CONFIG | Set to 1 to give the local Users group write access to nsclient.ini. This makes every local user an administrator of the host - see below. Ignored on a host already on the modern layout (its boot.ini says modern) and with ALLOW_CONFIGURATION=0; do not combine it with a fresh or first-time LAYOUT=modern install, where the writable file is still installed and then moved into %ProgramData% |
USER_WRITABLE_CONFIG is a local privilege escalation
nsclient.ini decides what the agent runs, and the agent runs as LocalSystem. A user who can write it can add an
external script, or point the script path at a folder they own, and have it executed as SYSTEM on the next reload
or restart. Installing with USER_WRITABLE_CONFIG=1 therefore hands local administrator rights to every account in
the Users group. Do not set it on a machine where any of those accounts is not already trusted as an administrator;
to let a specific person edit the configuration, grant that one account write access to the file instead.
Passive results over NSCA (NSCA_*)¶
NSCA_SERVER and friends configure the submission side: this agent sending
passive results to an nsca daemon. Setting NSCA_SERVER enables NSCAClient
and writes [/settings/NSCA/client/targets/default].
msiexec /qn /i NSCP-<version>-x64.msi ADDLOCAL=ALL ^
NSCA_SERVER=nagios.example.com NSCA_PORT=5667 ^
NSCA_PASSWORD=<the key from the daemon's nsca.cfg> NSCA_ENCRYPTION=aes256 ^
NSCA_HOSTNAME=<the host name Nagios knows this machine by>
The key must match password in the daemon’s nsca.cfg and the cipher its
decryption_method, or the daemon silently discards every submission. It is
stored in clear text on purpose: NSCA encrypts the payload with it rather than
verifying it, so a hash there would be a key nobody has. It is deliberately not
the shared NSCLIENT_PWD, which the inbound protocols verify callers against
and which is stored hashed.
These properties do not configure the other direction, where this agent
accepts NSCA submissions (NSCAServer). That listener has its own key, shared
with the hosts submitting here rather than with the daemon above, and it reads
neither this target nor [/settings/default] - with encryption on and no key of
its own it refuses to start. Set it after installing:
nscp nsca install --server --password <the key every submitting host uses>
On-disk layout (LAYOUT)¶
By default everything lives in the install folder, C:\Program Files\NSClient++\,
which any logged-in user can read - including nsclient.ini with the web and
NRPE passwords, the server’s TLS private key and the fleet identity.
LAYOUT=modern moves that writable half to C:\ProgramData\NSClient++\ and
restricts it to SYSTEM and Administrators; the program itself stays where it
was installed.
msiexec /qn /i NSCP-<version>-x64.msi LAYOUT=modern
The same command on an upgrade moves the existing installation’s configuration, certificates and fleet identity for you.
Leaving the property out keeps the layout the host already has. An upgrade therefore never moves an installation that did not ask to move, and never moves a modern one back to legacy just because the property was not repeated.
LAYOUT=legacy against a host that is already on the modern layout is logged
and ignored. The installer only ever moves files into the protected folder, so
honouring it would record a layout whose files had not moved. To go back, use
the agent itself, which migrates in both directions and can show you the plan
first:
nscp settings --migrate-layout legacy --dry-run
Experimental
The modern layout is opt-in and marked experimental: upgrades in particular have not been tested at scale. Prefer it for new installs; for existing installs test the upgrade in your own environment first - configuration management, backups and scripts that reference the old paths are what will notice.
An already-installed host can also be switched later, without reinstalling:
nscp settings --migrate-layout modern --dry-run shows exactly what would
move.
See Securing NSClient++ for what it fixes and File layout for what lives where.
Features¶
NSClient++ consists of the following features most which can be disabled when doing silent installations.
| Feature Name | Title | Description |
|---|---|---|
| CheckPlugins | Check Plugins | Various plugins to check your system. (Includes all check plugins) |
| ExtraClientPlugin | Various client plugins | Plugins to connect to various systems such as syslog, graphite and smtp |
| FirewallConfig | Firewall Exception | A firewall exception to allow NSClient++ to open ports |
| LuaScript | Lua Scripting | Allows running INTERNAL scripts written in Lua |
| NRPEPlugins | NRPE Support | NRPE Server Plugin. Support for the more versatile NRPE protocol (check_nrpe) |
| MySQLPlugin | MySQL Support | Plugin to check MySQL, MariaDB and Percona servers (includes the MariaDB Connector/C client library) |
| NSCAPlugin | NSCA plugin | Plugin to submit passive results to an NSCA server |
| CheckMK | Check MK support | Experimental support for check_mk server and clients |
| ElasticPlugin | Elastic Search support | Support for submitting metrics to elastic |
| NSCPlugins | check_nt support | NSClient Server Plugin. Support for the old NSClient protocol (check_nt) |
| PythonScript | Python Scripting | Allows running INTERNAL scripts written in Python |
| SampleScripts | Scripts | Scripts for checking and testing various aspects of your computer and NSClient++ |
| Shortcuts | Shortcuts | Main Service shortcuts |
| WEBPlugins | WEB Server | NSClient WEB Server. Use this to administrate or check NSClient via a browser or REST API |
| OP5Monitoring | OP5 Monitoring | Scripts/config for the op5 monitoring system. |
The NSCA-NG client (NSCANgClient) is not an installer feature. A few
antivirus engines report its DLL as malware with generic, unconfirmed
detections, so it ships in the Windows zip only and is copied into the
modules folder by hand. See
NSCANgClient for the steps.
Silent install¶
Now we can put all this together using the normal silent installer which is again part of the standard windows install
toolkit.
So if you already have a framework for managing installs use that instead of this command line.
The gist of it is: msiexec /quiet /i <MSI FILE> PROPERTY=PropertyValue ...
For instance Installing NSClient++ into c:\foobar using registry as configuration and not installing the Python script binaries.
msiexec /qn /l* log.txt /i NSCP-0.4.3.50-x64.msi INSTALLLOCATION=c:\FooBar CONFIGURATION_TYPE=registry://HKEY_LOCAL_MACHINE/software/NSClient++ ADDLOCAL=ALL REMOVE=PythonScript
Debugging¶
If you run into any issues or want to report a bug a good first step is to enable logging of the installation process.
This is done by adding /l* log.txt to the command line (you can of course change the log file name to whatever you want).
BEWARE: The log file can contain sensitive information such as passwords so be careful when sharing it with others.
Specifying your monitoring tool¶
There is an option which can be used to define a base-line for your monitoring tool. If you do not have a supported monitoring tool you can set it to “none” which will use the generic configuration which works with all monitoring tools.
msiexec /i NSCP-<version>.msi MONITORING_TOOL=none
Silent op5 install¶
To enable active checks via NRPE from OP5 you can set the MONITORING_TOOL option to OP5.
msiexec /i NSClient++.msi MONITORING_TOOL=OP5
Silent op5 install (Northbound)¶
To enable passive reports via OP5s Northbound API you can set the OP5_SERVER, OP5_USER and OP5_PASSWORD options.
In this case setting MONITORING_TOOL is done automatically when ever OP5_SERVER is detected.
msiexec /i NSClient++.msi OP5_SERVER=https://op5.com OP5_USER=monitor OP5_PASSWORD=rotinom
Enrolling with a fleet server¶
Starting from nothing?
Central management with NSClient Fleet is the end-to-end walkthrough: running the fleet server as a container, getting the agent to trust it, enrolling, and what changes on the agent afterwards. This section is the MSI reference.
If you manage your agents from an NSClient fleet server, the installer can enroll the host while it installs, so the machine is managed from the moment the service starts. Generate an install command on the fleet server and pass the server url and the bootstrap token it gives you:
msiexec /qn /i NSCP-<version>-x64.msi FLEET_SERVER=https://fleet.example.com FLEET_TOKEN=<bootstrap-token>
Enrolling makes the server an administrator of this host
The configuration a fleet server sends is an ordinary include of the settings store, so
it can enable script execution, define the scripts and rewrite the fleet settings
themselves: a fleet server can run code as SYSTEM on every host enrolled with it. That
is the same trust any configuration-management system has, and it is why the enrollment
link has to be a verified one. See
What the fleet server can do to a host.
Fleet MSI properties¶
FLEET_SERVER is what turns enrollment on; everything else refines it.
| Property | Required | Default | What it does |
|---|---|---|---|
FLEET_SERVER |
yes | - | Url of the fleet server, scheme included (https://fleet.example.com). Without it no enrollment is attempted. |
FLEET_TOKEN |
yes | - | The one-time bootstrap token from the install command the fleet server generated. One-time, and valid for an hour. |
FLEET_CA |
when the server certificate is not publicly trusted | the Windows ROOT store | Path to the issuing CA in PEM form, on the machine being installed. |
FLEET_HOSTNAME |
no | this machine’s host name | The name this host reports to the fleet server. |
FLEET_VERIFY_MODE |
no | certificate |
none stops the fleet server being verified at all, and is only accepted together with FLEET_INSECURE=1. |
FLEET_INSECURE |
no | unset | 1 opts into an unauthenticated enrollment: a plain http:// url, FLEET_VERIFY_MODE=none, or both. |
FLEET_BUNDLE_KEY |
for encrypted bundles | unset | The bundle encryption key (44 base64 characters) the fleet server showed once when it was created; several, comma separated, while rotating. Stored in the enrollment manifest, never sent to the server. On an already enrolled host it may be given on its own, without FLEET_SERVER, to replace the stored keys. |
FLEET_REQUIRE_ENCRYPTED_BUNDLES |
no | unset | 1 refuses every bundle that is not sealed with one of the bundle keys, plain ones included. Stored in the enrollment manifest, so the fleet server cannot switch it off; may be given on its own on an enrolled host. |
Running the installer with fleet arguments¶
All of these are one command line; ^ is the cmd continuation character, so drop it if you put the command on a single
line. Use the same properties from any deployment tool that can pass MSI properties (Intune, SCCM/MECM, Group Policy,
Ansible, Chocolatey) - they are ordinary public properties.
The fleet server has a publicly trusted certificate. Nothing beyond the two properties from the install command:
msiexec /qn /l*v install.log /i NSCP-<version>-x64.msi ^
FLEET_SERVER=https://fleet.example.com ^
FLEET_TOKEN=<bootstrap-token>
The fleet server has a private or self-signed certificate. This is the common case - a fleet server generates a
self-signed certificate for itself by default - and it is the step people miss. Copy the issuing certificate to the
machine first (it is a public certificate, so it needs no protection in transit) and point FLEET_CA at the copy:
msiexec /qn /l*v install.log /i NSCP-<version>-x64.msi ^
FLEET_SERVER=https://fleet.example.internal:8443 ^
FLEET_TOKEN=<bootstrap-token> ^
FLEET_CA=C:\ProgramData\fleet-ca.pem
FLEET_CA is a path on the machine being installed, read while the install runs - not a path on the machine that wrote
the command line - so put the file there before msiexec starts. Get it wrong and the install fails with a certificate
verification error that says nothing about the token; see
Give the agents something to trust for how to get the file out of
the fleet server.
Enrolling as part of a real install. The fleet properties combine with the rest of the command line as usual:
msiexec /qn /l*v install.log /i NSCP-<version>-x64.msi ^
ADDLOCAL=ALL REMOVE=PythonScript ^
LAYOUT=modern ^
ALLOWED_HOSTS=10.0.0.0/8 ^
FLEET_SERVER=https://fleet.example.internal:8443 ^
FLEET_TOKEN=<bootstrap-token> ^
FLEET_CA=C:\ProgramData\fleet-ca.pem ^
FLEET_HOSTNAME=web01.example.internal
Keep that local part small: whatever the fleet server sends after the first sync is the configuration you actually maintain, and a value set locally here wins over the fleet-managed one.
From PowerShell. PowerShell parses the arguments before msiexec sees them, so pass them as an array and wait for
the exit code rather than assuming it worked:
$token = '<bootstrap-token>'
$msiArgs = @(
'/qn', '/l*v', 'install.log', '/i', 'NSCP-<version>-x64.msi',
'FLEET_SERVER=https://fleet.example.internal:8443',
"FLEET_TOKEN=$token",
'FLEET_CA=C:\ProgramData\fleet-ca.pem'
)
$p = Start-Process msiexec.exe -ArgumentList $msiArgs -Wait -PassThru
if ($p.ExitCode -ne 0) { throw "NSClient++ install failed with $($p.ExitCode), see install.log" }
A value containing spaces is quoted around the value, not around the whole pair:
FLEET_CA="C:\Program Files\fleet-ca.pem" works, "FLEET_CA=C:\Program Files\fleet-ca.pem" is not read as a
property at all.
The lab shortcut
A fleet server you have no trust anchor for can still be enrolled against, but only if you say so explicitly -
FLEET_VERIFY_MODE=none on its own fails the install, as does a http:// url:
msiexec /qn /i NSCP-<version>-x64.msi ^
FLEET_SERVER=https://fleet.example.internal:8443 ^
FLEET_TOKEN=<bootstrap-token> ^
FLEET_VERIFY_MODE=none FLEET_INSECURE=1
The enrollment response carries the certificate this agent pins from then on and the key it trusts for executable bundles, so an unverified enrollment hands both to whoever answered - and the pinning then works perfectly, against the wrong server. Only on a network you trust.
Checking the enrollment¶
Enrollment failures fail the install, so a non-zero exit code from msiexec is the first signal. The reason is in the
log you asked for with /l*v:
findstr /i fleet install.log
The bootstrap token is kept out of that log, but the log names the server, where the identity was written and, on a failure, what went wrong. After a successful install:
security\agent-state.jsonexists, beside the installation by default or underC:\ProgramData\NSClient++\withLAYOUT=modern.nsclient.inihas gainedfleet = ${fleet-folder}/fleet.iniunder[/includes].- the host leaves awaiting enrollment on the fleet server once the service has started and completed its first sync.
What the installer does¶
During the install NSClient++ generates a key pair, sends a certificate request together with the token to
FLEET_SERVER, and stores the certificate material it gets back as agent-state.json in the security folder. It also
adds an include for the fleet-managed configuration ([/includes] fleet = ${fleet-folder}/fleet.ini). The service picks
all of this up on the next start and begins syncing its configuration from the fleet server; there is no module to
enable.
Both land wherever the host’s layout puts them - beside the installation by default, or under
C:\ProgramData\NSClient++\ with LAYOUT=modern. The include is written as the ${fleet-folder} token rather than a
resolved path, so it follows the layout rather than pinning it.
A few things worth knowing:
- Enrollment is required to succeed. If the fleet server cannot be reached, or rejects the token, the install fails
with an error explaining what went wrong rather than leaving you with an agent that never joined the fleet. Bootstrap
tokens are one-time and are burned on first use, so a rejected token means generating a new install command. A
certificate verification failure happens before the token is sent, so that token survives: fix
FLEET_CAand run the same command again. - The installer has to be allowed to write the configuration. Enrollment is what adds the include that makes the
host read what the fleet server sends it, so combining
FLEET_SERVERwithALLOW_CONFIGURATION=0- or installing onto a configuration the installer cannot update - fails the install rather than enrolling a host that then ignores everything the fleet server tells it. The install log names the reason the configuration was held to be unchangeable. - An already enrolled host keeps its identity. If
agent-state.jsonalready exists (an upgrade, a repair, or a re-install over an existing installation) the enrollment is skipped and the existing identity is kept. Delete the file to enroll again. - Uninstalling discards the enrollment.
agent-state.jsonholds this host’s private key and client certificate, so uninstalling removes it along with the other key material. The identity does not survive an uninstall/reinstall cycle, and because bootstrap tokens are one-time you need a fresh install command from the fleet server to enroll again - keep the host’s registration on the server in mind before uninstalling to reinstall. Upgrading in place is unaffected. - The fleet server is verified. The enrollment response supplies the certificate the agent pins for every later call
and the key it trusts for executable bundles, so the connection is verified against the Windows ROOT store by default.
Use
FLEET_CA=<file>if the fleet server uses a private CA.FLEET_INSECURE=1(with ahttp://url and/orFLEET_VERIFY_MODE=none) opts out of that, which is only reasonable on a trusted network or for testing. - Keep the token out of your logs. The token is hidden from the MSI log, but treat the deployment script that carries it as a secret; the token is a credential that exchanges for this host’s client certificate.
Enrolling after installation¶
The same enrollment can be done after installation with the command line, and is how a Linux host enrolls since there is no MSI there:
nscp enroll --server https://fleet.example.com --token <bootstrap-token>
Add --ca <file> when the fleet server does not have a publicly trusted certificate -
which includes the self-signed one it generates for itself by default. See
Give the agents something to trust.
Installing your own TLS certificates¶
The MSI itself ships no certificates: when a TLS-enabled server (NRPE, WEB, …) starts and finds nothing at its default certificate path, the service generates a per-host self-signed certificate there. That gets you encryption out of the box, but a self-signed certificate is exactly what a monitoring server cannot verify - so a silent install can hand the installer CA-signed material instead:
msiexec /qn /i NSCP-<version>-x64.msi CERTIFICATE=c:\certs\myhost.pem CERTIFICATE_KEY=c:\certs\myhost.key CERTIFICATE_CA=c:\certs\my-ca.pem
The files are copied into the security folder under the default names every server module reads
(certificate.pem, certificate_key.pem and ca.pem), wherever the host’s layout puts that
folder. Because the files exist, the service never generates its self-signed fallback, and no per-module certificate
configuration is needed.
CERTIFICATEis the server certificate (chain) in PEM format. If the private key is embedded in the same file - the NSClient++ convention, and what the generated certificate looks like - it is all you need to pass.CERTIFICATE_KEYis the private key when you keep it in a separate file. The modules default to reading the key from the certificate file, so the installer also points the NRPE and WEB servers at it (certificate key = ${certificate-path}/certificate_key.pem); for other servers (NSCA, check_mk, check_nt) add the samecertificate keysetting to their section by hand. PassingCERTIFICATE_KEYtherefore requires the installer to be allowed to write the configuration (do not combine it withALLOW_CONFIGURATION=0).CERTIFICATE_CAis the CA (bundle) the servers verify client certificates against - whatNRPEMODE=SECURE’sverify mode = peer-certchecks the connecting monitoring server against. It is independent of the other two: passing onlyCERTIFICATE_CAkeeps the generated server certificate but pins who may connect.
A few things worth knowing:
- A wrong command line fails the install. A missing file, a certificate and key swapped, or a certificate with no
key anywhere (neither embedded nor via
CERTIFICATE_KEY) fails before anything is copied, rather than installing an agent that silently serves the self-signed fallback - or nothing at all. - The properties are one-shot. They name files on the installing machine at install time; the installer copies
them and does not remember where they came from. Re-run the installer with the properties (or replace the files in
the
securityfolder) to rotate the material - passing them again on an upgrade replaces the installed copies. - Uninstalling removes the copies. The installed
certificate.pem,certificate_key.pemandca.pemare cleaned up with the rest of the key material; the files you pointed the properties at are yours and are left alone. - They configure the servers, not the installer. These certificates are what the agent serves. They are unrelated
to
TLS_CA/FLEET_CA, which tell the installer what to trust when it connects out (to a settings or fleet server).
To do the same after installation, use nscp nrpe install --certificate ... --certificate-key ... and
nscp web install --certificate ... --certificate-key ... - see Securing NSClient++.
Copy configuration from a HTTP server¶
Staring with version 0.10.5 it is possible to download a configuration file from a HTTP server and use that as the configuration for NSClient++.
msiexec /i NSClient++.msi IMPORT_CONFIG=http://myserver.com/nsclient.ini
Use configuration from a HTTP server¶
A simple way to manage NSClient++ configuration is to use the HTTP configuration backend. This way you can manage the configuration from a central server and all your clients will automatically pick up the configuration from there. Any changes you make to the configuration file on the server will automatically be picked up by the clients.
msiexec /i NSClient++.msi CONFIGURATION_TYPE=http://myserver.com/nsclient.ini
Verifying the settings server¶
Over https the installer verifies the server certificate before it uses what
it downloaded - that file becomes the whole configuration of the agent,
including its external script definitions, so whoever can answer for the
settings host would otherwise own the machine.
The certificate is checked against the Windows ROOT certificate store, which the
installer exports to a temporary bundle for the duration of the install (the
service maintains its own copy at ${ca-path}, but that file does not exist yet
while the installer is running). Nothing needs to be configured for a settings
server whose certificate was issued by a public CA, or by an internal CA that
has been rolled out to the machine’s trust store.
For a private CA that is not in the Windows store, point TLS_CA at the
issuing CA instead:
msiexec /i NSClient++.msi CONFIGURATION_TYPE=https://myserver.com/nsclient.ini TLS_CA=c:\certs\my-ca.pem
TLS_CA is used verbatim and replaces the exported store, so it also works for
pinning a single issuer. It is written to boot.ini, so the service keeps using
it for later fetches.
As a last resort verification can be turned off with TLS_VERIFY_MODE=none,
which makes the download trust whatever answers. Do this only on a network you
control; it is the one setting that turns a compromised or spoofed settings
server into remote code execution on every agent that boots against it.