---
myst:
html_meta:
"description": "Configure S3 object storage for the cdk8s-monitoring stack: Crossplane buckets for Thanos and Loki, and External Secrets that replicate credentials into the monitoring namespace."
"property=og:description": "Configure S3 object storage for the cdk8s-monitoring stack: Crossplane buckets for Thanos and Loki, and External Secrets that replicate credentials into the monitoring namespace."
"property=og:title": "Configure S3 credentials"
"keywords": "cdk8s, Kubernetes, monitoring, S3, Crossplane, External Secrets, Thanos, Loki"
---
# Configure S3 credentials
This guide shows you how to supply the object storage configuration the stack needs for Thanos metrics and Loki logs.
The library creates the buckets through Crossplane and replicates the credentials through External Secrets Operator, but it relies on cluster-level resources you provide.
## Provide the S3 block
Set the `s3` block in your `mergeConfig` input.
Both endpoint forms are required: the full URL for Loki, and the host-only form for the Thanos object store config.
```typescript
const config = mergeConfig({
// other required cluster values ...
s3: {
endpoint: 'https://fsn1.your-objectstorage.com',
endpointNoProtocol: 'fsn1.your-objectstorage.com',
region: 'fsn1',
buckets: { thanos: 'metrics-thanos-prod', loki: 'logs-loki-prod' },
},
});
```
## Name the external resources
The stack does not create the Crossplane provider config or the External Secrets stores it relies on.
You create those in your cluster under names of your choosing and pass the names through the `integrations` block.
```typescript
const config = mergeConfig({
// other required cluster values ...
integrations: {
s3ProviderConfig: 'my-s3-provider',
s3SecretStore: 'my-s3-secret-store',
s3CredentialsKey: 'my-s3-credentials',
grafanaSecretStore: 'my-app-secret-store',
grafanaCredentialsKey: 'my-grafana-admin',
},
});
```
The names above are placeholders.
Replace each with the name your cluster uses for that resource.
## What the library creates
From this block the stack synthesizes:
- A Crossplane `Bucket` for Thanos and one for Loki, both in the `crossplane-system` namespace, with versioning and lifecycle rules.
- A Thanos `ExternalSecret` that reads the source credentials and renders a `thanos-objstore-config` secret with an `objstore.yml` key.
- A Loki `ExternalSecret` that renders a `loki-s3-credentials` secret with `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
## Provide the cluster-level resources
The synthesized resources expect these to already exist.
The Crossplane provider config and credentials
: The `Bucket` resources are reconciled by Crossplane in `crossplane-system`.
A `ProviderConfig` and its credentials secret must point at your S3 endpoint.
Pass the provider config name as `integrations.s3ProviderConfig`.
The S3 `ClusterSecretStore`
: Both `ExternalSecret`s reference the store named by `integrations.s3SecretStore`.
Create that store and point it at the namespace holding the source credentials.
The source credentials secret
: Both `ExternalSecret`s extract from the remote key named by `integrations.s3CredentialsKey` in that store.
The resolved secret must hold `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
```{important}
The store and key names are not fixed in the library; you choose them and surface them through `integrations`.
Make sure the values you pass for `integrations.s3SecretStore` and `integrations.s3CredentialsKey` match resources that actually exist, or the External Secrets will fail to resolve.
```
## Verify
After deployment, confirm the buckets reconciled and the secrets materialized.
```shell
kubectl get buckets.s3.aws.upbound.io -n crossplane-system
kubectl get externalsecrets -n monitoring
kubectl get secret thanos-objstore-config loki-s3-credentials -n monitoring
```
## See also
- {doc}`setup-prerequisites` — install Crossplane and External Secrets Operator.
- {doc}`../explanation/architecture` — how Thanos and Loki use object storage.