Services

infra / running

Watchtower

Container-update advisor across every Docker LXC. Detects new images, never auto-applies — feeds an n8n + LLM pipeline that scores risk before notifying me.

What it is

Watchtower polls Docker registries for newer versions of every container running on a Docker host. Mine is configured monitor-only — it detects updates and sends notifications, but never pulls or restarts anything. Five instances total, one per Docker LXC, each watching only its local Docker daemon.

Why I run it

Two reasons it's monitor-only rather than auto-applying:

  1. :latest is a surprise generator for stateful services. I learned this loudly during a password-manager upgrade where a point release shipped a UI rendering regression that didn't agree with my browser's cached state. Auto-updating Vaultwarden would have meant a black screen first thing in the morning, not "Watchtower says there's an update — let me read the release notes."
  2. Knowing what's available matters as much as updating it. A weekly inventory of "what's drifted from upstream" is a useful homelab hygiene signal even when I don't intend to update everything.

The next layer up — the one I'm proud of — is the n8n + LLM pipeline that consumes Watchtower's notifications and gives them context. Raw "container X has a new image" isn't actionable. "Container X went from 1.42.3 to 1.43.0, here are the release notes, and the model rates this SAFE / REVIEW / WAIT based on whether the changelog mentions breaking changes" is.

How I use it

Each Docker LXC's Watchtower instance polls every 24 hours and emits a structured report (WATCHTOWER_NOTIFICATION_REPORT=true is critical — without it, the n8n parser only sees raw-text status lines and can't enumerate per-container updates reliably). Reports go to two places:

The advisor workflow filters out startup pings and schedule heartbeats, parses the structured report, deduplicates by image hash, fetches GitHub release notes for known image-to-repo mappings, and sends the whole bundle to a local LLM (currently a 7B Qwen instruct model via LM Studio). The LLM returns a structured JSON verdict — SAFE / REVIEW / WAIT — and a brief rationale. That verdict gets posted as a Discord embed with a link to the release notes.

The Discord channel for advisories is deliberately separate from the channel that receives Grafana alerts and PBS reports. Volume management — I don't want a noisy update notification drowning out a backup failure.

Setup notes

Runbook