Organizing your dotfiles — managing secrets

In the previous post — Organizing your dotfiles, we talked about how to manage our configurations in a centralized and organized way. In this post, we’ll learn how to manage our secrets such as secret variables and API tokens that we usually need for our environments.
Problem
As we’ve made our dotfiles managed in a git repository that can be shared, it’s important NOT to include the secret keys and tokens that we use. Otherwise, this can be catastrophic as malicious activities can be made by someone else using our keys.
For example, there might be an NODE_AUTH_TOKEN
or GITHUB_API_TOKEN
that you use to access the private packages or repositories that only you or your organization should have access to. They are used by certain commands such as when installing packages through pnpm install
or git
. These kinds of tokens are usually exposed as the environment variables through your shell configuration files such as .zshrc
or .bashrc
.
// example in .zshrc
export NODE_AUTH_TOKEN=ghp_abC12345dEfGhIjKL6789mNopQrSTUvWxYZ
since we made our .zshrc
managed in a git repo, we should not put these secret keys and tokens in it anymore. So, we need to find another way that can securely do so.
Using Password Manager
If you are like me, who uses a password manager to handle all of your passwords to be stored and used securely across all platforms, we can adopt the same strategy for our secret keys and tokens as well.
I, personally, use 1Password as my main storage for all my secrets in one place, so, I’ll be using this one for my dotfiles as well. (You may replace it with the password manager of your own choice). As for 1Password, there is a package that we can use to manage our secrets from the command line. We will use this to inject the secret keys and tokens stored in 1Password to our .zshrc
during runtime.
Firstly, let’s put our secrets to 1Password — create a new API credential

and store the key

Now that our secrets are safe in the password manager, we’ll need a way to use them in our shell environment. To do so, first, let’s create a separate file named ~/.dotfiles/zsh/secrets.zsh
and then, export the environment variables using the values from 1Password.

Lastly, we’ll inject these environment variables into our .zshrc
file.

What this does is that it reads from a file .dotfiles/zsh/secrets.zsh
where the secrets are retrieved from 1Password, and then, it exposes these secret variables onto .zshrc
file using the 1Password CLI command op inject
.
Ok, that’s it, it’s done. Let’s relaunch the terminal and you will now see the following:

This means that when starting the shell, it will try to access the secrets from 1Password and the 1Password will ask for your permission to do so. If approved, you will now be able to use your repos or packages normally as before.
Finally, we can now, commit these files to our .dotfiles
git repository without having to worry about exposing the secret keys and tokens. It works seamlessly and the secrets are safe and secure as they should be.