---
title: "Examples"
description: "A Postgres in the cluster, backed up from the manifest that deploys it."
url: "https://saved.sh/docs/kubernetes/examples"
---

Everything here uses the [Deployment](/docs/kubernetes/install) that works today. When the
operator ships, the `config.yaml` in these examples is unchanged; only what owns the pod
changes.

## A Postgres in the cluster [#a-postgres-in-the-cluster]

The worker reaches an in-cluster database the way any other pod does, by service DNS. The
backup ID is the one from the dashboard or `sctl backup list`.

```yaml title="config.yaml"
api_url: https://api.saved.sh
token: "<shown once when the worker was provisioned>"
local_temp_path: /var/lib/saved

backups:
  "018f3c2a-9d41-7c33-b2e1-5a0c7f9e1b44":
    source_type: postgres
    compression: true
    encryption:
      public_key: ./prod.asc
    source:
      host: postgres.default.svc.cluster.local
      port: 5432
      database: app
      user: backup
      password: "<password>"
      ssl_mode: require
      exclude_tables: [audit_log, sessions]
```

## The encryption key in the same Secret [#the-encryption-key-in-the-same-secret]

`public_key` takes a **path relative to the config file's own directory**, and the config file
lives in the Secret mount. Put the armoured key in the same Secret and it resolves without
any extra volume.

```bash
gpg --armor --export backups@example.com > prod.asc

kubectl -n saved create secret generic saved-worker-config \
  --from-file=config.yaml=./config.yaml \
  --from-file=prod.asc=./prod.asc
```

With the Secret mounted at `/etc/saved` and `workingDir: /etc/saved`, `./prod.asc` is
`/etc/saved/prod.asc`. We hold only the public half, and we cannot recover a backup if you
lose the private one. See [Encryption](/docs/workers/configuration#encryption).

## A script source against an in-cluster service [#a-script-source-against-an-in-cluster-service]

A `script` source runs a command inside the worker container, so it can only use what that
image has: `curl`, `pg_dump` and `mysqldump`. Ship the script itself in a
ConfigMap and mount it executable.

```yaml title="config.yaml"
backups:
  "018f8c5f-3e46-7da8-a071-5f1c6d4e8a35":
    source_type: script
    source:
      path: /opt/saved/export.sh
      interpreter: /bin/sh
```

```yaml
          volumeMounts:
            - name: scripts
              mountPath: /opt/saved
              readOnly: true
      volumes:
        - name: scripts
          configMap:
            name: saved-scripts
            defaultMode: 0555
```

```sh title="export.sh"
#!/bin/sh
set -eu

curl -fsS http://reports.default.svc.cluster.local/export > "$SAVED_OUTPUT"
```

Setting `interpreter` means the file does not have to be executable, which saves an argument
about ConfigMap file modes. &#x2A;*Write to `$SAVED_OUTPUT`**: anything on stdout is treated as a
log, not as backup data.

## Backing up a PersistentVolumeClaim [#backing-up-a-persistentvolumeclaim]

Use a `folder` source and mount the claim into the worker.

```yaml
          volumeMounts:
            - name: uploads
              mountPath: /data/uploads
              readOnly: true
      volumes:
        - name: uploads
          persistentVolumeClaim:
            claimName: app-uploads
            readOnly: true
```

```yaml title="config.yaml"
backups:
  "018f7b4e-2d35-7c97-9f60-4e0b5c3d7f24":
    source_type: folder
    compression: true
    source:
      path: /data/uploads
      exclude: ["*.tmp", "cache"]
```

<Callout type="warn">
  A `ReadWriteOnce` claim can only be mounted by pods on one node. If the application already
  holds it, the worker pod will not schedule until it is on that node too, or the claim
  supports `ReadWriteMany`. This is a property of the volume, not of the worker.
</Callout>

The result is one zip of the tree, encrypted before it leaves the cluster. Entries are stored
without zip compression, because the encrypt step compresses anyway.

## Next [#next]

<Cards>
  <Card href="/docs/kubernetes/install" title="Install" description="The Deployment these configs go into." />

  <Card href="/docs/workers/configuration" title="Configuration" description="Every source type and every key." />
</Cards>
