# Quickstart

> From your account to first telemetry in under ten minutes. One container in your compose file, two labels on your existing services, and you're done.

Canonical: https://docs.getlumin.dev/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

Create an account at **[app.getlumin.dev/signup](https://app.getlumin.dev/signup)**. Every account starts on the free Hobby tier, and signup needs no card. The [Terms of Service](https://getlumin.dev/terms) and the [Privacy Policy](https://getlumin.dev/privacy) apply.

Once your account exists, sign in at **[app.getlumin.dev](https://app.getlumin.dev/login)**. 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

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](https://docs.getlumin.dev/stacks/browser/).

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

Add three blocks to your existing `docker-compose.yml`:

```yaml
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_healthy
```

Put `LUMIN_AGENT_API_KEY=lmn_priv_…` in your `.env` next to the compose file, then:

```sh
docker compose up -d lumin-docker-proxy lumin-agent
```

The 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](https://docs.getlumin.dev/agent/install/#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](https://docs.getlumin.dev/agent/install/#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](https://docs.getlumin.dev/agent/security/) for why mounting `/var/run/docker.sock:ro` directly is not safe.

## 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:

```yaml
services:
  api:
    image: my-api:latest
    labels:
      lumin.logs: "true"
      lumin.service: "api"   # optional; defaults to container name
```

Redeploy 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

If a service already exposes a Prometheus `/metrics` endpoint (Spring Boot Actuator, `prometheus/client_golang`, FastAPI middleware, …), three more labels are all you need:

```yaml
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 | axum
```

The `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](https://docs.getlumin.dev/stacks/) for the exact metric names each framework emits and the `framework` value to pass.

## 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](https://docs.getlumin.dev/stacks/browser/) for the full setup.

## Where to go next

- **[Container labels reference](https://docs.getlumin.dev/agent/labels/)** — every `lumin.*` label the agent reads, with semantics.
- **[Stack guides](https://docs.getlumin.dev/stacks/)** — pick your framework.
- **[Projects & API keys](https://docs.getlumin.dev/concepts/projects-and-api-keys/)** — how the tenancy model works, when to mint a new project, how to rotate keys safely.
