When creating software, it’s common to deal with secrets like database passwords, API access tokens, etc. There are many ways to make secrets available to software. Below are notes on some of the ways. Threat Modeling might help you determine which way is best for what you are doing.

Environment variables

Putting secrets in environment variables (env vars) is very easy and might be fine if your setup is simple and otherwise very secure. It’s certainly better than putting secrets directly into source code. However, it’s important to know what the alternatives are and when to use them, which is covered by the other sections of this post.

If you’re using Docker and any .env files or other secrets files, you should probably have a .dockerignore that makes Docker ignore them. Definitely don’t define any secret env vars in Dockerfile because that would include them in the image (images should be safe to share). Linux users should probably restrict .env file permissions with chmod 600 .env to make the file only accessible to the file’s owner.

Encryption

.env files are usually plaintext, but there are many tools that can encrypt them for you. Encrypting .env files or other key-value files is mainly helpful for simple CI/CD pipelines that involve committing the encrypted files into Git to send them to a production server that automatically decrypts the files and redeploys. SOPS is probably the most widely used tool for this kind of pipeline, and it supports many more types of key-value files than just .env. Encrypting .env files that are just staying in your secure development environment is generally not worth the time and effort.

DevOps tools

Tools like Docker, Ansible, and Terraform each have multiple features for helping keep secrets safe. For example, Docker has Docker Secrets and Ansible has Ansible Vault.

Docker Secrets

Docker recommends using Docker Secrets because:

Environment variables are often available to all processes, and it can be difficult to track access. They can also be printed in logs when debugging errors without your knowledge. Using secrets mitigates these risks.

Secrets in Compose | Docker Docs

environment variables can unintentionally be leaked between containers (for instance, if you use --link).

Manage sensitive data with Docker secrets | Docker Docs

Docker Secrets is mainly designed for use with Docker Swarm. If you use Docker Secrets with Docker Compose, you will have to put each secret in a plaintext file outside the container. This is still more secure than putting secrets in unencrypted env vars.

Remember to add any secrets files that are in a project folder to .gitignore and .dockerignore. Linux users should probably chmod 600 secrets/* to restrict access to them.

Secrets managers

Secrets managers are services that protect secrets with many features including access control, versioning, auditing, and automatic rotation. Software usually gets secrets from a secrets manager by making web requests rather than by reading environment variables or files. Secrets managers are great for businesses with many employees, but are generally considered to be completely overkill and too expensive for use in secure development environments and locally hosted services.

Discussion on the purpose of secrets managers

There are many secrets managers. Many of the major cloud platforms have their own, such as:

There are also secrets managers that are not locked in to a specific cloud platform, including:

Secrets manager comparisons

Operating System (OS) keystores

Each major OS has a built-in way to securely store secrets. They have different interfaces, but there are libraries that abstract them into one interface.

Hardware

Further reading

This post focused on getting secrets into running software, but there’s so much more to the topic of secrets management. For example, another big part of it is scanning for leaked secrets.