NOOB2ROOT

Field Guide Detection & monitoring

Loki

Grafana's log database. It indexes only a few labels and scans compressed logs at query time, which is why it runs comfortably on a Raspberry Pi.

#What it is

Loki stores logs. Its trick is what it doesn't do: rather than indexing every word of every line (like Elasticsearch or Splunk), it indexes only a small set of labels, such as job="pihole", and stores the log lines compressed. At query time it picks the right streams by label and scans them. You query it with LogQL, usually through Grafana.

#Why I use it

It's the storage layer of my home SIEM. DNS logs from Pi-hole and honeypot logs from OpenCanary land here and are kept for 30 days. A full-text-indexing store would be far too heavy for a 4 GB Pi; Loki barely notices.

If you know Splunk: Loki is roughly the indexer, Alloy is the Universal Forwarder, and Grafana is the search head.

#Benefits

  • Light. Small index, compressed chunks, modest RAM.
  • Retention is one setting (retention_period: 720h with the compactor enabled).
  • Bound to localhost in my setup, so nothing on the LAN can talk to it directly; only Grafana and Alloy on the same box can.

#Trade-offs

  • Searching lots of data is slower than a full-text index, because it scans. At home volumes you won't notice.
  • Keep labels few and boring. Putting something like a client IP or domain into a label creates a stream per value and hurts performance. Extract those at query time instead.

#Gotchas I hit

  • The packaged config stores data under /tmp, which is wiped on every reboot on Trixie. Point path_prefix at /var/lib/loki.
  • chown loki:loki fails, because the loki user's primary group is nogroup. Use chown -R loki: /var/lib/loki; the trailing colon means "the user's own group".
  • "Ingester not ready: waiting for 15s" is normal warm-up. A completely blank response from /ready means Loki isn't running; check journalctl -u loki.

← All Field Guide entries