2026-06-24 17:13:44 +02:00
|
|
|
services:
|
|
|
|
|
fleet-prometheus:
|
|
|
|
|
# Pinned to the Prometheus 3.5 LTS line — NEVER :latest. The home `prom`
|
|
|
|
|
# on PIHA runs :latest, which is the anti-pattern we are deliberately not
|
|
|
|
|
# repeating here: a fleet liveness source must be reproducible.
|
|
|
|
|
image: prom/prometheus:v3.5.0
|
|
|
|
|
container_name: fleet-prometheus
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
command:
|
|
|
|
|
- '--config.file=/etc/prometheus/prometheus.yml'
|
|
|
|
|
- '--storage.tsdb.path=/prometheus'
|
|
|
|
|
# Tight VPS (3.7 GiB RAM + 4 GiB swap): keep the TSDB small. Whichever
|
|
|
|
|
# of time/size is hit first triggers compaction/deletion.
|
|
|
|
|
- '--storage.tsdb.retention.time=15d'
|
|
|
|
|
- '--storage.tsdb.retention.size=2GB'
|
|
|
|
|
# Allow `POST /-/reload` so liveness rules (added in a later step) can be
|
|
|
|
|
# hot-loaded without restarting and losing the scrape gap.
|
|
|
|
|
- '--web.enable-lifecycle'
|
|
|
|
|
volumes:
|
|
|
|
|
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
|
|
|
|
- fleet_prometheus_tsdb:/prometheus
|
|
|
|
|
ports:
|
2026-06-24 17:38:48 +02:00
|
|
|
# tailscale-internal: the listen socket is bound ONLY to the VPS Tailscale
|
|
|
|
|
# interface IP (TAILSCALE_BIND_IP), never 0.0.0.0. The port therefore does
|
|
|
|
|
# not exist on the public Hetzner IP at all — reachability is enforced in
|
|
|
|
|
# the bind itself (defense-in-depth), not solely by the host firewall.
|
|
|
|
|
# brain-watchdog on PIHA reaches this over the VPS Tailscale IP.
|
|
|
|
|
# Requires --env-file services/fleet-prometheus/.env at deploy (see README).
|
|
|
|
|
# Do NOT add this to npm / public DNS.
|
|
|
|
|
- "${TAILSCALE_BIND_IP}:9090:9090"
|
2026-06-24 17:13:44 +02:00
|
|
|
# node_exporter on the VPS runs with network_mode: host, so it listens on
|
|
|
|
|
# the host's :9100. This bridged container reaches it via host-gateway.
|
|
|
|
|
extra_hosts:
|
|
|
|
|
- "host.docker.internal:host-gateway"
|
|
|
|
|
# Memory: VPS has 4 GiB RAM. 512m cgroup ceiling; Docker restarts the
|
|
|
|
|
# container on breach. oom_score_adj is POSITIVE on purpose — fleet
|
|
|
|
|
# monitoring is less critical than the control-plane (-900), so the host
|
|
|
|
|
# OOM-killer should sacrifice this container FIRST, never the control-plane.
|
|
|
|
|
mem_limit: 512m
|
|
|
|
|
oom_score_adj: 200
|
|
|
|
|
# The prom/prometheus image is busybox-based and ships `wget` (but no curl),
|
|
|
|
|
# so an in-container HTTP check works here — unlike the vikunja image, which
|
|
|
|
|
# had neither and broke its healthcheck permanently.
|
|
|
|
|
healthcheck:
|
|
|
|
|
test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:9090/-/healthy"]
|
|
|
|
|
interval: 30s
|
|
|
|
|
timeout: 10s
|
|
|
|
|
retries: 5
|
|
|
|
|
start_period: 30s
|
|
|
|
|
|
|
|
|
|
volumes:
|
|
|
|
|
fleet_prometheus_tsdb:
|
|
|
|
|
name: fleet-prometheus_tsdb
|