Configuration

Configure Lookout through a single YAML file at /etc/lookout/config.yaml.

Lookout is configured with one YAML file. The installer writes it to /etc/lookout/config.yaml (mode 600, owned by the lookout user). Edit it and restart the service to apply changes:

sudo nano /etc/lookout/config.yaml
sudo systemctl restart lookout

If the file is missing, Lookout runs on built-in defaults. Out-of-range values are clamped back to safe ones with a warning in the log, so a misconfigured file degrades gracefully instead of crashing or going silent.

Durations are Go-style strings: 5s, 2m, 1h.

Top level

KeyDefaultDescription
collection_interval30sHow often collectors run (minimum 5s)
state_file/var/lib/lookout/state.jsonWhere firing-alert state is persisted across restarts

Alerts

The alerts block holds global timing plus one section per check.

KeyDefaultDescription
renotify_after1hHow long to wait before re-alerting on a still-firing issue
stale_after3 × collection_intervalAlert if a metric stops reporting for this long

Threshold checks

memory, disk, cpu, swap, and load are threshold checks. Each takes:

FieldDescription
thresholdThe value at which the alert starts
resolve_belowThe value at which it clears (defaults to a little under threshold)
forHow long the value must stay over threshold before alerting (0s = immediate)
severitywarning or critical

Keeping threshold and resolve_below apart stops an alert from flapping when a value sits right on the line.

alerts:
  memory:
    threshold: 85        # percent
    resolve_below: 80
    for: 2m
    severity: warning
  cpu:
    threshold: 85
    resolve_below: 80
    for: 2m
    severity: warning
  swap:
    threshold: 80
    resolve_below: 75
    for: 2m
    severity: warning
  load:
    # 1-minute load average divided by CPU cores
    threshold: 1.5
    resolve_below: 1.0
    for: 2m
    severity: warning

Defaults: memory and CPU 85, swap 80 (percent), load 1.5. These five run out of the box.

Disk

Disk is a threshold check with two extras: the mount points to watch, and an optional fill-rate prediction.

alerts:
  disk:
    threshold: 85
    resolve_below: 80
    for: 2m
    severity: warning
    predict_full_within: 4h   # also alert if a mount is on pace to fill within this window
    mounts:
      - /
      - /var

The default mount is /. Set predict_full_within: 0s to disable growth prediction.

Service and presence checks

These have no threshold — they alert when something isn't where it should be. They default to critical severity and do nothing until you list what to watch.

alerts:
  systemd:
    severity: critical
    services:
      - nginx
      - postgresql
  process:
    severity: critical
    names:
      - nginx
  http:
    severity: critical
    checks:
      - name: app
        url: "https://example.com/health"
        timeout: 5s           # default 5s
        expected_status: 200  # default 200
  tcp:
    severity: critical
    checks:
      - name: redis
        address: "127.0.0.1:6379"
        timeout: 5s
CheckAlerts when
systemdA listed service is not active
processA named process isn't found in /proc
httpA URL doesn't return its expected_status within timeout
tcpA TCP address won't accept a connection within timeout

Notifiers

Alerts fan out to every notifier you configure — Google Chat, Discord, Slack, Microsoft Teams, Telegram, PagerDuty, a generic webhook, or email. With none configured, alerts print to the journal. See Notifications for each one.

Heartbeat

Lookout can ping a dead-man's-switch URL on an interval, so you're alerted if the whole box, its network, or the agent itself goes dark. See Heartbeat monitoring.

heartbeat:
  url: "https://lookout.kelvinamoaba.com/ping/lk_ping_xxxxxxxxxxxx"
  interval: 60s

Docker

Container monitoring, off by default. See Docker monitoring.

docker:
  enabled: false
  severity: critical
  restart_threshold: 3
  restart_window: 10m

Prometheus metrics

Optionally expose the latest readings as Prometheus text at GET /metrics. Off by default; serves only the current in-memory snapshot. See Prometheus metrics.

metrics:
  enabled: false
  listen: "127.0.0.1:9100"   # loopback by default

Full example

The complete annotated config — also what the installer writes on first run:

collection_interval: 30s
state_file: /var/lib/lookout/state.json

metrics:
  enabled: false
  listen: "127.0.0.1:9100"

alerts:
  renotify_after: 1h
  stale_after: 90s
  memory:
    threshold: 85
    resolve_below: 80
    for: 2m
    severity: warning
  disk:
    threshold: 85
    resolve_below: 80
    for: 2m
    severity: warning
    predict_full_within: 4h
    mounts:
      - /
  load:
    threshold: 1.5
    resolve_below: 1.0
    for: 2m
    severity: warning
  cpu:
    threshold: 85
    resolve_below: 80
    for: 2m
    severity: warning
  swap:
    threshold: 80
    resolve_below: 75
    for: 2m
    severity: warning
  systemd:
    severity: critical
    services: []
  http:
    severity: critical
    checks: []
  tcp:
    severity: critical
    checks: []
  process:
    severity: critical
    names: []

notifiers:
  # google_chat:
  #   webhook_url: "https://chat.googleapis.com/v1/spaces/XXX/messages?key=...&token=..."
  # discord:
  #   webhook_url: "https://discord.com/api/webhooks/XXX/YYY"

heartbeat:
  # url: "https://lookout.kelvinamoaba.com/ping/lk_ping_xxxxxxxxxxxx"
  interval: 60s

docker:
  enabled: false
  severity: critical
  restart_threshold: 3
  restart_window: 10m