Skip to main content

Managing Passwords with Pass

Pass is the standard Unix password manager that follows the Unix philosophy: do one thing and do it well. It stores passwords as GPG-encrypted files in a simple directory structure and integrates seamlessly with Git for synchronization across machines.

Why Pass?

  • Simple and transparent: Passwords are just encrypted files in a directory
  • Git integration: Built-in version control and sync across devices
  • GPG encryption: Industry-standard encryption you can trust
  • Cross-platform: Works on macOS, Linux, BSD, and Windows (via WSL)
  • CLI-first: Perfect for terminal users and automation
  • Extensible: Large ecosystem of extensions and integrations

Installation

macOS

brew install pass gnupg

Linux (Ubuntu/Debian)

sudo apt install pass gnupg

Linux (Fedora/RHEL)

sudo dnf install pass gnupg

Initial Setup

Step 1: Create a GPG Key

If you don't already have a GPG key, create one:

gpg --full-generate-key

Follow the prompts:

  • Choose RSA and RSA (default)
  • Key size: 4096 bits
  • Expiration: 0 (doesn't expire) or your preference
  • Enter your name and email
  • Create a strong passphrase (this is your master password!)

Verify your key was created:

gpg --list-keys

Note the email address associated with your key.

Step 2: Initialize Pass

pass init "your-email@example.com"

This creates ~/.password-store/ and initializes it with your GPG key.

# Initialize git in the password store
pass git init

# Add your remote repository
pass git remote add origin git@github.com:yourusername/password-store.git

# Push to remote
pass git push -u origin main
tip

Create a private repository on GitHub, GitLab, or your preferred Git hosting service before adding the remote.

Basic Usage

Storing Passwords

# Add a password (you'll be prompted to enter it)
pass insert personal/github

# Add a password with multiple lines (for notes, security questions, etc.)
pass insert -m work/aws-console

# Generate a random password
pass generate personal/netflix 24

Retrieving Passwords

# Display a password in the terminal
pass personal/github

# Copy password to clipboard (clears after 45 seconds)
pass -c personal/github

# List all passwords
pass

# Search for passwords
pass find github

Organizing Passwords

Pass uses a hierarchical directory structure:

~/.password-store/
├── personal/
│ ├── github.gpg
│ ├── netflix.gpg
│ └── email/
│ └── gmail.gpg
├── work/
│ ├── aws-console.gpg
│ └── slack.gpg
└── banking/
└── chase.gpg

You can organize however makes sense to you!

Editing and Managing

# Edit an existing password
pass edit personal/github

# Remove a password
pass rm old/unused-service

# Move/rename a password
pass mv old-name new-name

# Copy a password entry
pass cp personal/github work/github-work

Syncing Across Machines

On Your First Machine

# After making changes, push to remote
pass git push

Every time you insert, edit, or remove a password, Pass automatically commits the change. You just need to push.

Setting Up on Additional Machines

  1. Install Pass and GPG (as shown in Installation section)

  2. Import your GPG key from your first machine:

    On the first machine, export your key:

    gpg --export-secret-keys your-email@example.com > gpg-private-key.asc
    gpg --export-ownertrust > gpg-ownertrust.asc

    Transfer these files securely to the new machine, then import:

    gpg --import gpg-private-key.asc
    gpg --import-ownertrust gpg-ownertrust.asc

    # Clean up the key files
    rm gpg-private-key.asc gpg-ownertrust.asc
  3. Clone your password store:

    git clone git@github.com:yourusername/password-store.git ~/.password-store
  4. Test it works:

    pass
    pass -c personal/github

Daily Sync Workflow

# Pull latest changes before working
pass git pull

# After making changes
pass git push

Advanced Features

Generating Strong Passwords

# Generate 32-character password with symbols
pass generate service/account 32

# Generate without symbols (alphanumeric only)
pass generate -n service/account 20

# Generate and don't show on screen
pass generate -c service/account 24

Multi-line Entries

Pass supports storing more than just passwords:

pass insert -m banking/account

Then enter:

MySecurePassword123
Username: john.doe
Account Number: 1234-5678-9012
Security Question: What is your pet's name?
Answer: Fluffy

The first line is always treated as the password, and pass -c will only copy that line.

Using Pass with Multiple GPG Keys

If you want to encrypt for multiple GPG keys (e.g., team password sharing):

pass init key-id-1 key-id-2 key-id-3

Temporary Password Display

# Show password for 45 seconds, then clear terminal
pass show -c 45 service/account

Shell Integration

Bash Completion

Add to ~/.bashrc:

source /usr/share/bash-completion/completions/pass

Zsh Completion

Add to ~/.zshrc:

autoload -U compinit && compinit
source /usr/share/zsh/site-functions/_pass

Fish Completion

Usually works out of the box. If not:

cp /usr/share/fish/vendor_completions.d/pass.fish ~/.config/fish/completions/

Security Best Practices

1. Strong GPG Passphrase

Your GPG passphrase is your master password. Make it:

  • At least 20 characters
  • A mix of words, numbers, and symbols
  • Something memorable but not guessable

2. Backup Your GPG Key

# Export your private key
gpg --export-secret-keys your-email@example.com > gpg-backup.asc

# Export trust settings
gpg --export-ownertrust > gpg-trust-backup.asc

Store these files:

  • On an encrypted USB drive
  • In a secure cloud storage (encrypted)
  • In a physical safe

Then delete them from your computer:

rm gpg-backup.asc gpg-trust-backup.asc

3. Use a Private Git Repository

Always use a private repository for your password store, even though passwords are encrypted.

4. Regular Git Pushes

Push changes regularly to avoid losing passwords:

# Add an alias for convenience
echo 'alias psync="pass git pull && pass git push"' >> ~/.bashrc

5. Never Store GPG Keys in Git

Do not commit your GPG private key to your password store repository. Export and store it separately.

Troubleshooting

"gpg: decryption failed: No secret key"

Your password was encrypted with a different GPG key. Either:

  • Import the correct GPG key
  • Re-encrypt with your current key: pass init your-email@example.com

"fatal: not a git repository"

Initialize git in your password store:

pass git init

GPG Agent Timeout

If GPG keeps asking for your passphrase, configure the timeout:

Edit ~/.gnupg/gpg-agent.conf:

default-cache-ttl 34560000
max-cache-ttl 34560000

Reload the agent:

gpg-connect-agent reloadagent /bye

Merge Conflicts

If you edit passwords on multiple machines without syncing:

pass git pull
# If conflicts occur
cd ~/.password-store
git status
# Manually resolve conflicts, then:
git add .
git commit -m "Resolve merge conflicts"
pass git push

Browser Integration

PassFF (Firefox)

Install the PassFF extension and the native host:

# Install the host application
curl -sSL https://github.com/passff/passff-host/releases/latest/download/install_host_app.sh | bash -s -- firefox

browserpass (Chrome/Firefox)

Install browserpass for auto-fill support.

Mobile Apps

Android: Password Store

Password Store is the official Android app with Git sync support.

iOS: Pass for iOS

Pass for iOS provides pass functionality on iPhone and iPad.

Tips and Tricks

Quick Clipboard Copy

Create an alias for frequently used passwords:

alias github-pass='pass -c personal/github'

OTP Support

Install the pass-otp extension for 2FA codes:

# Add a TOTP secret
pass otp add service/account

# Generate OTP code
pass otp service/account

Team Password Sharing

Initialize with multiple GPG keys:

pass init alice@example.com bob@example.com charlie@example.com

Everyone with their private key can decrypt the passwords.

Password History

Since Pass uses Git, you can view password history:

pass git log personal/github
pass git show <commit-hash>:personal/github.gpg | gpg -d

Import from Other Password Managers

Many import scripts exist in the pass contrib repository.

Example for LastPass:

./lastpass2pass.rb export.csv

Further Reading


Pass follows the Unix philosophy perfectly: simple, composable, and transparent. Once you get used to the workflow, it becomes second nature and integrates beautifully into a terminal-based workflow.