# Quadlet unit: loki (rootless, boot-persistent). # # Install path on dankclaw: ~/.config/containers/systemd/loki.container # Unit name: loki.service (container name: loki) # # Log store. This replaces the compose service of the same name in # dankclaw/compose.yaml ("Observability" block). # # IMAGE. franksdank/loki is built locally by deploy-remote.sh # (build_compose_image) from dankclaw/loki/Containerfile: upstream # grafana/loki plus a static busybox, because loki is distroless and the # healthcheck has nothing to run inside it. Pull=never keeps a boot from # trying to fetch that local tag from a registry. The localhost/ prefix is # required — this host's quadlet path cannot resolve a registry-prefixed ref # from local storage at create time. # # PUBLISHING. Bound to 127.0.0.1: Alloy pushes to loki:3100 over # dankclaw_default, Caddy proxies the guarded vhost to loki:3100 the same way, # and the homepage status timer probes 127.0.0.1:3100. Loki has # auth_enabled: false, so the compose service's 0.0.0.0 binding was an # unauthenticated log-ingest and read API on every host interface. # # CONFIG. /opt/loki/config/loki-config.yaml is installed from # shared/loki/loki-config.yaml on every deploy (single-binary, filesystem # storage, 30-day retention). Chunks and rules live in /opt/loki/data. # # Rootless: container root maps to the invoking user (dank), who owns # /opt/loki/data; the image's default user (10001) maps to a subuid that # cannot write it. [Unit] Description=Loki log store (Dankclaw) After=network-online.target Wants=network-online.target [Container] ContainerName=loki Image=localhost/franksdank/loki:latest Pull=never Network=dankclaw_default User=0:0 Exec=-config.file=/etc/loki/loki-config.yaml PublishPort=127.0.0.1:3100:3100 Volume=/opt/loki/config:/etc/loki Volume=/opt/loki/data:/loki # No HealthCmd here on purpose. A unit's HealthCmd reaches podman as # CMD-SHELL, which means `/bin/sh -c ` — and this image is # distroless, with no shell at all. The healthcheck therefore ships in the # image (dankclaw/loki/Containerfile) in exec form, where it also carries its # interval, timeout, start period and retry count. [Service] Restart=always RestartSec=10 [Install] WantedBy=default.target