Configuring tenancy and authentication for the LGTM stack keeps teams from writing or querying each other's observability data by accident. Loki, Tempo, and Mimir can use tenant identifiers such as X-Scope-OrgID, but a production stack still needs an authentication layer in front of those APIs.
Use a gateway, ingress controller, service mesh, or reverse proxy to authenticate clients and forward the correct tenant header to the backend. Grafana data sources should use stable tenant headers or tenant-aware routes, while direct backend access should be blocked from untrusted networks.
Tenant names should be boring and durable, such as platform, payments, or prod. Do not use user email addresses, project secrets, or request IDs as tenant identifiers because those values can leak into logs, metrics, and saved configuration.
$ cat tenants.txt platform payments search
loki: auth_enabled: true tempo: multitenancyEnabled: true mimir: structuredConfig: multitenancy_enabled: true
Exact Helm keys vary by chart and chart version. Render the values before applying them and keep the setting names aligned with the chart currently in use.
routes: - host: logs.example.com backend: loki-gateway requireAuth: true tenantHeader: X-Scope-OrgID - host: traces.example.com backend: tempo-query-frontend requireAuth: true tenantHeader: X-Scope-OrgID - host: metrics.example.com backend: mimir-nginx requireAuth: true tenantHeader: X-Scope-OrgID
$ kubectl apply --namespace monitoring -f gateway-policy.yaml gatewaypolicy.observability.example.com/lgtm-tenancy configured
$ curl --silent --include https://metrics.example.com/prometheus/api/v1/query
HTTP/2 401
content-type: application/json
{"message":"authentication required"}
$ curl --silent --include \ --header 'Authorization: Bearer <token>' \ --header 'X-Scope-OrgID: platform' \ 'https://metrics.example.com/prometheus/api/v1/query?query=up' HTTP/2 200 content-type: application/json
apiVersion: 1 datasources: - name: Mimir platform uid: mimir-platform type: prometheus access: proxy url: https://metrics.example.com/prometheus jsonData: httpHeaderName1: X-Scope-OrgID secureJsonData: httpHeaderValue1: platform
Keep bearer tokens and generated passwords in secrets. Do not commit them in Helm values, data source files, screenshots, or command transcripts.
$ helm upgrade --install grafana grafana/grafana \ --namespace monitoring \ --values values/grafana.yaml \ --wait Release "grafana" has been upgraded. Happy Helming!
$ curl --silent --user admin:<password> \
http://127.0.0.1:3000/api/datasources/uid/mimir-platform
{"uid":"mimir-platform","type":"prometheus","name":"Mimir platform"}
The success state is both sides: rejected unauthenticated access and accepted tenant-scoped access for each backend.