. <(aescrypt -d -o - ~/.secrets.aes)
I have a handful of aliases/functions to make it more smooth, but that's the core.It's a shellscript that they encrypted. They decrypt it and feed the decrypted output immediately into the shell, to be sourced.
That encrypted secrets file could contain any shellscript, so the aliases are stored in there, together with the API-Keys and passwords.
source-secret()
{
if [ -z "$1" ]; then
echo "Need filename to source"
elif ! [ -f "$1" ]; then
echo "File '$1' does not exist"
elif ! which aescrypt >/dev/null 2>&1; then
echo "Could not find required dependency 'aescrypt'"
else
. <(aescrypt -d -o - "$1")
fi
}Project-specific secrets can be stored locally via something like SOPS or remotely with something like Hashicorp Vault or AWS SecretsManager.
Applications that have secrets to manage (e.g., Emacs) or are partly about secrets management (e.g., GnuPG, OpenSSH) all store their secrets somewhere else and have secure (not plaintext, sometimes not even on disk) storage options available.
There's no reason to store secrets in plain text in your shell configuration. Practically any choice you can think of is a better one. Even if you did, there's no reason you couldn't store them in a more specific file that ~/.zshrc sources, and let LLM agents read zshrc but block access to the file containing your secrets. (I wouldn't rely on permissions prompts for this, though, lol.)
A good thing to do is organize. You can actually load different files. Here's a pretty common pattern that you'll find and it'll illustrate how to do other things
if [[ $(uname) == "Darwin" ]]; then
source "${INSERT_SOME_DIR}/osx.zsh"
elif [[ $(uname) == "Linux" ]]; then
source "${INSERT_SOME_DIR}/linux.zsh"
fi
You do this for loading based on the operating system. You might want some aliases, commands, or other routines in one but not the other. For example, in my linux one I have stuff for cuda paths. You can do all sorts of things too, like make a (generically named) work file, which you don't publish to github but you load it if it exists. Then you can put all your work related aliases there and not contaminate anything else. Something like `[[ -a ${INSERT_SOME_DIR}/work.zsh ]] && source ${INSERT_SOME_DIR}/work.zsh`.You shouldn't really load secure keys this way, but others had good answers so I thought I'd at least share a more general pattern since it isn't as well known among the less terminally inclined.
On personal pc no need to define the $ECORP var in shell init. On work pc define that var.
based alone on that you can conditionally do almost anything.
- shell source files/aliases
- vim/editors enable disable plugins based on existence of env vars.
- define shortcuts in file manager.
- and i add the following to my main $DOTFILES .gitignore.
# Any file that contains the following will be ignored.
# Used to ignore files in corporate environment
*ECORP*
*ecorp*
Based on multiple years across different setups, using environment variables was the most reliable option since I have been in places where there are restrictions on where my init files can be placed and having to change a shit ton of paths in my dotfiles or just keeping a different branch for work and personal (and making sure they stay in sync) was too much of a hassle.Additionally, maintaining hygiene is essential, where I only use a Read Only PAT token on my personal dotfiles in workenv. That way, there is no accidental way I would be able to push from my workenv.
> You’re just splitting your dotfiles
Ummm... yes? That is what I said > the issue of storing secrets in plain text files remain.
Ummm... kinda? The problem was that reading an rc file was considered dangerous. Not putting keys in your rc files is an improvement. Encrypting them is even better than that. But I also said more words in the original post and you don't really even need to read between the lines to figure out I said "you can generalize this", especially when there's comments next to it saying "here's how you load an encrypted file"