# REFERENCE COPY ONLY — configure.py generates observability/alertmanager.yml from ALERT_WEBHOOK_URL and that # generated file is what runs (it omits the Discord receiver's notifier entirely when no webhook is set, so # the config stays valid and alerts simply are not delivered). Never scp this over the generated one. # # Alertmanager: groups what vmalert fires and posts it to Discord. The webhook URL is NOT in here — it is a # secret, so configure.py writes it to /etc/vanguard/alert-webhook with mode 0600 and this reads it from there. # # The "heartbeat" route is the other half of the deadman. The Watchdog alert in alerts-metrics.yml always fires, # so Alertmanager posts a heartbeat to a file-watching receiver every interval; bin/vanguard-deadman.sh on the # host notices when that stops and tells Discord itself. Nothing inside the stack can report its own death. global: resolve_timeout: 5m route: receiver: discord group_by: [alertname, service] group_wait: 30s group_interval: 5m repeat_interval: 12h routes: - matchers: [severity="none"] receiver: heartbeat group_wait: 0s group_interval: 1m repeat_interval: 1m - matchers: [severity="critical"] receiver: discord group_wait: 10s repeat_interval: 1h inhibit_rules: # While the disk is critical, do not also shout that it is merely filling. - source_matchers: [alertname="MediaDiskCritical"] target_matchers: [alertname="MediaDiskFilling"] # If a core container is gone, its restart-loop alert is noise. - source_matchers: [alertname="ContainerGone"] target_matchers: [alertname="ContainerRestartLoop"] receivers: - name: discord discord_configs: - webhook_url_file: /etc/vanguard/alert-webhook title: '{{ if eq .Status "firing" }}🔴{{ else }}✅{{ end }} {{ .CommonLabels.alertname }}' message: | {{ range .Alerts }}{{ .Annotations.summary }} {{ if .Annotations.detail }}{{ .Annotations.detail }} {{ end }}{{ end }} - name: heartbeat # Goes to dumpd on the host (bridge-only port), which touches a file. bin/vanguard-deadman.sh checks that # file is fresh, so a heartbeat never reaches Discord but its ABSENCE does. webhook_configs: - url: http://127.0.0.1:9095/heartbeat send_resolved: false