Read API token from file instead of environment variable
pettijohn opened this issue · 6 comments
I am trying to spin up Caddy in a Docker container, passing a secret in the docker-compose file. Ref: https://docs.docker.com/engine/swarm/secrets/
Docker intentionally requires the contents of the secret to be in a file and not an environment variable. In a compose file it looks like:
services:
reverseproxy:
container_name: caddy
build: .
ports:
- 443:443
- 80:80
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- /shares/caddy/data:/data
- /shares/caddy/config:/config
secrets:
- cloudflare-api-key
secrets:
cloudflare-api-key:
file: ./cloudflare-api-key.secret
At runtime, that copies the contents of the file ./cloudflare-api-key.secret into /run/secrets/cloudflare-api-key in a tmpfs in the container (ref docs linked above for explanation).
Is it possible to pass the API token as a path to a file rather than an environment variable?
tls {
dns cloudflare /run/secrets/cloudflare-api-key
}
Note I worked around this by putting the secret in a .env file instead, but as the Docker documentation argues, this is probably less secure than putting it in a secret file https://docs.docker.com/compose/environment-variables/
FWIW I tried to write this but since I've never worked with Go I have no idea what I'm doing and it didn't seem to work. I spent way too much time trying to understand how to replace a module to even attempt to run the code. Anyway - here's a link to a broken/partial implementation:
Can you use the --envfile
flag to give Caddy the environment file that way? https://caddyserver.com/docs/command-line#caddy-run
This does work with some compose file magic. Overriding the entrypoint of the image is clunky as you can see but functional.
services:
reverseproxy:
container_name: caddy
build: .
restart: always
ports:
- 443:443
- 80:80
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./site:/site
- /shares/caddy/data:/data
- /shares/caddy/config:/config
secrets:
- cloudflare-api-key
entrypoint: ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile", "--envfile", "/run/secrets/cloudflare-api-key"]
secrets:
cloudflare-api-key:
file: ./cloudflare-api-key.secret
Nice, thanks for posting your solution!
(Going to close if that's alright, since that works. Would prefer to not have to reinvent env files for each plugin...)
I think it's fine to close. https://docs.docker.com/engine/swarm/secrets/ says "Docker secrets do not set environment variables directly. This was a conscious decision, because environment variables can unintentionally be leaked between containers (for instance, if you use --link)." I think the caddy --envfile
approach does not violate this because caddy loading its own environment state, not modifying the container's state (I assume). Seems like a fine approach.