At some point in time, we all have to set secrets in our terminal. If you want to keep your dotfiles in git this becomes a problem. There are plenty of creative ways around that issue but I’ve found sourcing passwords directly from a secret manager a great way to keep your secrets up to date, your dotfiles clean and no sensitive passwords lying around on disk. In this post I will show you how I source my passwords directly from 1password.
I’m assuming before diving in that you already have a 1password account.
Setting Up 1password CLI
First, let’s install the 1password CLI
brew install --cask 1password-cli
Once you have the CLI installed, you need to know your 1password signin address. This is the url you use to signin to reach your vaults. So maybe yours is something like doodoo.1password.com/signin
. Well your signin key for the op
CLI is then doodoo
and you would then login like this
op signin doodoo
Once you know that information you can place this in your ~/.zshrc
or ~/.bashrc
and load this on every new terminal session
eval "$(op signin doodoo)"
Every time you launch a terminal it will now ask for your 1password password and you will have access to your secrets
Enter the password for <your-email@email.com> at doodoo.1password.com:
Loading Secrets
So now that you are logged in, how do you source secrets into your shell? Here is an example from one of my secrets (the content has been changed). I’ve removed a lot of unnecessary data from this payload just to show the structure.
❯ op get item github-pat --vault Private | jq .
{
...
"details": {
"fields": [],
"notesPlain": "",
"password": "some-random-long-password-string",
"passwordHistory": [],
"sections": []
},
"overview": {
"title": "github-pat",
}
}
This is really useful, but even more useful is the op
CLI provides a --fields
flag to return just the data you need. So we can return a single piece of information using this flag like so.
❯ op get item github-pat --fields password --vault Private
some-random-long-password-string
Awesome, right? So now, retrieving and setting this in your environment becomes as simple as placing this in some of your dotfiles
export GITHUB_TOKEN=$(op get item github-pat --fields password --vault Work)
Automatically Logging In With iTerm (Optional)
Typing in your password to login is pretty annoying. There is a way to automate this in iTerm using Triggers. Whenever a certain phrase appears, iTerm will dropdown a select to use passwords from its Vault. If you navigate to iTerm -> Preferences -> Profiles -> Advanced
there will be a section that says Triggers
, click Edit
.
When you create a new trigger you want the regular expression to trigger on to be doodoo.1password.com
and the action you want is Open Password Manager
. For parameters I have 1password
set with instant and enabled checked.
Now that you have that setup you need place the password in your password manager. To do this, navigate to Windows -> Password Manager
and create an entry for 1password
. This is what the Trigger will look for when it finds a match for doodoo.1password.com
.
Now if you create a new iTerm session you should immediately see a dropdown whenever Enter the password for <your-email@email.com> at doodoo.1password.com:
appears!
Going Further With direnv
The icing on the cake for me is I use all of this in conjunction with direnv
. This little project loads environment variables by walking directories and looking for .envrc
files to load. In conjunction with 1password
this means you can load environment variables from your secret manager depending on your directly location. Here is an example of my directory structure for programming:
/Users/redman/code
├── work
+| ├── .envrc
│ └── twilio
├── github.com
+| ├── .envrc
│ ├── rossedman
│ │ └── rossedman.github.io
Each of these directories requires different github secrets. The way direnv
works is it will load the .envrc
for all directories under the .envrc
. Each of these directories now loads the appropriate access token when I’m working in them so I don’t have to switch or think about changing it. It loads it directly from 1password so its always up to date. If I need to rotate a PAT, I replace it in 1password and open a new terminal.
Here are what each .envrc
looks like. Notice that I name the secrets the same and place them in different Vaults as well. This gives me clean separation in 1password.
# work .envrc
export GITHUB_TOKEN=$(op get item github-pat --fields password --vault Work)
# personal .envrc
export GITHUB_TOKEN=$(op get item github-pat --fields password --vault Personal)
Now when you navigate to these directories it will load from 1password. Here is an example
❯ cd ~/code/work
direnv: loading ~/code/work/.envrc
direnv: export ~GITHUB_TOKEN ~GITHUB_URL
Conclusion
That’s it! I hope you learned something. I believe this is a very effective way to manage passwords especially for multipurpose computers where you need to switch contexts frequently and also need a secure solution to not store passwords on disk. Of note, that if you store your password in iTerm's
Password Manager you are removing some of the security benefits of this. If someone ever accessed your laptop they would also be able to just hit Return
and get passwords. Happy hacking!