I have been managing passwords with pass, the standard UNIX
password manager, for a while now, and I cannot recommend it enough. This particular password
manager excels in its simplicity: one password is stored in one file, encrypted by GnuPG, inside of
a Git repository. Categories of passwords are elegantly represented by the directory structure of
the password store. pass
has a simple command line interface, which allows for easy
interfacing with other software, such as dmenu or
rofi, through shell scripting.
Synchronization across different devices can be be achieved by a simple git push
or a git pull
.
This way you will not have to trust a company like LastPass to synchronize your passwords for you -
especially if you host your own Git server! You will be able to access and manage your passwords on
any device, as there are great clients available for many different platforms.
Let’s get started.
Installation
pass
is available in the standard repositories of most Linux distributions. Installing should be
as simple as:
- Debian/Ubuntu:
apt install pass
- Fedora:
yum install pass
- OpenSUSE:
zypper in password-store
- Gentoo:
emerge -av pass
- Arch:
pacman -S pass
Setup
GnuPG
To encrypt and decrypt your passwords, pass
uses GnuPG (GPG for short).
You will need a GPG keypair before creating your password store. If you do not have one yet, run:
gpg --full-generate-key
This will create a new GPG keypair in ~/.gnupg
, by default. Make sure to enter a strong password
when prompted; this is the master password that will be needed to decrypt the passwords in your
password store. To view your new public GPG key, run:
gpg --list-keys
The output will look something like this:
/home/test/.gnupg/pubring.kbx
-----------------------------
pub rsa4096 2022-11-05 [SC]
BC7F6D5FD6DD8DEC1F108221D8C7A6C84D1E6029
uid [ultimate] Test User <test@testuser.com>
sub rsa4096 2022-11-05 [E]
Creating the password store
We are now ready to create a new password store! Run the command below. Substitute <your-gpg-id>
with your GPG ID; this is the long alphanumeric string in the output of gpg --list-keys
(in my
case, it is: BC7F6D5FD6DD8DEC1F108221D8C7A6C84D1E6029
).
pass init <your-gpg-id>
That’s it! You have now set up your password store. A directory has been created in your home
directory: ~/.password-store
. This is where all your encrypted passwords will be stored.
Managing passwords
Let’s add some existing passwords to the password store. pass
supports directories, which lets you
organize passwords into (nested) categories. Below, we add a password for our Google account in the
root of our password store, and one for GitLab in the ‘work’ folder.
pass insert google
pass insert work/gitlab
You will be prompted to enter and confirm the passwords. You can then list the passwords in your password store by running:
pass
The output will look like this:
Password Store
├── google
└── work
└── gitlab
To retrieve the password, use one of the following:
pass google # Output to terminal; or
pass -c google # Copy to your clipboard
This will decrypt the file ~/.password-store/google.gpg
, containing your password, and output it
to your terminal or copy it to your clipboard if you pass the -c
flag. Decrypting requires the
password to your GPG key, which you will be prompted for.
Instead of continuing to use your old passwords (which you might re-use in several places), it is
better to use randomly generated passwords for every account! To generate a new random password for
my-account
, use the pass generate
:
pass generate my-account # Generate password with 25 characters
pass generate -n my-account # Do not use symbols in the password
pass generate my-account 15 # Generate a password with 15 characters
You can also update existing passwords this way; if the password already exists, you will be asked
for confirmation to overwrite the existing password. Don’t worry, since pass
uses Git, and every
change to the password store is marked by a new commit, you can always revert back to previous versions
of your passwords.
Of course, you can also manually edit passwords:
pass edit my-account
… and rename passwords:
pass mv my-account my-renamed-account
… and much more! For a full list of commands and options, simply type:
pass help
or check the man
-page:
man pass
Pass and dmenu
pass
comes installed with a handy script, passmenu
, that allows you to query your passwords
through dmenu, a powerful menu application. To select a password
in dmenu
and copy it to your clipboard, run:
passmenu
passmenu
can also type the password out for you. Binding the command below to a key combination is
very powerful: simply click wherever you need to enter your password, hit the key combination,
select the password you need, and passmenu
will fill it in for you. This is much more powerful
than using, for example, a browser plugin, as this approach works in any application; not just the
browser!
passmenu --type
One-time passwords
One-time passwords (OTP) are commonly used for multi-factor authentication. They are mostly used through mobile apps, such as Google Authenticator or Microsoft Authenticator. A six-digit code is typically retrieved through such an app, which has to be entered as a second step during authentication.
You will be glad to learn that pass
also supports OTP through the
pass-otp extension. You will likely find it in the standard
repositories of your Linux distribution.
Most websites that support OTP will show you a QR code that would normally have to be scanned by a
smartphone app. Instead, download the image to your computer. I will assume you saved it to
qr.png
. You will need to install zbar, which
should also be available in the standard repositories of your Linux distro, to decode the QR code.
Use the following command to decode the QR code, which contains the OTP secret, and append it to the
password file of my-account
:
zbarimg -q --raw qr.png | pass otp append my-account
You can also scan the QR code using your webcam:
zbarcam -q --raw | pass otp append my-account
If you now run pass my-account
, you will see that an additional line has been added with the OTP
secret, starting with otpauth://totp/
.
Now, to retrieve an OTP token, simply run:
pass otp my-account
And you will see a six-digit OTP code being printed to your terminal. Pretty cool, right?
Unfortunately, no passmenu-otp
script is packaged with pass-otp
to use it in combination with
dmenu
, but it is very simple to create one yourself. Simply copy the passmenu
script to a
location in your $PATH
, for example:
cp "$(which passmenu)" ~/.local/bin/passmenu-otp
Edit the script such that pass otp
is called instead of just pass
. The bottom five lines
should now look like this:
if [[ $typeit -eq 0 ]]; then
pass otp show -c "$password" 2>/dev/null
else
pass otp show "$password" | { IFS= read -r pass; printf %s "$pass"; } | $xdotool
fi
Once that’s done, just bind passmenu-otp
to a key combination of your choice, and using one-time
passwords will have just become a whole lot easier!
Unlock your GPG keyring at login
Decrypting the passwords in your password store requires you to enter the password of your GPG
key every time, if you do not perform any further configuration. This can become annoying if you have
to enter many passwords per day. A solution is to use gpg-agent
(a key management daemon for
GPG) and set the cache timeout to a high value. This would, however, still require you to enter the
password at least once after logging in to your system. There is a useful project called
pam-gnupg that automatically starts gpg-agent
upon login
and passes on your login password to it, in order to unlock your GPG key automatically. This, of
course, does require you to have the same password for your GPG key and your Linux user.
If you run an Arch-based distro, you can install pam-gnupg
trough the
AUR. Otherwise, manual
installation is also quite painless:
git clone 'https://github.com/cruegge/pam-gnupg'
cd pam-gnupg
./autogen.sh
./configure
make
sudo make install
Once installed, you need to edit the PAM configuration of your display manager. PAM is a framework
for user authentication within Linux. I currently use lightdm
, so in my case, I had to edit
/etc/pam.d/lightdm
, and add the following lines at the end:
auth optional pam_gnupg.so store-only
session optional pam_gnupg.so
To let gpg-agent
accept the password passed on by pam-gnupg
, add the following line to
~/.gnupg/gpg-agent.conf
:
allow-preset-passphrase
You probably also want to set the cache timeout to a large value, so that you will not be bothered with password prompts anyway, after the initial cached password times out. Add the following line to the same file to set the timeout to 86400 seconds, i.e., 24 hours:
max-cache-ttl 86400
Finally, you need to let pam-gnupg
know which key to unlock. First, run:
gpg --list-secret-keys --with-keygrip
This will give you output similar to this:
/home/test/.gnupg/pubring.kbx
-----------------------------
sec rsa4096 2022-11-05 [SC]
BC7F6D5FD6DD8DEC1F108221D8C7A6C84D1E6029
Keygrip = CC63EC89672E3F8FDD0F2A24323BE34BA0D7317D
uid [ultimate] Test User <test@testuser.com>
ssb rsa4096 2022-11-05 [E]
Keygrip = 3A4D0CF6F136972948B8370956002C4EA7EBF9BF
Copy the keygrip marked with [E]
, in my case 3A4D0CF6F136972948B8370956002C4EA7EBF9BF
, and
write it to ~/.pam-gnupg
:
echo '3A4D0CF6F136972948B8370956002C4EA7EBF9BF' > ~/.pam-gnupg
Now log out and back into your system, and your GPG key should be automatically unlocked, freeing you from password prompts!
Clients on different platforms
There are several nice clients for pass
on different platforms. To start with, there is a Qt-based
cross-platform GUI front-end for called QtPass, which works on
Linux, BSD, macOS and Windows. It is a full-fledged client, and a great option for those who do not
care for the command line or dmenu
-style interface.
The client I have most experience with (apart from passmenu
) is the Android app called Password
Store. You can synchronize your
Git repository through HTTPS or SSH, and it supports Autofill and one-time passwords, among many
other features. And all of that is packaged in a clean-looking user interface. You can find it on
F-Droid. Highly recommended!
It looks like there is a similar open-source app for iPad and iPhone called Pass. I have no experience with this one, but it looks good and is well reviewed.
I occasionally use Windows for my day job, so I needed a client here as well. There is QtPass, but I was looking for a dmenu-like experience that I have gotten so used to on Linux. If you are like me, you will definitely like pass-winmenu. It offers a simple pop-up menu that reminds me of rofi, which can be brought up by pressing a configurable key combination.