Observability at Scale
Centralized log aggregation with Loki and Grafana, extending Intermediate's per-service uptime checks, and the real storage cost of long-term high-resolution metrics.
Monitoring and Alerting covered Uptime Kuma (is a service up or down) and a basic Grafana + Prometheus setup (metrics like CPU, RAM, disk over time). Both answer "what's the current state of things." Neither answers "what happened, in detail, across every service, at 3am last Tuesday" - that's what centralized logging is for, and it's the last new capability this guide covers.
Why centralized logs, once you have more than one machine
With one server, journalctl or docker compose logs on that box is
enough - everything relevant is right there. Across a Proxmox cluster
with several VMs each running their own containers, "check the logs"
now means SSHing into several places and remembering which service
lives where. Centralized logging pulls every container and system
log into one searchable place, so debugging a cross-service issue (a
failed deploy that cascades, an auth failure that shows up in three
different services' logs) doesn't mean hopping between hosts.
Loki + Grafana
Loki (Grafana Labs) is a log aggregation system designed to pair
with Grafana - it deliberately indexes only metadata (labels like
container, host, service) rather than full-text indexing every
log line, which keeps it far cheaper to run than something like
Elasticsearch for the same volume of logs. You already have Grafana
from the Intermediate monitoring setup, so Loki slots into the same
dashboard rather than requiring a separate UI.
services:
loki:
image: grafana/loki:3.0.0
container_name: loki
ports:
- "3100:3100"
volumes:
- ./loki-data:/loki
restart: unless-stopped
alloy:
image: grafana/alloy:latest
container_name: alloy
volumes:
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./config.alloy:/etc/alloy/config.alloy
command: run /etc/alloy/config.alloy
ports:
- "12345:12345"
restart: unless-stopped
- Grafana Alloy is the agent that ships logs to Loki - one instance per host, reading local system and container logs and forwarding them with labels (which host, which container) attached. Alloy is the successor to Promtail, which Grafana Labs moved to long-term support in 2025 and ended entirely in March 2026 - don't stand up a new Promtail deployment at this point. Alloy also doubles as an OpenTelemetry Collector if you want that later, which Promtail never did.
- Add Loki as a data source in the Grafana you already have running, then logs and metrics dashboards live side by side.
- Pin image versions explicitly (
3.0.0for Loki above, notlatest)- Loki's config schema has changed across major versions before, and an unplanned upgrade can break ingestion silently.
Long-term metrics: the storage trade-off
Prometheus (from the Intermediate setup) stores metrics at whatever resolution you scrape at - commonly every 15-30 seconds. That resolution is genuinely useful for debugging something that just happened, but it adds up fast: high-resolution data for a fleet of VMs and containers, kept indefinitely, can consume tens of gigabytes a year even for a modest homelab, and Prometheus's default local storage isn't built to be a long-term archive at that granularity.
The realistic options:
- Shorter local retention (Prometheus's default
--storage.tsdb.retention.time, commonly 15 days) for high-resolution recent data, which covers "what happened this week" - the overwhelmingly common use case. - Downsampling for anything kept longer - tools like Thanos or Mimir can store older data at reduced resolution (e.g. 5-minute averages instead of 15-second samples), shrinking storage dramatically for data you're unlikely to need at full precision months later.
- Just don't keep years of high-resolution data - for most homelabs, "is this trending up over months" is answerable from weekly or daily averages, not second-by-second history. Ask what question you're actually trying to answer with old metrics before provisioning storage to keep them all at full resolution.
Same judgment call applies to logs: Loki lets you set retention per label, so noisy, low-value logs (health-check pings, for instance) can expire in days while genuinely useful application logs are kept longer.
With logging, metrics, and their retention trade-offs sorted, the one scenario this guide hasn't touched yet is losing the entire site the homelab lives in - see Multi-Site Homelab for the honest version of that conversation.
Next: Multi-Site Homelab.