> Section: [4. Configuration](https://jaque.sh/docs/config/cue-in-practice.md)
> Next: notifications/contacts-and-policies
> Index: https://jaque.sh/llms.txt


This is a systematic reference, one section per top-level CUE definition in
`config/schema.cue`: every field, its type, its default and the
constraint the schema enforces on it. For a guided, example-driven
walkthrough of building a config against this schema, see [CUE in
practice](../config/cue-in-practice.md) instead.

## 1. `#Schema`

The root object a config file unifies against. Closed: an unknown
top-level regular field is a schema error.

| Field | Type | Default | Constraint |
|---|---|---|---|
| `hosts` | `{[Name=string]: #Host}` | - | required (may be empty) |
| `resources` | `#Resources` | `{}` | see `#Resources` |
| `commands` | `{[Name=string]: #Command}` | `{}` | see `#Command` |
| `contacts` | `{[Name=string]: #Contact}` | `{}` | see `#Contact` |
| `notifications` | `{[Name=string]: #NotificationPolicy}` | `{}` | see `#NotificationPolicy` |
| `views` | `{[Name=string]: #View}` | `{}` | see `#View` |
| `sinks` | `{[=~"^[a-z][a-z0-9_-]*$"]: #Sink}` | - | optional, see `#Sink` |
| `timezone` | `string` | `"Local"` | non-empty; the IANA zone every timeperiod without its own `timezone` is read in |
| `timeperiods` | `{[Name=string]: #TimePeriod}` | `{}` | see `#TimePeriod` |
| `downtimes` | `{[Name=string]: #Downtime}` | `{}` | see `#Downtime` |
| `slos` | `{[Name=string]: #SLO}` | `{}` | see `#SLO` |
| `dependencies` | `{[Name=string]: #Dependency}` | `{}` | see `#Dependency` |
| `handlers` | `{[Name=string]: #Handler}` | `{}` | see `#Handler` |
| `event_handlers` | `#EventHandlers` | `{}` | see `#EventHandlers` |

## 2. `#Host`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `address` | `string` | - | required, non-empty |
| `parents` | `[...string]` | `[]` | - |
| `vars` | `#Vars` | `{}` | see `#Vars` |
| `check` | `#Check` | - | required |
| `services` | `{[Name=string]: #Service}` | `{}` | - |
| `notification` | `string` | `""` | empty means the host never notifies |
| `zone` | `string` | `"default"` | non-empty |
| `labels` | `#Labels` | `{}` | see `#Labels` |
| `handler` | `string` | `""` | empty means no handler; otherwise a key into the top-level `handlers` map |
| `handler_enabled` | `bool` | `true` | - |

## 3. `#Service`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `vars` | `#Vars` | `{}` | see `#Vars` |
| `check` | `#Check` | - | required |
| `notification` | `string` | `""` | empty means the service never notifies |
| `zone` | `string` | `""` | empty inherits the host's `zone` |
| `labels` | `#Labels` | `{}` | see `#Labels` |
| `handler` | `string` | `""` | empty means no handler; otherwise a key into the top-level `handlers` map |
| `handler_enabled` | `bool` | `true` | - |

## 4. `#Command`

A command template: instantiated by `#CommandCheck` (a check) and by the
`command` contact type, both via a name that is a key into the top-level
`commands` map.

| Field | Type | Default | Constraint |
|---|---|---|---|
| `line` | `string` | - | required, non-empty |
| `shell` | `bool` | `false` | `false` tokenizes `line`; `true` hands it whole to `/bin/sh -c` after macro expansion |

## 5. `#Schedule`

Embedded by every branch of `#Checks`.

| Field | Type | Default | Constraint |
|---|---|---|---|
| `check_interval` | `time.Duration` | `"60s"` | `> 0` |
| `retry_interval` | `time.Duration` | `"15s"` | `> 0` |
| `timeout` | `time.Duration` | `"10s"` | `> 0` |
| `max_attempts` | `int` | `3` | `>=1` |
| `flap` | `#Flap` | - | required, see `#Flap` |
| `check_period` | `string` | `""` | name of a timeperiod; empty means the check is never gated by a calendar |

## 6. `#Flap`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `enabled` | `bool` | `true` | - |
| `alpha` | `number` | `0.1` | `>0 & <=1` |
| `high_threshold` | `number` | `0.3` | `>=0 & <=1` |
| `low_threshold` | `number` | `0.15` | `>=0 & <=high_threshold` |
| `notify_on_flap_stop` | `bool` | `false` | `true` sends the problem notification right after `FlappingStop` on the same result, instead of waiting for the next result to re-notify |

## 7. The `#Checks` branches

Every branch unifies `#Schedule` with its own type-specific fields;
`type` is the discriminator and matches the branch's key in `#Checks`.

### 7.1 `tcp` (`#TCPCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"tcp"` |
| `address` | `string` | - | required, non-empty (`"host:port"`) |

### 7.2 `http` (`#HTTPCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"http"` |
| `url` | `string` | - | required, non-empty |

### 7.3 `dns` (`#DNSCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"dns"` |
| `server` | `string` | - | required, non-empty (`"host:port"`) |
| `name` | `string` | - | required, non-empty (record to resolve) |

### 7.4 `icmp` (`#ICMPCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"icmp"` |
| `host` | `string` | - | required, non-empty |

### 7.5 `tls` (`#TLSCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"tls"` |
| `address` | `string` | - | required, non-empty |
| `warn_within` | `time.Duration` | `"336h"` | - |
| `crit_within` | `time.Duration` | `"72h"` | - |

### 7.6 `snmp` (`#SNMPCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"snmp"` |
| `address` | `string` | - | required, non-empty |
| `oid` | `string` | - | required, non-empty |
| `community` | `string` | - | v2c; required, non-empty when set |
| `user` | `string` | - | v3 USM; required, non-empty when set |
| `auth_proto` | `string` | `""` | `""`, `"MD5"`, `"SHA"`, `"SHA224"`, `"SHA256"`, `"SHA384"`, `"SHA512"` |
| `auth_pass` | `string` | `""` | - |
| `priv_proto` | `string` | `""` | `""`, `"DES"`, `"AES"`, `"AES192"`, `"AES256"`, `"AES192C"`, `"AES256C"` |
| `priv_pass` | `string` | `""` | - |
| `warn` | `string` | `""` | Nagios threshold range; mutually exclusive with `expect` |
| `crit` | `string` | `""` | Nagios threshold range; mutually exclusive with `expect` |
| `expect` | `string` | `""` | exact-match string; mutually exclusive with `warn`/`crit` |
| `label` | `string` | `""` | perfdata point name; the OID when empty |
| `uom` | `string` | `""` | raw Nagios UOM for gauge values; ignored for counters, which are always `c` |

Exactly one of `community` or `user` must be set; the schema enforces
this as a disjunction. `auth_proto`/`auth_pass`/`priv_proto`/`priv_pass`
are only meaningful alongside `user`.

### 7.7 `legacy` (`#LegacyCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"legacy"` |
| `path` | `string` | - | required, non-empty |
| `args` | `[...string]` | `[]` | - |

### 7.8 `wasm` (`#WASMCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"wasm"` |
| `module` | `string` | - | required, non-empty (path to a `.wasm` file) |
| `args` | `[...string]` | `[]` | - |

### 7.9 `command` (`#CommandCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"command"` |
| `command` | `string` | - | required, non-empty; key into the top-level `commands` map |
| `args` | `[...string]` | `[]` | - |

### 7.10 `passive` (`#PassiveCheck`)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"passive"` |
| `freshness_threshold` | `time.Duration` | - | required, no default |
| `stale_status` | `string` | `"UNKNOWN"` | `"UNKNOWN"`, `"WARNING"`, `"CRITICAL"` |

`timeout` (from `#Schedule`) has no meaning for `passive`.

## 8. `#TimePeriod`

A named timeperiod, in Nagios's own syntax. `ranges` maps a date
expression (`"monday"`, `"2026-12-25"`, `"july 4"`, `"day 21 - 25 / 2"`,
`"monday 3 july"`, `"monday -1"`) to a time list
(`"09:00-17:00,18:00-20:00"`; `"00:00-00:00"` closes the day). See
[Timeperiods](https://jaque.sh/docs/config/timeperiods.md) for the full range syntax and
how a day resolves.

| Field | Type | Default | Constraint |
|---|---|---|---|
| `timezone` | `string` | `""` | empty inherits the top-level `timezone` |
| `ranges` | `{[string]: string}` | - | required (may be empty) |
| `exclude` | `[...string]` | `[]` | names of other timeperiods to carve out of this one |

## 9. `#Downtime`

A recurring downtime: every object `selector` matches, of the given
`scope`, is in downtime whenever the named timeperiod is open. See
[Downtimes](https://jaque.sh/docs/config/downtimes.md).

| Field | Type | Default | Constraint |
|---|---|---|---|
| `selector` | `string` | - | required, non-empty; a [label selector](https://jaque.sh/docs/config/labels-and-views.md) |
| `scope` | `string` | - | required; `"host"` or `"service"` |
| `period` | `string` | - | required, non-empty; name of a timeperiod |
| `comment` | `string` | `""` | free text |

The map key under `downtimes:` is the recurring downtime's name. `period`
must name a declared timeperiod, and `selector` must match at least one
object of `scope`; either is a config error otherwise.

## 10. `#Dependency`

An explicit dependency: while `on` yields a status in `fails_on`, the
dependents' notifications are suppressed per `suppress`. See
[Dependencies](https://jaque.sh/docs/config/dependencies.md).

| Field | Type | Default | Constraint |
|---|---|---|---|
| `dependents` | `[#DependencyTarget, ...]` | - | required, non-empty; each is `{ref: string}` or `{select: string}` |
| `on` | `#Rule` | - | required |
| `fails_on` | `[#DependencyFailure, ...]` | - | required, non-empty; `"ok"`, `"warning"`, `"critical"`, `"unknown"`, `"pending"`, `"unreachable"` |
| `suppress` | `string` | `"all"` | `"all"` or `"problems"` |
| `states` | `string` | `"hard"` | `"hard"` or `"soft"` |
| `inherits` | `bool` | `false` | - |
| `period` | `string` | `""` | empty means the dependency always applies; otherwise the name of a timeperiod |

The map key under `dependencies:` is the dependency's name. Every ref in
`dependents` and in `on` must resolve, every `select` must match at
least one object, and `period` must name a declared timeperiod; a
dependent that is also a ref of its own rule, or a cycle across several
dependencies, is a config error.

## 11. `#Handler` and `#EventHandlers`

A handler is one of the three command shapes a check already has, plus
a timeout. See [Event handlers](https://jaque.sh/docs/config/event-handlers.md).

### `#Handler`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | `"legacy"`, `"command"` or `"wasm"`; same fields as the matching `#Checks` branch (7.7, 7.9, 7.8) |
| `timeout` | `time.Duration` | `"30s"` | - |

### `#EventHandlers`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `enabled` | `bool` | `true` | - |
| `host` | `string` | `""` | empty means no global host handler; otherwise a key into the top-level `handlers` map |
| `service` | `string` | `""` | empty means no global service handler; otherwise a key into the top-level `handlers` map |

The map key under `handlers:` is the handler's name. `event_handlers.host`
and `event_handlers.service`, and a host's or a service's own `handler`,
must each name a declared entry; a `command` handler must also name a
declared entry in the top-level `commands` map.

## 12. `#View`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `selector` | `string` | - | required; parsed into a selector at decode time |
| `description` | `string` | `""` | free text, unparsed |

The map key under `views:` is the display name. It is unconstrained, no
pattern, unlike `#Labels`' keys, because it is never parsed.

## 13. `#Labels`

| Position | Pattern |
|---|---|
| key | `=~"^[a-z][a-z0-9_.-]*$"` |
| value | `=~"^[a-zA-Z0-9][a-zA-Z0-9_.:/-]*$"` |

These patterns are copied from the single definition the runtime enforces
internally; a test pins the two copies together so drift fails the build.

## 14. `#Vars`

| Position | Pattern |
|---|---|
| key | `=~"^[A-Z][A-Z0-9_]*$"` |
| value | `string` |

A key `PASSWORD` on a host is referenced as `$_HOSTPASSWORD$`; on a
service, as `$_SERVICEPASSWORD$`. See [Security considerations](#security-considerations).

## 15. `#Resources`

| Position | Pattern |
|---|---|
| key | `=~"^USER[0-9]+$"` |
| value | `string` |

A key that is not `USER<digits>` is a config error rather than a
silently unreachable value.

## 16. `#Contact` and the contact types

Seven discriminated variants of `#Contact`, each also carrying `labels`
(`#Labels`, default `{}`) and `notification_period` (`string`, default
`""`, name of a timeperiod; empty means the contact is always
reachable). `email`, `webhook`, `telegram` and `slack` also
carry `group_wait` (`time.Duration`, default `"0s"`), the digest window
described in [Adapters](https://jaque.sh/docs/notifications/adapters.md#grouping).

### `email`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"email"` |
| `address` | `string` | - | required, non-empty |

### `webhook`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"webhook"` |
| `url` | `string` | - | required, non-empty |

### `command`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"command"` |
| `command` | `string` | - | required, non-empty; key into the top-level `commands` map |
| `args` | `[...string]` | `[]` | - |
| `address` | `string` | `""` | what `$CONTACTEMAIL$` expands to for this contact |

### `telegram`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"telegram"` |
| `chat_id` | `string` | - | required, non-empty |

### `pagerduty`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"pagerduty"` |
| `routing_key` | `string` | - | required, non-empty; the Events API v2 routing key of the service |

### `slack`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"slack"` |
| `webhook_url` | `string` | - | required, non-empty; the incoming webhook URL, which is also the credential |

### `incidentio`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `type` | `string` | - | fixed `"incidentio"` |
| `alert_source_config_id` | `string` | - | required, non-empty; the API token is the process flag `-incidentio-token` |

## 17. `#NotificationPolicy`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `period` | `string` | `""` | name of a timeperiod; empty means always |
| `levels` | `[...#EscalationLevel]` | - | required, non-empty |

## 18. `#EscalationLevel`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `contacts` | `[...string]` | - | required, non-empty |
| `threshold` | `int` | `0` | `>=0`; `0` means never escalate past this level |
| `renotify_interval` | `time.Duration` | `"1h"` | - |
| `disabled_kinds` | `[...string]` | `[]` | each one of `"PROBLEM"`, `"RECOVERY"`, `"STATUS_CHANGE"`, `"FLAPPING_START"`, `"FLAPPING_STOP"`, `"ACKNOWLEDGEMENT"`, `"DOWNTIME_START"`, `"DOWNTIME_END"`, `"DOWNTIME_CANCELLED"`, `"CUSTOM"` |
| `period` | `string` | `""` | name of a timeperiod; empty means the level is always open |

## 19. `#Sinks`

Every sink shares `#SinkCommon`, then adds its own type-specific fields.
The map key under `sinks:` matches `=~"^[a-z][a-z0-9_-]*$"`.

### `#SinkCommon` (shared by every sink type)

| Field | Type | Default | Constraint |
|---|---|---|---|
| `input` | `string` | `"metrics"` | `"metrics"` or `"events"` |
| `selector` | `string` | `""` | a labels selector expression |
| `batch_size` | `int` | `1000` | `>0` |
| `flush_interval` | `time.Duration` | `"5s"` | - |

### Per-type fields

| Type | Field | Type | Default | Constraint |
|---|---|---|---|---|
| `clickhouse` | `url` | `string` | - | required, non-empty |
| `clickhouse` | `table` | `string` | `"perfdata"` | `=~"^[A-Za-z_][A-Za-z0-9_]*$"` |
| `remote_write` | `url` | `string` | - | required, non-empty |
| `remote_write` | `cursor` | `string` | `""` | - |
| `archive` | `url` | `string` | - | required, non-empty |
| `archive` | `segment_bytes` | `int` | `67108864` | `>0` |
| `archive` | `input` | `string` | - | fixed `"events"` |
| `http` | `url` | `string` | - | required, non-empty |
| `http` | `headers` | `{[string]: string}` | `{}` | - |
| `http` | `cursor` | `string` | `""` | - |
| `exec` | `command` | `[string, ...string]` | - | required, non-empty |
| `exec` | `cursor` | `string` | `""` | - |
| `file` | `path` | `string` | - | required, non-empty |
| `file` | `rotate_bytes` | `int` | `67108864` | `>0` |
| `file` | `cursor` | `string` | `""` | - |
| `otlp` | `url` | `string` | - | required, non-empty |
| `otlp` | `headers` | `{[string]: string}` | `{}` | - |
| `otlp` | `cursor` | `string` | `""` | - |

## 20. Security considerations

The config file is plaintext CUE on disk rather than a secrets store.
`#Vars` values are free-form strings and commonly carry material like SNMP
community strings or plugin passwords, expanded into check and
notification command lines via `$_HOSTxxx$`/`$_SERVICExxx$` macros. File
permissions on the config path are the only protection. `#SNMPCheck`'s
`auth_pass`/`priv_pass` are the same: plaintext in the file, plaintext in
the resulting SNMP request per the v3 USM protocol. Sink and contact URLs
(`clickhouse`, `remote_write`, `http`, `otlp`, `webhook`) can embed
credentials in their query string or headers; `QueryService.ListSinks` and
`ListContacts` omit these fields from their response so the
API surface never echoes them back (see [Command and query
service](../api/command-and-query-service.md)). Long-lived secrets that
apply process-wide, the SMTP password, the Telegram bot token, are kept
out of CUE entirely and passed as CLI flags or env vars instead; see
[CLI flags](https://jaque.sh/docs/reference/cli-flags.md), section 10.

## 21. The auth document (`-auth-config`), a separate schema

Not to be confused with `#SNMPCheck`'s `auth_proto`/`auth_pass` in
section 7.6, which are per-check SNMP v3 credentials. This section
describes `config/auth_schema.cue`, a schema entirely separate from
`#Schema` above. It governs the document passed via `-auth-config`, not
`-config`: `#Schema` (section 1) has no `auth` field, and a document
loaded as `-config` cannot declare identities. See [CLI
flags](../reference/cli-flags.md) for the flag and [Security
considerations](../deployment/security.md) for why identities live
outside `-config` and what `-session-secret` does with them.

### `#Schema` (auth document)

The root object `-auth-config`'s file unifies against.

| Field | Type | Default | Constraint |
|---|---|---|---|
| `auth` | `{[Name=string]: #Identity}` | - | required, and must declare at least one identity; the map key is the identity's name |

### `#Identity`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `role` | `string` | `"viewer"` | `"viewer"`, `"operator"`, `"admin"`, ranked in that order |
| `password_hash` | `string` | - | exactly one of `password_hash`/`token_hash` required; both or neither is a config error |
| `token_hash` | `string` | - | exactly one of `password_hash`/`token_hash` required; both or neither is a config error |

Identities are read once at process boot; changing this document
requires restarting jaque, unlike `-config`, which reloads on SIGHUP.

## 22. `#SLO`

| Field | Type | Default | Constraint |
|---|---|---|---|
| `selector` | `string` | - | required, non-empty; a [label selector](https://jaque.sh/docs/config/labels-and-views.md) |
| `target` | `number` | - | required; `>0` and `<=100` |
| `period` | `string` | `""` | empty means the whole report range; otherwise the name of a timeperiod |
| `exclude_downtimes` | `bool` | `true` | - |
| `down_statuses` | `[...string]` | `[]` | `"WARNING"`, `"CRITICAL"` or `"UNKNOWN"`; empty means every problem status |

The map key under `slos:` is the display name. It is unconstrained, no
pattern, unlike `#Labels`' keys, because it is never parsed. `slos`
requires `ui.availability` to be declared; `period` must name a declared
timeperiod.
