# Gatus

Map Gatus endpoints, conditions, and channels to kogut.toml.

There is no Gatus importer. Rewrite `config.yaml` as
[`kogut.toml`](https://docs.kogut.dev/reference/configuration/) using the mappings below.

## Endpoints

| Gatus | `kogut.toml` |
|---|---|
| `endpoints[]` | `[[check]]` |
| `name` | `name`, unique among checks and heartbeats |
| `group` | `service`, required. Use the endpoint name if ungrouped |
| HTTP or HTTPS `url` | `url` |
| `tcp://host:port` | `tcp = "host:port"` |
| `dns.query-name` | `dns`, using `/etc/resolv.conf`, without a custom resolver or record type |
| `icmp://host` | `ping = "host"` |
| `method`, `headers` | `method`, `headers` |
| `interval` | `every` |
| `client.timeout` | `timeout` |

Durations use one number and unit, such as `90m` instead of `1h30m`. Limits and defaults
are in [`[[check]]`](https://docs.kogut.dev/reference/configuration/#check).

Request bodies, GraphQL requests, disabled certificate verification, and disabled
endpoints have no equivalent. TLS, STARTTLS, SSH, UDP, and WebSocket checks have no
matching type. A TCP check tests only whether the port accepts connections.

## Conditions

HTTP conditions map to `expect`. Every assertion must pass.

| Gatus | `kogut.toml` |
|---|---|
| `[STATUS] == 200` | `{ status = 200 }` |
| `[BODY] == pat(*Welcome*)` | `{ body_contains = "Welcome" }` |
| `[BODY].status == UP` | `{ json = "$.status", equals = "UP" }` |
| `[BODY].queue.size == 0` | `{ json = "$.queue.size", equals = 0 }` |
| `[RESPONSE_TIME] < 300` | `{ response_time_below = "300ms" }` |

Without a status assertion, HTTP checks require `2xx`, narrower than `[STATUS] < 300`.
JSON equality keeps types, so `equals = 0` does not match `"0"`. See
[Assertions](https://docs.kogut.dev/monitoring/checks/#assertions).

TCP and DNS checks need no condition. HTTPS checks also watch
[certificate expiry](https://docs.kogut.dev/monitoring/certificates-and-domains/) with fixed thresholds.
`len()`, `has()`, and `!=` have no equivalent. Ping accepts only response-time
assertions.

## External endpoints

`external-endpoints[]` maps to `[[heartbeat]]` with `name`, `service`, and
`every = heartbeat.interval`. Gatus tokens do not transfer. Jobs use new
[heartbeat ping URLs](https://docs.kogut.dev/monitoring/heartbeats/#copy-the-ping-url).

## Notification channels

| Gatus | `[[alert]]` keys |
|---|---|
| Slack or Discord webhook | `type = "slack"` or `"discord"`, `url` |
| Telegram token and id | `type = "telegram"`, `bot_token`, `chat_id` |
| ntfy server, topic, token | `type = "ntfy"`, `url` with topic, `token` |
| Custom webhook | `type = "webhook"`, `url`, with kogut's JSON body |
| Email | `type = "email"`, `smtp`, `username`, `password`, `from`, `to` |

If the Gatus ntfy configuration has no `url`, use `https://ntfy.sh/<topic>` as the
channel's `url`.

Secrets use `${NAME}`, not `$NAME`. Per-endpoint routing and failure or success
thresholds have no equivalent. Host limits, such as a disk at 95%, are set in
[`[[host]]`](https://docs.kogut.dev/reference/configuration/#host). See
[How alerts work](https://docs.kogut.dev/alerts/how-alerts-work/).

## Sign-in

kogut has accounts with [roles](https://docs.kogut.dev/sign-in/roles/) and a separate public
[status page](https://docs.kogut.dev/status-page/). People sign in with a password, through
[OpenID Connect](https://docs.kogut.dev/sign-in/openid-connect/), or through
[forward auth](https://docs.kogut.dev/sign-in/forward-auth/). Gatus's `issuer-url`, `client-id`, and
`client-secret` become `issuer`, `client_id`, and `client_secret`.

## Example

For an HTTP endpoint named `api` in the `backend` group:

```toml title="kogut.toml"
[[check]]
name = "api"
service = "backend"
url = "https://api.acme.com/health"
every = "30s"
expect = [
	{ status = 200 },
	{ json = "$.db", equals = "ok" },
	{ response_time_below = "500ms" },
]

[[alert]]
type = "telegram"
bot_token = "${TELEGRAM_TOKEN}"
chat_id = "-1001234567890"
```
