What's Changed
NSClient++ 0.11.33 Release Notes
Changes since 0.11.32 (commit 06be00cc).
This release is focused on two user-facing areas:
- HTTP proxy support for every HTTP-based client (NRDPClient, ElasticClient, Op5Client, the configuration
loader, ...). - CheckDisk improvements — a new
check_single_filecommand plus five long-standingcheck_filesbug fixes.
HTTP proxy support
NSClient++ can now route HTTP and HTTPS traffic through a corporate proxy. The same configuration surface is used by
every component that builds on the internal http::simple_client (NRDPClient, ElasticClient, Op5Client, the remote
boot.ini loader, ...).
For HTTPS targets the client opens a CONNECT tunnel to the proxy, validates the proxy's response, and only then performs
the TLS handshake — so a single setting covers both http:// and https:// URLs.
Per-target proxy on submit (NRDP, Elastic, Op5)
Two new options are accepted on every HTTP client command and target:
| Option | Purpose |
|---|---|
proxy
| Proxy URL — scheme://[user:pass@]host[:port]/. Empty value disables the proxy.
|
no-proxy
| Comma-separated list of hosts that bypass the proxy. A leading . is a suffix match.
|
Example — submit an NRDP check through a corporate proxy, but never proxy intranet hosts:
nscp client --module NRDPClient --query submit_nrdp \
--host nagios.example.com --token mytoken \
--proxy http://alice:s%40cret@proxy.corp.example:3128/ \
--no-proxy localhost,127.0.0.1,.internal \
--command check_disk --result OK --message "All disks healthy"
The same keys are accepted in nsclient.ini target definitions:
[/settings/NRDP/client/targets/nagios]
address = https://nagios.example.com/nrdp/
token = mytoken
proxy = http://proxy.corp.example:3128/
no proxy = localhost,127.0.0.1,.internalNotes:
- If the proxy needs authentication, embed credentials in the URL — they are sent as
Proxy-Authorization: Basic. Both
@and:inside the username/password must be percent-encoded (alice:s%40cretdecodes toalice:s@cret). - Bypass matching is case-insensitive.
.internalmatches bothfoo.internalandinternal. - On a
407 Proxy Authentication Requiredthe proxy's response body is now captured in the error message, so
misconfigured credentials produce an actionable error instead of an opaque "connect failed".
Proxy for the configuration loader
If boot.ini itself lives behind a proxy, configure it in boot.ini:
[proxy]
url = http://proxy.corp.example:3128/
no_proxy = localhost,127.0.0.1,.internalThe proxy is applied to the initial configuration download, every refresh, and any attachments declared in the remote
configuration. HTTPS targets are tunnelled via CONNECT, so the same setting covers http:// and https:// settings
URLs.
Failed downloads still fall back to the cached copy of the configuration if one is present, so a transient proxy
outage will not stop NSClient++ from starting — but the very first run on a fresh machine needs the proxy to be
reachable.
What is not included
- Only the
http://proxy scheme is supported.socks5:///https://proxies are not. - No automatic detection of system proxy settings (
HTTP_PROXYenv vars, WinINET / WPAD). The proxy must be configured
explicitly.
CheckDisk: new command check_single_file
check_single_file is a focused variant of check_files for inspecting a single, known path. Compared to using
check_files for the same job it has:
- Only one required argument (
file=<path>) — nopath+pattern, nomax-depth, nototal. - A clear error when the input is empty (
No file specified (use file=<path>)). UNKNOWN: File not found: <path>when the file is missing — instead of the empty-set / "No files found" workflow that
surprised users in #613.- A useful default
detail-syntax(%(filename) (size=%(size), age=%(age))) so a no-threshold run is informative on
its own.
All existing filter keywords (size, age, written, version, line_count, type, ...) work, because the
implementation reuses the existing check_files filter machinery.
Examples
Confirm a file exists:
check_single_file file=C:/Windows/System32/notepad.exe
OK: notepad.exe (size=201728, age=12345)
Warn when a file becomes stale:
check_single_file file=C:/windows/WindowsUpdate.log "warn=age > 5m" "crit=age > 1h"
CRITICAL: WindowsUpdate.log (size=276, age=917)
Pin a specific binary version:
check_single_file file="C:/Windows/System32/notepad.exe" \
"crit=version != '1.2.3.4'" \
"detail-syntax=%(filename): %(version)"
CRITICAL: notepad.exe: 6.2.26100.8115
CheckDisk: check_files bug fixes
#730 — max-depth=0 is now "top directory only"
Previously max-depth=0 caused check_files to bail out before scanning anything, returning no files found for users
who simply asked for a non-recursive scan. It is now equivalent to max-depth=1 (scan the top directory, do not
recurse). max-depth=N for N >= 1 is unchanged, so this is not a breaking change for existing configurations.
check_files path=C:/logs pattern=*.log max-depth=0
#598 — Non-ASCII paths now work
Beware that this is still tricky to get right if you are checking from linux via for instance NRPE.
Recursive scanning previously called GetFileAttributes through boost::filesystem's system codepage conversion while
every other Win32 call in the same scan went through UTF-8 conversion. Paths containing accented letters, CJK
characters, etc. were silently mangled and reported as File was NOT found even when they existed. They now work
consistently.
#613 — Missing paths surface as UNKNOWN
If the path passed to check_files could not be opened (typo, deleted directory, permission denied) the failure was
previously hidden behind the configured empty-state — typically OK or a generic No files found. Operators monitoring
file/folder counts therefore got a green status for misconfigured paths.
Top-level paths that cannot be opened now produce an explicit UNKNOWN: Path was not found: <path>, so the failure is
visible in the monitoring system.
#605 — Reparse points are skipped during recursion
NTFS junctions, symlinks and mount points all look like directories, so a tree containing a junction back into itself
was walked twice and files were counted twice. check_files now skips entries whose attributes contain
FILE_ATTRIBUTE_REPARSE_POINT when recursing — the same default as Windows tools like robocopy /XJ. Files matched in
the top-level pass are unaffected.
#717 — Legacy CheckFiles defaults empty-state=ok
The legacy CheckFiles shim translates old-style arguments (path, pattern, MaxWarn, MaxCrit, …) into modern
check_files arguments. Modern check_files defaults empty-state to unknown, which meant a legacy command that
found zero files came back as UNKNOWN even though the original 0.4-era behaviour was to return OK. The shim now sets
empty-state=ok when translating, restoring the legacy semantics.
Other changes
- Numerous small clean-ups across CheckSystem, CheckSystemUnix, CheckNet, NRDPClient, Op5Client, ElasticClient and the
WEB server — internal only, no behaviour change. - New unit test infrastructure for the settings layer (
settings_dummy_test,settings_http_test,settings_ini_test,
settings_interface_impl_test) and 100+ new tests around the HTTP client / proxy code paths. - Linux build is back to green after the proxy work.
Upgrade notes
- No configuration migration is required. All new keys (
proxy,no-proxy, the[proxy]boot.ini section) are opt-in. - The
check_filesfixes change observable behaviour in a few corner cases:max-depth=0now scans the top directory instead of returning empty (#730).- Missing paths now return UNKNOWN instead of OK/empty (#613).
- Junction loops are no longer double-counted (#605).
- Legacy
CheckFilescalls that previously returned UNKNOWN on empty results will now return OK (#717).
If any existing alerting was relying on the old behaviour of these specific corner cases, review it before
upgrading.
Full Changelog: 0.11.32...0.11.33