Quickstart
This is the golden path: account → API key → drop the agent into Compose → see logs and metrics in the UI.
You will not write any application code in this guide. The agent collects host and container metrics, tails container stdout/stderr, and scrapes any Prometheus /metrics endpoint you already expose — opt-in per container via Docker labels.
1. Get an account
Section titled “1. Get an account”Create an account at app.getlumin.dev/signup. Every account starts on the free Hobby tier, and signup needs no card. The Terms of Service and the Privacy Policy apply.
Once your account exists, sign in at app.getlumin.dev. The ten minutes this guide promises start now.
You land in a default project. Projects are the unit of tenancy — every API key, every log row, every metric belongs to exactly one project. For now, the default project is fine; you can rename it under Settings → Project.
2. Mint an API key
Section titled “2. Mint an API key”Open Settings → API keys → New key. Name it something like lumin-agent and leave Kind on “Server / agent” (the default). You will see a key that starts with lmn_priv_… — copy it now. Lumin never shows the secret again.
Browser app instead? Pick Kind = Browser SDK instead. You’ll get a
lmn_pub_*key that can only post browser events — safe to bake into a frontend bundle. See the Browser SDK guide.
This key authenticates the agent. It is a write-only ingest credential: it can POST /v1/logs, /v1/metrics, /v1/events, and /v1/agent/snapshot for this project only. It cannot read any data and cannot reach the app UI. If it ever leaks, rotate it from the same screen.
3. Drop the agent into your Compose file
Section titled “3. Drop the agent into your Compose file”Add three blocks to your existing docker-compose.yml:
services: # ...your existing services...
lumin-docker-proxy: image: wollomatic/socket-proxy:1.13.1 restart: unless-stopped user: "0:0" environment: SP_LISTENIP: 0.0.0.0 SP_ALLOWFROM: lumin-agent SP_ALLOW_HEAD: /_ping SP_ALLOW_GET: '/v1\.[0-9]+/containers/(json|[0-9a-f]{64}/(json|stats|logs))' SP_ALLOWHEALTHCHECK: "true" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro read_only: true cap_drop: [ALL] security_opt: ["no-new-privileges:true"] healthcheck: test: ["CMD", "/healthcheck"] interval: 5s timeout: 3s retries: 5 start_period: 5s
lumin-agent: image: luminmonitor/lumin-agent:latest restart: unless-stopped environment: LUMIN_API_KEY: ${LUMIN_AGENT_API_KEY} # the lmn_priv_... you minted LUMIN_ENDPOINT: https://api.getlumin.dev LUMIN_HOSTNAME: ${HOSTNAME:-prod-1} LUMIN_INTERVAL: 15s DOCKER_HOST: tcp://lumin-docker-proxy:2375 HOST_PROC: /host/proc HOST_SYS: /host/sys volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro read_only: true tmpfs: [/tmp] cap_drop: [ALL] security_opt: ["no-new-privileges:true"] depends_on: lumin-docker-proxy: condition: service_healthyPut LUMIN_AGENT_API_KEY=lmn_priv_… in your .env next to the compose file, then:
docker compose up -d lumin-docker-proxy lumin-agentThe agent will register a host snapshot within fifteen seconds. Open Infrastructure in the UI and the host should appear.
luminmonitor/lumin-agent is public, so the pull needs no docker login. It ships linux/amd64 and linux/arm64 in one manifest — an Arm host (Hetzner CAX, Oracle Ampere, Raspberry Pi) pulls the same tag as an x86 host. Use :latest to follow releases, or pin a version like luminmonitor/lumin-agent:0.1.0 in production. See Image tags and platforms.
Not using Compose? The agent has no Compose dependency — it reads the Docker API and Docker labels. See Run without Compose for the docker run equivalent, and for what works on Swarm, Portainer, and Coolify.
The lumin-docker-proxy sidecar is not optional. It mediates every Docker API call the agent makes. See the agent security model for why mounting /var/run/docker.sock:ro directly is not safe.
4. Opt your existing services into log shipping
Section titled “4. Opt your existing services into log shipping”The agent does not tail any container by default. To stream a container’s stdout/stderr into Lumin, add two Docker labels:
services: api: image: my-api:latest labels: lumin.logs: "true" lumin.service: "api" # optional; defaults to container nameRedeploy with docker compose up -d api. Within thirty seconds the agent discovers the new label, opens a follow-stream against the container, and starts forwarding lines. Open Logs in the UI — WHERE service = "api" should start scrolling in real time.
JSON log lines with a level field are parsed as structured logs (Caddy’s access logs, any logger writing JSON to stdout). Unstructured lines fall back to a best-effort level sniff (error, warn, info, …) and default to INFO when nothing matches.
5. Opt services into metric scraping
Section titled “5. Opt services into metric scraping”If a service already exposes a Prometheus /metrics endpoint (Spring Boot Actuator, prometheus/client_golang, FastAPI middleware, …), three more labels are all you need:
services: api: image: my-api:latest labels: lumin.logs: "true" lumin.service: "api" lumin.metrics: "true" lumin.metrics.port: "8080" lumin.metrics.framework: "gin" # gin | spring | express | fastapi | axumThe framework label tells the agent how to normalise stack-specific names into Lumin’s canonical http.requests / http.latency_ms / http.errors schema, so different services chart side by side. See the stack guides for the exact metric names each framework emits and the framework value to pass.
6. (Optional) Add the browser SDK
Section titled “6. (Optional) Add the browser SDK”If you want per-user session timelines, install @lumin-monitor/browser in your frontend. The same guide covers how to tag your server-side logs with the browser session id so you can filter them with attr.session_id:…. See the Browser SDK guide for the full setup.
Where to go next
Section titled “Where to go next”- Container labels reference — every
lumin.*label the agent reads, with semantics. - Stack guides — pick your framework.
- Projects & API keys — how the tenancy model works, when to mint a new project, how to rotate keys safely.