Skip to content

Contacts and policies

Deciding something is broken and telling the right person are two different problems. This page is the second one: who gets told, and under what rule.

Four kinds, each a discriminated variant of #Contact:

contacts: {
alice: {type: "email", address: "[email protected]"}
oncall_hook: {type: "webhook", url: "https://hooks.example.com/oncall"}
bob: {type: "command", command: "page", args: ["-q"], address: "[email protected]"}
dave: {type: "telegram", chat_id: "555444333"}
}

command contacts invoke a top-level command template — the same indirection command checks use, address filling in whatever $CONTACTEMAIL$ expands to for that contact. webhook and command are how anything not natively supported gets wired in (PagerDuty, Opsgenie, a Slack incoming webhook — whatever speaks HTTP or takes command-line args).

For telegram, see Adapters — the bot token is process-level config, not part of the contact.

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

Wire it to a host or service by name:

hosts: gw: {
address: "192.168.1.1"
check: {type: "icmp", host: "192.168.1.1"}
notification: "business_hours"
services: ssh: {
check: {type: "tcp", address: "192.168.1.1:22"}
notification: "business_hours"
}
}

notification defaults to "" — empty means the object never notifies, which is exactly the behavior every config written before contacts and policies existed already has: adding notifications is opt-in, never a silent behavior change for existing configs.

levels is a non-empty list, evaluated in order — see Escalations and windows for threshold and renotify_interval semantics in full.