Server

Nagios Active vs Passive Checks, and When to Use Each

By Prabath Thalangama· October 24, 2026· 3 min read
#nagios#monitoring#alerting

Introduction

Nagios (and its forks — Icinga, Naemon, Nagios Core) supports two ways a check result gets into the system. Picking the right one per service avoids both missed outages and needless load. This post explains the two models and the one setting that makes passive checks trustworthy.

Concepts

Active check — Nagios itself runs a plugin on a schedule (check_interval), the plugin exits 0/1/2/3 (OK/WARNING/CRITICAL/UNKNOWN) with a one-line summary, and Nagios records that. This is the default and what most check_http, check_ssh, check_disk definitions are.

Passive check — something else produces the result and submits it to Nagios via the external command file or a transport like NSCA / the Nagios API. Nagios doesn't schedule anything; it just receives.

Use active when Nagios can reach the thing and running the check is cheap: ping, TCP ports, HTTP endpoints, SNMP, SSH-based checks.

Use passive when:

  • The check must run on a host Nagios can't log into (a DMZ box pushing results out).
  • The event is asynchronous — a backup job reporting success/failure when it finishes, a log-watcher firing on a pattern, a cron job checking itself in.
  • You're aggregating from another system (a CI pipeline, a custom script).

Hands-on

An active check

define service {
    host_name               web1
    service_description      HTTPS
    check_command            check_http!-S -H app.example.com -u /healthz
    check_interval           1        # minutes
    retry_interval           1
    max_check_attempts       3        # soft->hard after 3 failures
    check_period             24x7
}

A passive check with freshness

define service {
    host_name               backup-host
    service_description      Nightly Backup
    check_command            check_dummy!3 "No result submitted yet"
    passive_checks_enabled   1
    active_checks_enabled    0
    check_freshness          1
    freshness_threshold      93600    # seconds: 26h — job runs daily
    check_period             24x7
    max_check_attempts       1
}

Freshness checking is the important part. Without it, a passive service that stops reporting stays green forever — the backup host could be dead and Nagios wouldn't know. With check_freshness 1 and a freshness_threshold, Nagios runs the check_command (here check_dummy 3 "..." → UNKNOWN/stale) if no result arrives within the window. Set the threshold to a bit more than the expected interval between submissions.

Submitting a passive result

The backup script, at the end, appends to the command file:

CMD="/var/lib/nagios/rw/nagios.cmd"
NOW=$(date +%s)
STATUS=0   # 0 OK, 2 CRITICAL
MSG="Backup completed: 4.2 GB in 11m"
printf "[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n" \
  "$NOW" "backup-host" "Nightly Backup" "$STATUS" "$MSG" > "$CMD"

Remote hosts use send_nsca (paired with an nsca daemon on the Nagios server) or, on Icinga 2, the REST API.

Verification and troubleshooting

  • Passive service stuck OK / "PENDING" forever — check_freshness isn't enabled, or accept_passive_service_checks is off globally (nagios.cfg).
  • "Service results are stale" flapping — the freshness_threshold is tighter than the real submission interval, or the submitter's clock is skewed (the [timestamp] in the command must be recent).
  • PROCESS_SERVICE_CHECK_RESULT silently ignored — the service name / host name in the command must match the config exactly, and the command file is a named pipe: use >, and only when nagios is running to read it.
  • Active check works from the CLI but not in Nagios — path and environment differ. Run it as the nagios user: sudo -u nagios /usr/lib/nagios/plugins/check_http ....
  • Everything goes CRITICAL at once — the Nagios server lost network or DNS, not the monitored hosts. Add a "canary" active check to something always-up.
PrabathStuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.