> For the complete documentation index, see [llms.txt](https://docs.keeper.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.keeper.io/keeperpam/secrets-manager/integrations/kubernetes-secrets-injector/examples.md).

# Examples

These are complete, runnable examples for the Kubernetes Injector. Each one assumes you have already **installed the injector** and **created the KSM authentication secret** (`keeper-credentials`) as described on that page.

{% hint style="info" %}
Record and field names below (for example `database-credentials`, `tls-cert`, `Production/Databases`) are **illustrative** - create matching records in your Shared folder that is shared to Keeper Secrets Manager Application, or change the annotations to point at your own records.
{% endhint %}

### Quick check: inject a secret into a Pod

The fastest way to confirm the injector is working - fetch a record to a file and read it. The below .yaml configuration file demonstrates the feature.

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: hello-secrets
  annotations:
    keeper.security/inject: "true"
    keeper.security/ksm-config: "keeper-credentials"
    keeper.security/secret: "demo-secret"
spec:
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "cat /keeper/secrets/demo-secret.json && sleep 3600"]
```

{% code overflow="wrap" %}

```bash
kubectl logs hello-secrets         # prints the record JSON
kubectl get pod hello-secrets -o jsonpath='{.spec.containers[*].name}'   # includes keeper-secrets-sidecar
```

{% endcode %}

### Database credentials as a file

The default mode: the record is written as JSON to `/keeper/secrets/`, and the app reads it.

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 1
  selector: { matchLabels: { app: web } }
  template:
    metadata:
      labels: { app: web }
      annotations:
        keeper.security/inject: "true"
        keeper.security/ksm-config: "keeper-credentials"
        keeper.security/secret: "database-credentials"
    spec:
      containers:
        - name: web
          image: my-app:latest   # reads /keeper/secrets/database-credentials.json
```

### Render a `.env` file

Use the `config` block to choose an output `format`. Here the record is rendered as a `.env` file the app can source.

```yaml
metadata:
  annotations:
    keeper.security/inject: "true"
    keeper.security/ksm-config: "keeper-credentials"
    keeper.security/config: |
      secrets:
        - record: database-credentials
          path: /keeper/secrets/db.env
          format: env
```

```bash
kubectl exec deploy/web -c app -- cat /keeper/secrets/db.env
# LOGIN=app_user
# PASSWORD=...
```

### Build a connection string with a template

Go templates (with [Sprig](https://masterminds.github.io/sprig/) functions) turn record fields into any format - here a Postgres URL.

```yaml
metadata:
  annotations:
    keeper.security/inject: "true"
    keeper.security/ksm-config: "keeper-credentials"
    keeper.security/config: |
      secrets:
        - record: database-credentials
          path: /keeper/secrets/db-url.txt
          template: |
            postgresql://{{ .login }}:{{ .password }}@{{ .host }}:5432/app
```

### Inject as environment variables

For legacy apps that only read env vars. Field names become uppercased keys; add a prefix and fetch once at startup (env vars can't change without a restart).

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: legacy-app
  annotations:
    keeper.security/inject: "true"
    keeper.security/ksm-config: "keeper-credentials"
    keeper.security/inject-env-vars: "true"
    keeper.security/env-prefix: "APP_"
    keeper.security/secret: "database-credentials"
    keeper.security/init-only: "true"
spec:
  containers:
    - name: app
      image: legacy-app:latest   # sees APP_LOGIN, APP_PASSWORD, ...
```

{% hint style="warning" %}
Environment variables are stored in the Pod spec (visible in `kubectl get pod -o yaml`, persisted in `etcd`). Prefer file injection for sensitive values.
{% endhint %}

### Create a Kubernetes Secret for a Deployment

When a workload needs a native `Secret` (for `secretKeyRef`, `envFrom`, or a `Secret` volume), have the injector create one from the record.

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-with-secret
  annotations:
    keeper.security/inject: "true"
    keeper.security/ksm-config: "keeper-credentials"
    keeper.security/inject-as-k8s-secret: "true"
    keeper.security/k8s-secret-name: "app-secrets"
    keeper.security/secret: "database-credentials"
spec:
  containers:
    - name: app
      image: my-app:latest
      env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: password
```

{% code overflow="wrap" %}

```bash
kubectl get secret app-secrets -o jsonpath='{.data}' | jq 'keys'   # ["login","password",...]
```

{% endcode %}

### TLS certificate and key for NGINX

Download file attachments from a Keeper record to a path your app mounts.

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: tls-nginx
  annotations:
    keeper.security/inject: "true"
    keeper.security/ksm-config: "keeper-credentials"
    keeper.security/file-cert: "tls-cert:server.crt:/keeper/secrets/tls/tls.crt"
    keeper.security/file-key: "tls-cert:server.key:/keeper/secrets/tls/tls.key"
spec:
  containers:
    - name: nginx
      image: nginx:alpine
      volumeMounts:
        - name: keeper-secrets
          mountPath: /etc/nginx/tls
          subPath: tls
```

### Inject every secret in a folder

Fetch all records in a Keeper folder - one file per record under the output path.

```yaml
metadata:
  annotations:
    keeper.security/inject: "true"
    keeper.security/ksm-config: "keeper-credentials"
    keeper.security/folder: "Production/Databases"
    keeper.security/folder-path: "/keeper/secrets/db"
```

{% hint style="info" %}
You can also reference a folder by UID with `keeper.security/folder-uid`.
{% endhint %}

### Extract a single field with Keeper Notation

Write just one field to a precise path using Keeper Notation. Notation is parsed by the per-secret `keeper.security/secret-<name>` annotation (the plain `keeper.security/secret` annotation always treats its value as a record title).

```yaml
metadata:
  annotations:
    keeper.security/inject: "true"
    keeper.security/ksm-config: "keeper-credentials"
    keeper.security/secret-token: "keeper://API-Keys-UID/field/password:/keeper/secrets/token.txt"
```

### Automatic rotation

In sidecar mode the agent re-fetches on an interval and rewrites the files in place - no Pod restart. Apps that re-read the file pick up the new value automatically.

```yaml
metadata:
  annotations:
    keeper.security/inject: "true"
    keeper.security/ksm-config: "keeper-credentials"
    keeper.security/secret: "database-credentials"
    keeper.security/refresh-interval: "1m"
```

```bash
# rotate the value in Keeper, then watch it update in place:
kubectl exec deploy/web -c app -- sh -c 'while :; do cat /keeper/secrets/database-credentials.json; sleep 10; done'
```

### More examples and Github Source

The injector's GitHub repository has a full catalog of runnable examples (web demos, databases, rotation dashboards, resilience, cloud auth, and more).

* View the [Github Source](https://github.com/Keeper-Security/keeper-k8s-injector/tree/main/examples)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/secrets-manager/integrations/kubernetes-secrets-injector/examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
