# Config as Code Define your monitors and alerts in a YAML file. Version control them, copy them between instances, or spin up a fresh setup in one command. ## Quick start Export what you already have: ```bash goupkeep export -o monitors.yaml ``` That gives you a working file you can edit and re-apply: ```bash goupkeep apply -f monitors.yaml ``` That's it. Apply only creates or updates — it won't delete anything unless you tell it to. ## The YAML file Two top-level sections: `alerts` and `monitors`. Alerts go first because monitors reference them by name. ```yaml alerts: - name: Discord Ops type: discord settings: url: https://discord.com/api/webhooks/your/token - name: PagerDuty Critical type: pagerduty settings: routing_key: your-integration-key severity: critical monitors: - name: API type: http url: https://api.example.com/health interval: 30 alert: Discord Ops - name: Production type: group alert: PagerDuty Critical monitors: - name: Prod Web type: http url: https://prod.example.com interval: 15 - name: Prod DB type: port hostname: db.internal port: 5432 interval: 30 ``` ## Monitor types Each type has required fields. Everything else is optional with sensible defaults. **http** — polls a URL ```yaml - name: My API type: http url: https://api.example.com/health interval: 30 ``` Optional: `method` (default GET), `accepted_codes` (default 200-299), `timeout`, `check_ssl`, `expiry_threshold` (default 7 days), `max_retries`, `ignore_tls`, `description`, `paused`. **ping** — ICMP ping a host ```yaml - name: Gateway type: ping hostname: 10.0.0.1 interval: 30 ``` **port** — check if a port is open ```yaml - name: SSH Server type: port hostname: 10.0.0.1 port: 22 interval: 60 ``` **dns** — resolve a hostname ```yaml - name: DNS Check type: dns hostname: example.com dns_resolve_type: A dns_server: 1.1.1.1 interval: 60 ``` **push** — heartbeat endpoint for cron jobs ```yaml - name: Nightly Backup type: push interval: 86400 ``` Push monitors get a token assigned automatically. Hit the push endpoint before the interval expires or it alerts. **group** — organize monitors together ```yaml - name: Production type: group monitors: - name: Web type: http url: https://prod.example.com interval: 15 ``` Groups can't nest inside other groups. A group is healthy when all its children are healthy. ## Alert types All 9 providers work in the YAML. The `settings` map is different per type. ```yaml # Discord / Slack / Generic Webhook — just a URL - name: Discord Ops type: discord settings: url: https://discord.com/api/webhooks/your/token # Email - name: Email Oncall type: email settings: host: smtp.example.com port: "587" user: oncall@example.com pass: your-password from: oncall@example.com to: team@example.com # Ntfy - name: Ntfy Alerts type: ntfy settings: url: https://ntfy.sh topic: my-alerts priority: "4" # Telegram - name: Telegram Ops type: telegram settings: token: "123456:ABC-DEF..." chat_id: "-1001234567890" # PagerDuty - name: PD Critical type: pagerduty settings: routing_key: your-integration-key severity: critical # Pushover - name: Pushover type: pushover settings: token: app-token user: user-key # Gotify - name: Gotify type: gotify settings: url: https://gotify.example.com token: app-token priority: "8" ``` ## Commands **Export current state:** ```bash goupkeep export -o monitors.yaml # to a file goupkeep export # to stdout ``` **Apply a config:** ```bash goupkeep apply -f monitors.yaml ``` **See what would change first:** ```bash goupkeep apply -f monitors.yaml --dry-run ``` **Delete monitors not in the YAML:** ```bash goupkeep apply -f monitors.yaml --prune ``` Without `--prune`, apply never deletes anything. It only creates and updates. **Pointing at a different database:** ```bash goupkeep export -db-type postgres -dsn "host=localhost dbname=upkeep sslmode=disable" goupkeep apply -f monitors.yaml -db-type postgres -dsn "..." ``` Both commands respect the `UPKEEP_DB_TYPE` and `UPKEEP_DB_DSN` environment variables too. ## How apply works Monitors and alerts are matched by **name**. Names must be unique across the entire file. 1. Alerts are resolved first (created or updated) 2. Groups are created next (so children can reference them) 3. Everything else is created or updated 4. If `--prune` is set, anything in the database that's not in the YAML gets deleted Apply is idempotent. Run it twice with the same file, second run changes nothing. If something fails mid-apply, just fix the issue and run it again. It picks up where it left off. ## Typical workflow ```bash # set up your monitors in the TUI first, then export goupkeep export -o monitors.yaml # commit it git add monitors.yaml && git commit -m "add monitor config" # deploy to another instance scp monitors.yaml prod-server: ssh prod-server goupkeep apply -f monitors.yaml # or just keep it as a backup you can restore from goupkeep apply -f monitors.yaml ```