This page builds a real config against jaque's schema one addition at a time: a host, a service, a shared template, contacts and a policy, labels, zones, and finally how a config is validated. Every snippet is loadable as written, with the schema filling each default it does not state. Why CUE is the argument for the language; this page is the practice, and the config schema is the reference every key here is documented in.

1. The smallest config

hosts: gw: {
	address: "192.168.1.1"
	check: {type: "icmp", host: address}
}

One host, ICMP checked every 60 seconds, which is #Schedule's default check_interval. host: address reuses the field set two lines up: CUE resolves references within the same struct, so the IP is written once.

2. A host with a service

hosts: gw: {
	address: "192.168.1.1"
	check:   {type: "icmp", host: "192.168.1.1"}
	services: web: check: {type: "http", url: "http://192.168.1.1/"}
}

Every service under a host is checked independently, with its own #Schedule. A service does not inherit its host's check_interval; what it inherits is the host's reachability, through the dependency graph, which is a different thing.

3. A shared template

Ten devices of the same kind should not repeat their check config ten times. Anchor a partial struct on #Host (or #Check) and unify it at each use site; Why CUE walks the #CastDevice example and explains why anchoring on the schema rather than a bare struct is what keeps a typo in the template a validation error instead of a silently ignored field.

4. Contacts, a policy, and an escalation

contacts: {
	alice: {type: "email", address: "alice@example.com"}
	oncall_hook: {type: "webhook", url: "https://hooks.example.com/oncall"}
}

notifications: business_hours: {
	period: [
		{weekday: "monday", start: "09:00", end: "17:00"},
	]
	levels: [
		{contacts: ["alice"], threshold: 3, renotify_interval: "30m"},
		{contacts: ["oncall_hook"], renotify_interval: "10m"},
	]
}

hosts: gw: {
	address: "192.168.1.1"
	check: {type: "icmp", host: "192.168.1.1"}
	notification: "business_hours"
}

notification names a policy in the top-level notifications map and defaults to empty, which means the object never notifies: every config written before policies existed keeps the behaviour it had. Every contact type, the escalation semantics and the window grammar are in Contacts and policies and Escalations and windows.

5. Labels and views

hosts: web: {
	address: "10.0.0.1"
	check:   {type: "icmp", host: "10.0.0.1"}
	labels:  {env: "prod", role: "web"}
}

views: prod: selector: "env=prod"

Labels and views has the key and value constraints, the selector grammar and what a saved view is.

6. Zones

zone defaults to "default" on a host. A service's zone defaults to "", which inherits the host's:

hosts: gw: {zone: "eu-west"}
services: web: {}  // inherits "eu-west"

A zone is the work queue a check dispatches to; it matters only in a split topology with -target worker processes, and is documented there.

7. Validating a config

There is no separate jaque validate subcommand: loading is validating.

jaque -config yourfile.cue

Validation runs in two phases and the error differs by which one catches the problem. A schema-constraint failure (an unknown field, a wrong type, a community beside a user) is reported against the field. A concretion failure (a value left unresolved, a required field with no default such as a passive check's freshness_threshold) is reported against the field that never became concrete. Why CUE explains the two phases; the operator-facing consequence is that the error names a field, never "config invalid".

8. Security considerations

A config file carries secrets in plain text: vars such as a host password, resources, an SNMP community, a contact's webhook URL. File permissions are their only protection, and a command template with shell: true interpolates them into a shell line (see Command checks, section 4). Credentials that are per instance rather than per object, such as a Telegram bot token or SMTP credentials, are process flags and not config fields, precisely so that the config file can be shared more freely than the process environment.