> Section: [3. Checks](https://jaque.sh/docs/checks/native-checks.md)
> Next: checks/legacy-exec-plugins
> Index: https://jaque.sh/llms.txt


Most of what an estate needs checked does not need a subprocess: a TCP
connect, an HTTP request, a DNS lookup, a certificate date, an SNMP GET.
jaque runs these six inside the engine process itself: no fork, no
shell, no plugin binary to keep patched. SNMP is one of the six rather than
an add-on because a switch or a router will never run an agent, and polling
it over the wire is the only option that exists. The cost is that a native
check can only do what jaque has written code for; for everything else
there is the [legacy exec protocol](https://jaque.sh/docs/checks/legacy-exec-plugins.md) and
[WASM](https://jaque.sh/docs/checks/wasm-checks.md).

## 1. The six types

Every check is a struct with a `type` discriminator; the schema resolves
the branch from it and rejects any field the branch does not declare.

| Type | Required fields | Result |
|---|---|---|
| `tcp` | `address` (`host:port`) | OK on connect, CRITICAL otherwise. |
| `http` | `url` | 5xx is CRITICAL, 4xx is WARNING, any other response is OK. |
| `dns` | `server` (`server:port`), `name` | OK when `name` resolves against `server`. |
| `icmp` | `host` | OK on echo reply. |
| `tls` | `address`, `warn_within`, `crit_within` | WARNING or CRITICAL as the certificate's expiry comes inside each window. |
| `snmp` | `address`, `oid`, plus v2c or v3 credentials | Evaluated against `warn`/`crit` ranges or an `expect` string. |

## 2. Shapes, from the schema

```cue
services: {
	ssh:  check: {type: "tcp", address: "10.0.0.1:22"}
	web:  check: {type: "http", url: "https://10.0.0.1/"}
	dns:  check: {type: "dns", server: "10.0.0.1:53", name: "example.com"}
	cert: check: {type: "tls", address: "10.0.0.1:443", warn_within: "336h", crit_within: "72h"}
}
```

### 2.1 TLS windows

`tls` defaults to `warn_within: "336h"` (14 days) and `crit_within: "72h"`
(3 days). The defaults are wide on purpose: a failed certificate rotation
should give the operator a real window to notice, not a same-day scramble.

### 2.2 ICMP without root

`icmp` uses unprivileged datagram sockets (`udp4`), so the binary needs no
capability and no setuid bit. The kernel has to permit it: on most Linux
distributions run
`sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"` (or a narrower
group range) or every `icmp` check returns UNKNOWN with permission denied.

### 2.3 SNMP: v2c or v3, never both

```cue
check: {
	type:    "snmp"
	address: "10.0.0.254:161"
	oid:     "1.3.6.1.2.1.1.3.0"
	community: "public"
	// or, for v3 USM:
	// user:       "monitor"
	// auth_proto: "SHA256" // "", "MD5", "SHA", "SHA224", "SHA256", "SHA384", "SHA512"
	// auth_pass:  "..."
	// priv_proto: "AES256" // "", "DES", "AES", "AES192", "AES256", "AES192C", "AES256C"
	// priv_pass:  "..."
	warn:   "" // Nagios-style threshold range, or...
	crit:   "" // ...another one, or...
	expect: "" // ...an exact-match string. Mutually exclusive.
	label:  "" // perfdata point name (default: the oid)
	uom:    "" // raw Nagios UOM for gauges: "%", "KB", "B"...
}
```

The schema is a disjunction: a check carries either `community` (v2c) or
`user` (v3 USM), and `auth_proto`, `auth_pass`, `priv_proto` and
`priv_pass` are only meaningful beside `user`. A config naming both fails
validation before jaque opens a socket. With `warn`, `crit` and `expect`
all empty, the check is presence-only: OK when the OID answers.

Every numeric answer is emitted as a perfdata point, thresholds or not, so
an SNMP check doubles as a metric source for cpu, memory and interface
octets. `label` names the point (the OID by default) and `uom` gives it a
unit; counters need neither: a Counter32/Counter64 on the wire is emitted
with the `c` UOM regardless of `uom` and lands in `jaque_perfdata_total`,
where `rate()` belongs.

## 3. Scheduling

Native checks share `#Schedule` with every other check type:
`check_interval` (default `60s`), `retry_interval` (default `15s`),
`timeout` (default `10s`), `max_attempts` (default `3`) and `flap`. The
[State model](https://jaque.sh/docs/concepts/state-model.md) says what each of those numbers
controls; nothing about a native check changes it.

## 4. Concurrency and jitter

Two flags bound how much runs at once. `-global-concurrency` (default 50)
caps checks in flight across the whole process. `-host-concurrency`
(default 4) caps them per host, so one host that is timing out on every
service cannot hold the scheduler's budget for everyone else. Each object's
schedule also carries a deterministic jitter derived from a hash of its own
ID, so 500 checks loaded with the same `check_interval` do not fire in the
same instant on every cycle.

## 5. Security considerations

`community`, `auth_pass` and `priv_pass` are secrets written in the config
file; the file's permissions are the only thing protecting them, and SNMP
v2c sends the community string in clear on the wire. `http` and `tls`
checks connect to whatever `url` or `address` names, from the engine
process, with the engine's network position. The `ping_group_range` sysctl
above widens who on the host may open ICMP datagram sockets; narrow it to
the group jaque runs as.
