Doppler Encrypted Secrets Snapshots for High Availability
Tags: secretops, kubernetes, devops, security
Published: 2022-11-23 05:36:42

Ideally, fetching secrets at runtime by your application is avoided altogether using [Doppler integrations](https://docs.doppler.com/docs/integrations) (e.g. Doppler Kubernetes Secrets Operator), which continuously sync secrets to your hosting environment ahead of time, but this won't always be possible.

For legacy applications, on-prem, and virtualized environments where secrets must be fetched at runtime, bundling [Doppler CLI](https://docs.doppler.com/docs/install-cli) secrets snapshots into your application provides a robust failsafe in the event Doppler's API is unreachable.

The result is similar to a GitOps secrets approach, but without the messy business of committing encrypted secrets to Git repositories can be avoided.

## Build. Encrypt. Deploy. Fallback.

Doppler secrets snapshots are bundled into the application build during CI/CD with a single command:

```sh
doppler secrets download secrets.json.enc
```

Then to fallback to a secrets snapshot when running your application:

```sh
doppler run --fallback secrets.json.enc -- ./app-start.sh
```

Secrets snapshots aren't just for high availability. They're perfect for network-restricted environments and offer protection if Doppler's API rate limit is exceeded.

The addition of the `--fallback-only` instructs the CLI only to use the snapshot:

```sh
doppler run \
 --fallback secrets.json.enc \
 --fallback-only -- ./app-start.sh
```

Now let's look into passphrase usage for encrypting and decrypting secrets snapshots.

## Passphrase

By default, the CLI configuration is used to construct the passphrase, which is typically the Service Token value exposed via the DOPPLER_TOKEN environment variable. While this is the simplest solution, setting the passphrase explicitly has the benefits of:

* Only using the `DOPPLER_TOKEN` for authentication
* Allowing the passphrase and DOPPLER_TOKEN values to be rotated independently

Most importantly, your implementation must guarantee the passphrase remains constant from build to deployment during a release. As these are infrastructure secrets, we recommend a dedicated infra project for each application containing only the `DOPPLER_TOKEN` and (should you use a passphrase) a `DOPPLER_PASSPHRASE`.


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/znck0v4xl1q4dqhkqzl2.jpeg)

‎[Doppler integrations](https://docs.doppler.com/docs/integrations) then keep infrastructure secrets in sync between your build and deployment environments, eliminating the risks associated with manual copying and pasting.

The following video demonstrates how to set up an infra project in three simple steps:

%[https://vimeo.com/769739281]

With the required pieces in place, let's move on to creating and using secrets snapshots.

## Build

With the `DOPPLER_TOKEN` and `DOPPLER_PASSPHRASE` injected into your build environment (e.g. GitHub Action Secrets), we can now create the secrets snapshot file:

```sh
doppler secrets download \
  --passphrase "$DOPPLER_PASSPHRASE" \
  secrets.json.enc
```

Secrets snapshots also support name transformers and download formats:

```sh
# ASP.NET Core secrets snapshot
doppler secrets download \
 --passphrase "$DOPPLER_PASSPHRASE" \
 --format dotnet-json \
 appsettings.json.enc
```

Ensure the secrets snapshot file is included in your build, then you're done!

## Deploy

With the `DOPPLER_TOKEN` and `DOPPLER_PASSPHRASE` injected into the deployment environment via automation (e.g Ansible), the Doppler CLI will attempt to fetch the latest version of secrets using the secrets snapshot as a fallback:

```sh
doppler run \
  --passphrase "$DOPPLER_PASSPHRASE" \
  --fallback secrets.json.enc -- ./start-app.sh
```

## Summary

Doppler secret snapshots are your high-availability solution to ensure applications can always access their secrets.

Using Docker? Check out our dedicated [Docker High Availability documentation](https://docs.doppler.com/docs/docker-high-availability) to learn more.