Configuring object storage for Loki moves log chunks and index data out of local container storage and into a durable backend such as Amazon S3, Google Cloud Storage, Azure Blob Storage, or a compatible object store. Production Loki deployments need this before retained logs can survive pod or node replacement.
The current Loki Helm chart supports object storage through chart values that become Loki storage configuration. The exact provider settings depend on the object store, but the success state is the same: Loki starts, accepts a log line, writes objects to the expected bucket or prefix, and returns the line through LogQL.
Use separate buckets or prefixes for production, staging, and development. Object storage credentials should come from Kubernetes secrets, workload identity, or the cloud provider's native identity mechanism rather than raw keys in values files.
Related: How to configure retention in Loki
Related: How to run Loki with Docker Compose
Related: How to deploy a production LGTM stack
$ aws s3api create-bucket \
--bucket lgtm-loki-prod \
--region us-east-1
{
"Location": "/lgtm-loki-prod"
}
Use the provider and region approved for the deployment. Do not publish real bucket names when they identify a live environment.
$ kubectl create secret generic loki-object-storage \ --namespace monitoring \ --from-literal=AWS_ACCESS_KEY_ID='<access-key-id>' \ --from-literal=AWS_SECRET_ACCESS_KEY='<secret-access-key>' secret/loki-object-storage created
loki: schemaConfig: configs: - from: "2024-04-01" store: tsdb object_store: s3 schema: v13 index: prefix: loki_index_ period: 24h storage: type: s3 bucketNames: chunks: lgtm-loki-prod ruler: lgtm-loki-prod admin: lgtm-loki-prod s3: region: us-east-1 commonConfig: replication_factor: 3
The 24h index period is also required for Loki retention.
Related: How to configure retention in Loki
extraEnvFrom: - secretRef: name: loki-object-storage
Prefer cloud workload identity when the platform supports it. Secret references should not expose access keys in rendered manifests or task logs.
$ helm template loki grafana/loki \ --namespace monitoring \ --values loki-storage.yaml ##### snipped ##### object_store: s3 bucketnames: lgtm-loki-prod
$ helm upgrade --install loki grafana/loki \ --namespace monitoring \ --values loki-storage.yaml \ --wait --timeout 15m Release "loki" has been upgraded. Happy Helming!
$ curl --silent https://logs.example.com/ready ready
$ curl --silent --show-error --request POST \ https://logs.example.com/loki/api/v1/push \ --header 'Content-Type: application/json' \ --data @loki-smoke.json
The payload should use a low-cardinality stream label such as service_name and a current nanosecond timestamp.
$ curl --silent --get https://logs.example.com/loki/api/v1/query_range \
--data-urlencode 'query={service_name="loki-smoke"}' \
--data-urlencode limit=5
{"status":"success","data":{"resultType":"streams","result":[]}}
$ aws s3 ls s3://lgtm-loki-prod/ --recursive 2026-06-21 09:00:00 4096 fake/tenant/index/loki_index_20342.gz 2026-06-21 09:00:01 16384 fake/tenant/chunks/...