Skip to content

Passive Monitoring with NSCA/NRDP

Goal: Have NSClient++ run checks on a schedule and push the results to your monitoring server — without the monitoring server needing to poll each machine.

Tip

Passive monitoring is ideal when the monitored machines are behind a firewall, are in a DMZ, or when you want to distribute the check workload across many agents rather than centralising it on the monitoring server.


How Passive Monitoring Works

In active (NRPE) monitoring, the monitoring server initiates contact and polls the agent:

flowchart LR
    S[Monitoring Server] -->|check_nrpe| A[NSClient++]
    A -->|runs check| R[Result]
    R --> S

In passive monitoring, the agent runs checks on its own schedule and pushes results to the server:

flowchart LR
    S[Scheduler] -->|runs check| C[NSCAClient]
    C -->|NSCA| M[Monitoring Server<br/>NSCA daemon]

The monitoring server simply waits for results. If no result arrives within the expected time window, the monitoring server raises a “freshness” alert.


Prerequisites

Enable these modules in nsclient.ini:

[/modules]
CheckSystem  = enabled   ; provides check_cpu, check_memory, etc.
CheckDisk    = enabled   ; provides check_drivesize
Scheduler    = enabled   ; runs checks on a timer
NSCAClient   = enabled   ; pushes results to the NSCA server

Step 1 — Verify the NSCA Connection

Before configuring scheduled checks, verify that NSClient++ can send a test result to the NSCA server.

nscp nsca --host <nagios-server-ip> ^
    --password secret-password ^
    --encryption aes256 ^
    --command "service check" ^
    --result 2 ^
    --hostname "my-windows-host" ^
    --message "Hello from NSClient++"

Note

The ^ character is the Windows Command Prompt line-continuation character. In PowerShell use a backtick (`) instead, or write the command on a single line.

Expected output:

Submission successful

If you have set up a test result file on the NSCA server, you should see:

[timestamp] PROCESS_SERVICE_CHECK_RESULT;my-windows-host;service check;2;Hello from NSClient++

NSCA server-side configuration

The NSCA daemon needs the matching cipher and password in its nsca.cfg:

decryption_method = 14
password          = secret-password

If you’re troubleshooting the connection, redirect the result file to a path you can tail to see what arrives:

command_file = /tmp/result.txt

Note

The password is a shared secret — both sides must use the same value, and it isn’t authenticated in the cryptographic sense (no challenge/response). Use a strong, long password to make brute-force impractical.

NSCA encryption reference

NSClient++ uses Crypto++; NSCA uses libmcrypt. The two libraries don’t share a common identifier, so the matching is by table:

NSClient++ value NSCA method Security
none 0 ⚠️ Not secure — avoid
xor 1 ⚠️ Not secure — avoid
des 2 ⚠️ Insecure
3des 3 ⚠️ Legacy
cast128 4 🟡 Moderate
xtea 6 🟡 Moderate
blowfish 8 🟡 Moderate
twofish 9 🟢 Very secure
rc2 11 ⚠️ Insecure
aes256 14 ✅ Industry standard (default)
serpent 20 🟢 Paranoid
gost 23 ⚠️ Questionable

AES naming gotcha

NSCA names ciphers by block size, NSClient++ names them by key size. NSCA’s RIJNDAEL-128 (method 14) is what NSClient++ calls aes256 — same algorithm, different label. NSCA only supports AES with a 128-bit block, so the other AES-named NSCA values are not valid choices.


Step 2 — Configure the Scheduler

The Scheduler module runs your checks at regular intervals and sends results to a channel (NSCA by default).

Set default parameters for all scheduled jobs:

[/settings/scheduler/schedules/default]
channel  = NSCA    ; which channel to send results to
interval = 5m      ; how often to run each check
report   = all     ; send results regardless of status (OK, WARN, CRIT)

Add scheduled checks:

[/settings/scheduler/schedules]
; Format: check_name = check_command [arguments...]
host_check = check_ok
cpu        = check_cpu
memory     = check_memory
disk_c     = check_drivesize drive=C: "warn=free < 20%" "crit=free < 10%"

Each key becomes the service name that Nagios/Icinga will see in the passive check result.

Note

The default schedule section applies its settings to all schedules that do not override them. You can override any setting per schedule by creating a dedicated section:

[/settings/scheduler/schedules/disk_c]
command  = check_drivesize drive=C: "warn=free < 20%" "crit=free < 10%"
interval = 15m   ; check disk less often than cpu/memory
channel  = NSCA
report   = all

Schedule options reference

Option Description
interval How often the check runs (e.g. 30s, 5m, 1h). Apply via the default template.
schedule Cron-style alternative to interval (see below). Use one or the other, not both.
command The check command to execute. With short-form (name = command) this is the value.
alias Name reported back to Nagios. Defaults to the schedule key, so usually omitted.
channel Target channel for the result. Defaults to NSCA; set this to fan out to other channels.
report Filter on which results are sent: all, ok, warning, critical, or comma-combinations.

Cron-style schedules

When you need finer control than “every N minutes” — e.g. “47 minutes past every hour”, “weekdays at 06:00”, or “every Sunday at midnight” — use schedule instead of interval. The five fields are the standard cron form: minute hour day-of-month month day-of-week.

[/settings/scheduler/schedules/disk_c]
command  = check_drivesize drive=C: "warn=free < 20%" "crit=free < 10%"
schedule = 47 * * * *      ; 47 minutes past every hour
channel  = NSCA

[/settings/scheduler/schedules/nightly_full]
command  = check_drivesize
schedule = 0 2 * * *       ; every day at 02:00
channel  = NSCA

[/settings/scheduler/schedules/weekday_office]
command  = check_cpu
schedule = */15 8-18 * * 1-5  ; every 15 min, 08:00–18:00, Mon–Fri
channel  = NSCA

Use interval for the simple recurring case; reach for schedule when you need a specific wall-clock time or weekday filter.

Short-form vs. long-form schedules

The [/settings/scheduler/schedules] block supports two equivalent shapes:

; Short form — the key is the alias, the value is the command.
[/settings/scheduler/schedules]
cpu  = check_cpu
mem  = check_memory
; Long form — one section per schedule, more knobs available.
[/settings/scheduler/schedules/cpu]
command  = check_cpu
interval = 30s

[/settings/scheduler/schedules/mem]
command  = check_memory
interval = 5m

Short form is concise but only carries command. Switch to long form when you need per-schedule overrides (interval, channel, alias, report).

Real-time channels

The Scheduler isn’t the only thing that can publish into the NSCA channel. CheckLogFile and CheckEventLog can both publish results in real time — useful for surfacing log/event hits without waiting for the next scheduler tick. They share the same channel mechanism, so a result from CheckEventLog is indistinguishable from a scheduled one on the receiving side.

[/settings/eventlog/real-time/filters/critical-app]
log     = Application
filter  = level = 'error' AND source = 'MyApp'
channel = NSCA

Multiple targets

A single NSCAClient instance handles one target, but you can fan results out to multiple servers (or channels) by combining target sections with the channel knob on each schedule. The receiver matches by channel name.


Step 3 — Configure the NSCA Client

[/settings/NSCA/client/targets/default]
address    = <nagios-server-ip>
encryption = aes256
password   = secret-password

The password must match the password in the NSCA server’s nsca.cfg.


Step 4 — Set the Hostname

NSClient++ must send results using the hostname as it is known in Nagios/Icinga. By default it uses the Windows computer name which may not match.

Auto-detect hostname:

[/settings/NSCA/client]
hostname = auto

Use a specific hostname:

[/settings/NSCA/client]
hostname = win-server-01.example.com

Build the hostname from system variables:

[/settings/NSCA/client]
hostname = ${host_lc}.${domain_lc}

Variables can be combined with literal text — for example to add a win_ prefix on Windows hosts that share a Linux-host naming convention:

[/settings/NSCA/client]
hostname = win_${host_lc}.${domain_lc}

Supported variables:

Variable Meaning
${host} Windows computer name (mixed case)
${host_lc} Lowercase
${host_uc} Uppercase
${domain} Windows domain name
${domain_lc} Domain lowercase
${domain_uc} Domain uppercase
${address_ipv4} IPv4 address of the machine
${address_ipv6} IPv6 address (lowercase, compressed)

The IPv6 address is also available in case and padding variants: ${address_ipv6_lc} / ${address_ipv6_uc} pick the case, and appending _comp / _uncomp (e.g. ${address_ipv6_uc_uncomp}) picks between the compressed (2001:db8::7) and the fully zero-padded (2001:0db8:0000:0000:0000:0000:0000:0007) form.


Step 5 — Restart NSClient++

net stop nscp
net start nscp

After restart, NSClient++ will start executing scheduled checks and pushing results to the NSCA server. Your monitoring tool should begin receiving passive check results within one interval.


Step 6 — Send a Result Without Waiting for the Interval

Waiting five minutes (or an hour) to see whether an edit to nsclient.ini did what you wanted is the slowest possible feedback loop. Three commands let you push a result immediately; they differ in how much of the scheduled pipeline they exercise.

Run the configured schedules now

run_schedules (Scheduler module) runs the schedules you configured in Step 2 right away and submits their results on their normal channel — same command, same arguments, same alias, same target — so what lands on the monitoring server is exactly what the timer would have sent. This is the one to use after a configuration change:

nscp client --boot --query run_schedules
Ran 4 schedule(s): cpu, disk_c, host_check, memory

Add --argument schedule=<alias> to run a single schedule instead of all of them:

nscp client --boot --query run_schedules --argument schedule=disk_c
Ran 1 schedule(s): disk_c

run_schedules is an ordinary check command, so it is equally available over NRPE, in nscp test, and over the REST API — handy for a “push my results now” button:

curl -k -u admin:<password> "https://<agent>:8443/api/v2/queries/run_schedules/commands/execute"

Note

nscp client --boot boots a second, short-lived agent from the same nsclient.ini — it does not talk to the running service, so the results are submitted by that temporary process. Reload the service first (or restart it) if you want the running agent to pick your edit up as well.

Push a check that is not in the schedule

check_and_forward (CheckHelpers module) runs any check and forwards its result as a passive check. Nothing has to be configured in the scheduler first, which makes it a good way to try a new check before adding it:

nscp client --boot --query check_and_forward --argument command=check_cpu --argument alias="CPU Load" --argument channel=NSCA
OK: Message submitted: NSCA
Argument Meaning
command The check to run (required).
arguments Arguments for that check, repeat for more than one.
channel Channel to submit on, defaults to NSCA.
alias Service description to report, defaults to the command name.
destination Which NSCA target to send to, defaults to the client’s default target.
source Host name to report as, defaults to this machine’s.

Note that the OK here only means “handed to the NSCA client” — the status of check_cpu itself is what was submitted and is visible on the monitoring server, not in this reply.

Send a hand-written result

Finally, the nscp nsca form from Step 1 sends a result you write yourself, with no check involved at all. That makes it the right tool for testing connectivity, encryption and host/service naming against the NSCA daemon — and the wrong one for verifying that a check produces what you expect, since the message is whatever you typed:

nscp nsca --host <nagios-server-ip> --password secret-password --encryption aes256 ^
    --command "CPU Load" --result 0 --message "Hello from NSClient++"

Tip

If the reason you are pushing results by hand is that the agent was just restarted or rebooted and the monitoring server is showing stale data, set run on startup = true on the schedules instead — they then run once as soon as the agent is up, and after every configuration reload.


Complete Configuration Example

[/modules]
CheckSystem  = enabled
CheckDisk    = enabled
Scheduler    = enabled
NSCAClient   = enabled

[/settings/NSCA/client]
hostname = ${host_lc}.${domain_lc}

[/settings/NSCA/client/targets/default]
address    = 10.0.0.1
encryption = aes256
password   = s3cr3t_p@ssw0rd

[/settings/scheduler/schedules/default]
channel  = NSCA
interval = 5m
report   = all

[/settings/scheduler/schedules]
host_check = check_ok
cpu        = check_cpu
memory     = check_memory
disk_c     = check_drivesize drive=C: "warn=free < 20%" "crit=free < 10%"

Using NRDP Instead of NSCA

NRDP is a more modern HTTP-based alternative to NSCA. Replace NSCAClient with NRDPClient and update the configuration:

[/modules]
NRDPClient = enabled

[/settings/NRDP/client/targets/default]
address  = http://nagios-server/nrdp/
token    = my-nrdp-token

The scheduler configuration stays the same — just change channel = NSCA to channel = NRDP.

Step 6 works the same way: run_schedules submits on whatever channel each schedule is configured for, check_and_forward takes channel=NRDP, and the hand-written one-off is nscp nrdp --url http://nagios-server/nrdp/ --token my-nrdp-token --command "CPU Load" --result 0 --message "Hello from NSClient++".


Troubleshooting

NSCA is fire-and-forget — the agent doesn’t get a delivery acknowledgement, so a misconfigured client will look fine from NSClient++’s side and silent on the server side. The first place to look is the NSCA daemon log on the monitoring server:

sudo tail -f /var/log/syslog

A successful submission shows up as:

nsca: Connection from 192.168.0.104 port 8198
nsca: Handling the connection...
nsca: SERVICE CHECK -> Host Name: 'win-server-01', Service Description: 'CPU Load',
      Return Code: '0', Output: 'OK CPU Load ok.|...'
nsca: End of connection...

A misconfigured submission usually surfaces as:

nsca: Connection from 192.168.0.104 port 26117
nsca: Handling the connection...
nsca: Received invalid packet type/version from client

That message means almost always one of two things:

  • Wrong password — the shared secret on the agent doesn’t match nsca.cfg’s password.
  • Wrong encryption — the cipher mismatch (e.g. you set encryption = aes256 but the daemon has decryption_method = 9).

If the daemon log is silent altogether, the connection isn’t reaching it — check address, port, firewalls, and allowed_hosts on the NSCA daemon.

To see what NSClient++ is sending, restart it in test mode:

net stop nscp
nscp test

…and watch the trace lines as the scheduler fires. Rather than waiting for the interval, type run_schedules at the nscp test prompt (or run the commands from Step 6) to fire them on demand and watch what happens.


Monitoring Configuration on the Server Side

In Nagios/Icinga, define your services as passive with a freshness threshold:

define service {
    host_name              win-server-01.example.com
    service_description    CPU Load
    check_command          check_dummy!3!"No data received"
    passive_checks_enabled  1
    active_checks_enabled   0
    check_freshness         1
    freshness_threshold     600   ; seconds (10 minutes)
}

Next Steps