# Configure

Source: https://www.pingtower.com/docs/addons/config/

One YAML file. The agent refuses to start on anything it does not understand, which is the point.

```yaml
# /etc/addons/agent.yaml
agent:
  id: probe-fra-01
  region: eu-fra
  tower:
    url: https://api.pingtower.com        # or your own box
    token_env: PINGTOWER_INGEST_TOKEN     # read from /etc/addons/agent.env
  heartbeat: 5m
  max_concurrent: 8
  enable_addons: [sshcheck]               # privileged addons must be listed
  enable_sensors: []

defaults:
  interval: 60s
  sample_interval: 60s
  timeout: 10s
  report: on_change

checks:
  - id: api-health
    addon: httpcheck
    interval: 30s
    down_level: 500                       # 500 pages; 400 is the default
    with:
      url: https://api.acme.example/healthz
      expect_status: 200
      max_ttfb: 800ms

  - id: api-cert
    addon: tlscert
    interval: 6h
    with:
      address: api.acme.example:443
      warn_before: 336h                   # 14 days; default is 21

  - id: box-login
    addon: sshcheck
    interval: 5m
    with:
      address: 10.0.0.12:22
      user: probe
      key_file: /etc/addons/probe_ed25519
      command: systemctl is-active postgresql
      expect_output: active
```

## `agent`

| Field | Default | Meaning |
| --- | --- | --- |
| `id`<span class="req">REQUIRED</span> | | Stable name. Carried on every event and the heartbeat's identity. |
| `region` | | Free-form label carried on every event. |
| `tower.url` | | Where to POST. `https://api.pingtower.com`, or your box. |
| `tower.token_env` | `PINGTOWER_INGEST_TOKEN` | Environment variable holding the `pti_` token. Never a config value, so it stays out of the file. |
| `tower.max_rps` | | Cap on the agent's own send rate. |
| `tower.spool_dir` | `/var/lib/addons/spool` | Where events wait out an outage. |
| `tower.spool_max_bytes` | 64 MiB | Oldest events are dropped past this. |
| `heartbeat` | `5m` | How often the agent reports on itself. |
| `max_concurrent` | 8 | Checks running at once. |
| `enable_addons` | `[]` | Privileged addons this agent may run. An unknown or non-privileged name is a startup error. |
| `enable_sensors` | `[]` | Sensors this agent may run. Same rule. |
| `state_dir` | beside the spool | Where addons that need a baseline, like `hostmetrics`, keep it. |

## `defaults` and per-check fields

Every field here can be set once under `defaults` and overridden per check.

| Field | Default | Meaning |
| --- | --- | --- |
| `interval` | `60s` | How often to run. |
| `timeout` | `10s` | Per run. A timeout is a down verdict with the reason. |
| `report` | `on_change` | `on_change` sends on a status transition plus one sample per `sample_interval`. `on_breach` also keeps sending every run while the check is not up. `always` sends every run. |
| `sample_interval` | `60s` | Under `on_change` and `on_breach`, the cadence of the "still here" sample. |
| `down_level` | 400 | Level of the event when the check is down. Set 500 for a check that should page. |

Per check only:

| Field | Meaning |
| --- | --- |
| `id`<span class="req">REQUIRED</span> | Stable name. Becomes the `check:<id>` tag. |
| `addon`<span class="req">REQUIRED</span> | One from the [catalogue](/docs/addons/#the-catalogue). |
| `with` | The addon's own parameters. An unknown key is a startup error. |

## Validate and try

```sh
addons agent --config /etc/addons/agent.yaml --check     # parse and validate, then exit
addons list                                               # every addon, parameter and default
addons check tlscert --param address=example.com:443      # run one check once, print the event
addons check tlscert --param address=example.com:443 --report   # and send it
```

`addons check` reads the token from the environment, never a flag.

## Sensors

Sensors have their own list and their own gate. See [Sensors](/docs/addons/sensors/).

```yaml
agent:
  enable_sensors: [nftwatch, network]

sensors:
  - id: host-firewall
    sensor: nftwatch
    with: { netns: host, settle: 250ms, reconcile: 5m }
```
