Password recycling is dangerous. All it takes is one slip-up and hackers have stolen the password. From there, every account that uses the stolen password is compromised. I learned this the hard way. But password managers can be frustrating. A solid one is KeePassX, though I was unsatisfied with the workflow of its GUI application.

The solution that I’ve landed on is password_store, a command line password manager for Linux. It organizes passwords in a directory structure, encrypts using GPG, and provides version control through git.

  1. Install the pass utility.
    $ sudo apt install pass
    
  2. Generate a GPG key and follow the prompts. The passphrase set up in this step unlocks the key when you later use it to retrieve encrypted passwords.
    $ gpg --generate-key
    
  3. Initialize the password store; substitute “name” for the name used when generating the gpg key.
    $ pass init "name"
    
  4. Initialize password_store’s git repository for version control.
    $ pass git init
    
  5. Create a git repo elsewhere and push to it.
    $ ssh user@elsewhere
    user@elsewhere:~$ mkdir pass.git && cd pass.git
    user@elsewhere:~/pass.git$ git init --bare
    user@elsewhere:~/pass.git$ exit
    $ pass git add origin user@elsewhere:pass.git
    $ pass git push --set-upstream origin master
    
  6. When adding passwords, the convention is to use a directory structure of service/username so that you can keep track of such organizational data easily. Be aware that these metadata are stored in the clear, so you may not want to push everything to a public server for privacy reasons. Use pass git push and pass git pull to maintain the repos across all of the devices which share this password store.
    $ pass generate myuniversity/myid
    mkdir: created directory '/home/user/.password-store/myuniversity'
    [master ca64eb2] Add generated password for myuniversity/myid.
     1 file changed, 1 insertion(+)
     create mode 100644 myuniversity/myid.gpg
    The generated password for myuniversity/myid is:
    Y9Gjc$Ny>Li7[\90?w&vYMW"b
    $ pass git push
    
  7. Export your GPG key so that it can be installed on other devices.
    $ gpg --export-secret-keys -a "name" > key.gpg
    

    The key is still secured under your passphrase.

  8. On another device, import the key and clone the pass.git repo.
    user@anotherdevice:~$ gpg --import key.gpg
    user@anotherdevice:~$ gpg --edit-key "name"
    gpg> trust
    Your decision? 5
    Do you really want to set this key to ultimate trust? (y/N) y
    gpg> quit
    user@anotherdevice:~$ git clone user@elsewhere:pass.git
    user@anotherdevice:~$ mv pass .password-store
    user@anotherdevice:~$ pass myuniversity/myid
    Y9Gjc$Ny>Li7[\90?w&vYMW"b
    

One benefit of using password_store is that the passwords are accessible even without the password_store utility installed:

$ gpg -d .password-store/myuniversity/myid.gpg
Y9Gjc$Ny>Li7[\90?w&vYMW"b

Other fancy features include:

  • Tab completion.
  • Edit keys:
    $ pass edit myuniversity/myid
    > Y9Gjc$Ny>Li7[\90?w&vYMW"b
    > What is your mother's maiden name? 5iAlGJM!Z'AbEhqL>wdqeYgm,
    
  • Copy keys to clipboard with pass -c myuniversity/myid. This copies only the first line, so in the above example my mother’s maiden name would not be copied.
  • Set passwords (useful when importing from another system):
    $ pass insert foo/bar
    Enter password for foo/bar: 
    
  • Generate passwords with constrained length/characters:
    pass generate --no-symbols mybanks/securitysucks 8
    mkdir: created directory '/home/nathan/.password-store/mybanks'
    [master 456aec9] Add generated password for mybanks/securitysucks.
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 mybanks/securitysucks.gpg
    The generated password for mybanks/securitysucks is:
    XCkwQ4uj
    

Additional help and information is available in pass help.