pass
is a command line password manager for Linux that embodies the UNIX philosophy. It's like 1Password, but it lives in your terminal. This comes with some drawbacks, certainly, but is also very powerful.
Here we'll get pass
installed and then explore a couple reasons why you might like a Command Line Interface (CLI) to your password manager.
Installation
I'm using Ubuntu 18.04 (I know), but these instructions should work for any apt
based distribution, and should be easily adaptable to your *nix of choice.
First, we'll make sure we have pass
itself, gpg
which comes with Ubuntu by default and will be used to encrypt our passwords, and also xclip, which we'll use to copy passwords to the system clipboard.
$ sudo apt install pass gpg xclip
Getting started
Before we can use pass
, we'll need a generate a GPG keypair. To do that, we'll kick off the keypair generation wizard like so:
$ gpg --full-generate-key
Choose the default kind of key (RSA), and default keysize (3072). Set the expiry to 0
(doesn't expire). Confirm these options with y
.
Next, it will ask you to create a user ID to associate with this key. First you'll be asked your name - I can't help you answer that. Next, you'll be asked for your email address - this is kinda like the "username" for your GPG key. Finally you'll be asked if you'd like to supply a comment - you can skip this by just hitting enter
or give your job title if you're very important. Choose O
to confirm your information.
Next, you'll be asked to enter a passphrase. This should be 8+ characters long. You'll need to remember it, but it should be secure. Think of something appropriate, enter it, then enter it again to confirm.
GPG will now generate a random key. Wiggle your mouse around and mash the keyboard to generate entropy while it does this. I have no idea how it does this or if this is a joke, but this is security we're talking about here, so get mashing.
Initialize pass
:
Now we get to start using pass
. First we create the initial password store, passing it our GPG key ID (which is the email address we used above).
$ pass init the-email-address-you-used-for@your-gpg.key
Using pass
pass
stores passwords in a hierarchical directory structure. This structure is somewhat arbitrary, but basically follows the structure service-name/username
. If you have multiple accounts on the same service, you might nest those accounts under a parent folder, e.g. aws/development/adam@example.com
and aws/production/adam@example.com
- each of these paths will lead to a different password.
Adding passwords
Add a new service and set the password (you'll be asked to type the password and then type again to confirm):
$ pass insert test-service/adam@example.com
If you don't know the password already (i.e. you're signing up for a new service), you can generate a random password instead of making one up yourself (where 16
is the length you want the password to be):
$ pass generate test-service/adam@example.com 16
Viewing passwords
To view the password you just generated, or indeed any password in the vault, simply pass pass
the path to the value you'd like to retrieve (you'll be asked to enter your GPG password from earlier):
pass test-service/adam@example.com
To view that generated password and copy it to the system clipboard):
pass -c test-service/adam@example.com
To list all available accounts (but not their passwords):
$ pass ls
Removing passwords
To remove a password (you'll be asked to confirm deletion):
$ pass rm test-service/adam@example.com
Remove all passwords in a given directory (you'll be asked to confirm deletion):
$ pass rm -r test-service
...and because pass
follows the UNIX philosophy, you can find instructions for loads more knobs and whistles with man pass
.
Really using pass
So far, so good. You're a l33t hacker and now use a CLI password manager. Your passwords are stored locally and you can only get to them from your terminal. Congratulations, you just made your life just a little more difficult.
Or did you?
Here's the thing. pass
doesn't have to store passwords. It can store any string at the end of those paths. And those paths don't have to map one-to-one with a username and password combination.
Use pass
to store secure API keys
One of the most interesting uses of a CLI password manager is that it can integrate with your shell. That means if we can use pass
in our bash
scripts. This gets really useful when we combine that with e.g. loading ENV VARs for our projects.
Say we had the following passwords set:
$ pass ls
Password Store
└── aws
├── secret_key
└── access_key
We could then set these in a .env
file, and use dotenv
to read those values when booting our application (as described elsewhere):
AWS_SECRET_KEY: $(pass aws/secret_key)
AWS_ACCESS_KEY: $(pass aws/access_key)
When we boot our app, the $()
syntax will get expanded out, pass will be called, and our secret_key
and access_key
will be interpolated in place. Very cool. We can check this file into source control and no one will know what our AWS credentials actually are.
If we have multiple credentials for the same service, we could separate them out however we like - pass
doesn't care. We could have aws/staging/access_key
and aws/production/access_key
(maybe don't store prod access keys locally though), or aws/staging/client_a/access_key
and aws/staging/client_b/access_key
. Whatever works for you.
Conclusion
We've only just scratched the surface of what one can do when your credentials are managed on the command line. Next up I'd like to figure out how to get credentials shared between machines / teams through git
, ensuring only those with approved GPG keys can access the secrets held within. And you'll be surprised at how flexible having your passwords can be in practice, once you get your head around it.
I still use a regular password manager for regular passwords, but for credentials like API keys and tokens, pass
is quickly becoming a handy tool.
Top comments (2)
If you use 1Password as your general password manager have you tried their "op" command-line tool? Interested to know if it offers enough to be an alternative to pass.
Hey, Richard, judging from your bio I’d say you probably know the answer to this better than I would!
I’ve not tried
op
as I’m not a 1Password user myself, but I’m sure you’d be able to achieve the same result?One thing I did like about
pass
was that keys can be arbitrarily nested in a directory-like structure, which means you can have several keys/tokens/passwords under a given path, which can allow for storing more complex credentials than just a username and password, e.g. a database connection string made up of username, password, host, port, database and schema, all stored under e.g. aws/rds/production/ - not sure why or of that’d ever be handy, but thought it was an interesting facet of the model.