Files
serverAppConfigs/dankclaw/observability/quadlet/alertmanager.container
T
Frank d2810ab610 feat(security): digest-pin every registry image on all three hosts (fleet law)
Closing the command-center security queue #70/#71/#72/#73/#74: rolling tags
let a rebuild move under a running service with nobody approving it, and
make a CVE audit ungradeable. 36 quadlet units across dankclaw, dankserver
and frankbook-pro now carry tag@sha256; localhost/* builds stay exempt
(their build is the pin). The pihole and copyparty pins pull the fixed
builds; valkey 9.1.2 (already running) and redis 7.4.11 are pinned in
place, vendor fixes TBD.

New gate tests/quadlet_image_pins.bats: no unpinned registry image, no
generator-rejected key anywhere. Three seams that pinned the old exact-tag
law (frankbook readarr, open_webui, seerr) now require tag AND digest -
strictly stronger. Quadlet Lifecycle docs: batch-abort law, entrypoint
flags-only law, pin law.
2026-10-21 16:32:36 -07:00

55 lines
2.2 KiB
INI

# Quadlet unit: alertmanager (rootless, boot-persistent).
#
# Install path on dankclaw: ~/.config/containers/systemd/alertmanager.container
# Unit name: alertmanager.service (container name: alertmanager)
#
# The delivery half of the LLM alert rules. Until 2026-09-17 the rules in
# shared/prometheus/rules/llm-fleet.yml evaluated and reached nobody — a
# firing alert was visible in Prometheus and on the Grafana dashboard and
# nowhere else, and an undelivered alert looks identical to a quiet one.
# This unit closes that gap: Prometheus pushes to alertmanager:9093 over the
# dankclaw_default network, and the single receiver webhooks the host-side
# signal-relay user unit, which hands the text to signal-cli under Frank's
# existing Signal account.
#
# PUBLISHING. 127.0.0.1 only, like every other observability unit: the
# unauthenticated Alertmanager API (lifecycle endpoints are always on in
# this binary — there is no flag to gate them) has no business on a host
# interface, and no off-host consumer needs it. Caddy gains no vhost for
# it; the homepage timer probes loopback.
#
# CONFIG. /opt/alertmanager/config/alertmanager.yml is installed from
# shared/prometheus/alertmanager.yml by deploy-remote.sh on every deploy, so
# the repo copy is the source of truth. STATE lives in /opt/alertmanager/data.
#
# Rootless: container root maps to the invoking user (dank) in this user
# namespace and dank owns /opt/alertmanager/data. The image's default user
# (nobody) maps to a subuid that cannot write it — same User=0:0 as prometheus.
[Unit]
Description=Alertmanager alert delivery (Dankclaw)
After=network-online.target
Wants=network-online.target
[Container]
ContainerName=alertmanager
Image=docker.io/prom/alertmanager:latest@sha256:e9733bafb1bdef9b00e25a21f8f99dc26a22224bf16641ad754d1649f4c3357a
Network=dankclaw_default
User=0:0
Exec=--config.file=/etc/alertmanager/alertmanager.yml --storage.path=/alertmanager
PublishPort=127.0.0.1:9093:9093
Volume=/opt/alertmanager/config:/etc/alertmanager
Volume=/opt/alertmanager/data:/alertmanager
HealthCmd=wget --spider -q http://localhost:9093/-/healthy
HealthInterval=30s
HealthTimeout=10s
HealthRetries=3
HealthStartPeriod=30s
[Service]
Restart=always
RestartSec=10
[Install]
WantedBy=default.target