DEV Community

Artem
Artem

Posted on AI-assisted

Managing External Secrets in Docker Swarm

I've been working with Docker Swarm secrets and kept running into the same limitation: secrets are immutable.

Once a secret is created, you can't update its value. When a password, API key, or another secret changes in an external secret store, you need a way to propagate that change to Docker Swarm.

A common approach is to create a new secret with a version or hash in its name:

database-password-v1
database-password-v2
Enter fullscreen mode Exit fullscreen mode

That works, but I wanted something simpler: keep the external secret store as the source of truth while keeping the YAML stack definition unchanged.

So I built cloud-secrets.

What I wanted

  1. Keep using ordinary Docker secrets from the application's point of view.
  2. Keep the application completely unaware of the external secret store.
  3. Keep the secret available at /run/secrets/database-password without changing the stack when its value is rotated.

How cloud-secrets works

The idea is pretty simple:

External Secret Store → cloud-secrets → Docker Swarm
Enter fullscreen mode Exit fullscreen mode

cloud-secrets runs on a Swarm manager and keeps external secrets in sync with Docker Swarm.

It periodically checks for changes and handles the Docker secret lifecycle when a value changes.

The stack continues to refer to the same logical secret:

secrets:
  database-password:
    external: true
Enter fullscreen mode Exit fullscreen mode

while cloud-secrets takes care of what's happening underneath.

Currently, HashiCorp Vault is supported as an external secret store.

Running it

Here's a shortened example using Vault with AppRole:

services:
  cloud-secrets:
    image: swarmdeployorg/cloud-secrets:v0.4.0
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - CS_PROVIDER=vault
      - CS_REFRESH_INTERVAL=1m
      - VAULT_ADDR=http://vault:8200
      - VAULT_AUTH_APPROLE_ROLE_ID=/run/secrets/cloud-secrets-vault-approle-role-id
      - VAULT_AUTH_APPROLE_SECRET_ID=/run/secrets/cloud-secrets-vault-approle-secret-id
      - VAULT_MOUNT_PATH=prod
    secrets:
      - cloud-secrets-vault-approle-role-id
      - cloud-secrets-vault-approle-secret-id
    deploy:
      placement:
        constraints:
          - node.role == manager

secrets:
  cloud-secrets-vault-approle-role-id:
    external: true
  cloud-secrets-vault-approle-secret-id:
    external: true
Enter fullscreen mode Exit fullscreen mode

The RoleID and SecretID can themselves be provided as Docker secrets.

I'm intentionally leaving the complete Vault and AppRole setup out of this post. It's all covered in the project documentation.

That's it

The goal of cloud-secrets is deliberately narrow:

Your external secret store manages the values. Docker Swarm delivers them to applications. cloud-secrets keeps the two in sync.

The project is open source:

https://github.com/swarm-deploy/cloud-secrets

Guide to setting up Vault and Cloud Secrets:

https://github.com/swarm-deploy/cloud-secrets/blob/master/docs/usage_vault.md

If you're using external secrets with Docker Swarm, I'd be interested to hear how you're handling secret rotation today.

Top comments (0)