Use pass — the UNIX Password Manager
Set up pass, the UNIX password manager: initialise a GPG-encrypted store, manage credentials, sync across machines with Git, and integrate with your browser.
Before you start
- ▸A terminal and sudo or root access
- ▸Git installed and a private remote repository (GitHub, Gitea, or self-hosted)
- ▸Basic familiarity with GPG concepts (public/private key pairs)
pass is a minimal password manager that follows the Unix philosophy: each password lives in a GPG-encrypted file, stored in a plain directory tree you control. There are no proprietary formats, no locked-in cloud accounts, and no black-box binaries — just GPG, Git, and a shell script you can read. This guide walks you through initialising a store, adding credentials, wiring up a browser extension, and syncing across machines with Git.
Install pass and Its Dependencies
You need gnupg and pass. Most distros package both.
Debian / Ubuntu
sudo apt update && sudo apt install -y pass gnupg
Fedora / RHEL / Rocky
sudo dnf install -y pass gnupg2
Arch
sudo pacman -S pass gnupg
Create or Choose a GPG Key
pass encrypts every entry with a GPG key. If you already have one you trust, skip ahead. Otherwise, generate a new key — use at least RSA 4096 or an ed25519 key.
gpg --full-generate-key
Choose ECC (sign and encrypt) with Curve 25519 on GnuPG 2.1+, or RSA 4096 on older installs. Set an expiry of 1–2 years and a strong passphrase.
After generation, note your key ID or fingerprint:
gpg --list-secret-keys --keyid-format LONG
Output will look similar to this (will vary):
# sec ed25519/A1B2C3D4E5F60001 2024-01-15 [SC] [expires: 2026-01-15]
# AABBCCDDEEFF00112233445566778899AABBCCDD
# uid [ultimate] Your Name <[email protected]>
Copy the long key ID (e.g., A1B2C3D4E5F60001) or the full fingerprint — you'll need it next.
Initialise the Password Store
pass init A1B2C3D4E5F60001
This creates ~/.password-store/ and writes a .gpg-id file containing your key ID. Every entry added from now on is encrypted to that key. You can pass multiple key IDs to encrypt to several recipients — useful for shared team stores.
Add and Retrieve Passwords
Add a new password interactively
pass insert email/personal
pass prompts you to type and confirm the password. The entry is saved as ~/.password-store/email/personal.gpg. The directory structure is yours to define — a common layout is category/sitename.
Generate a random password
pass generate web/github.com 32
This creates a 32-character random password and encrypts it immediately. Add --no-symbols if the site rejects special characters.
Retrieve a password
pass email/personal
Decrypts and prints the entry. To copy to clipboard instead (clears after 45 seconds):
pass -c email/personal
Store multi-line entries (username, TOTP seed, notes)
The first line is treated as the password by most tools. Additional lines are free-form.
pass insert --multiline web/github.com
Type the password on line 1, then any extra fields on subsequent lines, and press Ctrl-D when done. A common convention:
# line 1: s3cr3tP@ssword
# line 2: login: myusername
# line 3: url: https://github.com
List and edit the store
pass ls
pass edit web/github.com
Sync the Store with Git
Because the store is a plain directory of GPG files, it maps perfectly onto a Git repository. The pass git sub-command wraps git with the store as the working directory.
Option A — create a new Git repo inside the store
pass git init
pass git remote add origin [email protected]:youruser/password-store.git
pass git push -u origin main
Important: use a private repository. The files are encrypted, but metadata (entry names, directory structure) is not. A self-hosted Gitea instance or a private GitHub/GitLab repo are both fine.
Option B — clone an existing store on a new machine
# First import your GPG key on the new machine, then:
git clone [email protected]:youruser/password-store.git ~/.password-store
Pulling and pushing changes
Every pass insert, pass generate, and pass rm command automatically creates a Git commit when the store is a Git repo. Push and pull manually:
pass git pull
pass git push
Transferring your GPG key to another machine
# On the source machine:
gpg --export-secret-keys --armor A1B2C3D4E5F60001 > secret-key.asc
# Transfer secret-key.asc securely (e.g., via encrypted USB or scp)
# On the destination machine:
gpg --import secret-key.asc
gpg --edit-key A1B2C3D4E5F60001 trust quit # set trust to ultimate
Delete secret-key.asc after import.
Browser Integration with passff / browserpass
Two mature browser extensions expose the pass store in Firefox and Chromium-based browsers. Both require a small native host binary installed on your system.
browserpass (recommended)
Install the native host binary:
# Debian / Ubuntu
sudo apt install -y browserpass
# Fedora
sudo dnf install -y browserpass
# Arch
sudo pacman -S browserpass
Then register it for your browser. The package usually ships a Makefile for this:
# Firefox
sudo make hosts-firefox-user -C /usr/lib/browserpass
# or for Chromium
sudo make hosts-chromium-user -C /usr/lib/browserpass
On some distros the Makefile path is /usr/share/browserpass/ — check with dpkg -L browserpass or rpm -ql browserpass.
Finally, install the browser extension:
Once both the native host and extension are in place, navigate to a login page, press Ctrl+Shift+L, and browserpass will match entries by URL and auto-fill.
Note for Wayland users: clipboard operations require wl-clipboard (wl-copy/wl-paste) to be installed. Pass will use it automatically if it detects a Wayland session (WAYLAND_DISPLAY is set).
# Debian / Ubuntu
sudo apt install -y wl-clipboard
# Arch
sudo pacman -S wl-clipboard
Verify Everything Works
pass generate test/verify 20
pass test/verify
pass -c test/verify # should copy to clipboard
pass rm test/verify
Check the Git log to confirm auto-commits are working:
pass git log --oneline -5
Troubleshooting
GPG agent not running / passphrase not cached
Ensure the GPG agent is started. On most systemd desktops it starts automatically via socket activation. If it isn't:
gpg-agent --daemon --use-standard-socket
Also verify ~/.gnupg/gpg-agent.conf has a sensible default-cache-ttl (e.g., 3600) so you aren't prompted on every decrypt.
"decryption failed: No secret key"
The entry was encrypted to a key you don't have locally. This happens when cloning a store whose .gpg-id references a different key. Import the correct secret key, or re-encrypt the store after adding your own key ID: pass init NEW_KEY_ID re-encrypts all entries.
browserpass can't find entries
The extension matches on the domain part of the entry path. An entry named web/github.com or github.com will match github.com. Entries named web/github will not match automatically. Rename with pass mv web/github web/github.com.
Git merge conflicts
Because entries are binary GPG blobs, standard text merges fail. The safest workflow is to always pass git pull before editing. If a conflict occurs, manually keep the newer .gpg file and commit the resolution.
Frequently asked questions
- Is it safe to store the password store in a public Git repository?
- No. The password content is GPG-encrypted, but entry names and directory structure are plaintext metadata. Use a private repository — self-hosted Gitea, private GitHub, or a bare repo on your own server.
- Can I use pass on Android or iOS?
- Yes. Password Store (Android) and Pass for iOS are open-source apps that read the same ~/.password-store format and can sync via Git. You'll need to import your GPG key into each mobile app.
- How do I share a subset of passwords with a team member?
- Create a subdirectory, place a .gpg-id file in it listing multiple key IDs, then run pass init inside that directory. Entries in that subtree will be encrypted to all listed keys.
- What happens if I lose my GPG key?
- You lose access to all encrypted entries — there is no recovery mechanism by design. Back up your secret key (and its revocation certificate) to encrypted offline storage such as a USB drive in a safe place.
- Does pass work on Wayland without X11?
- Yes, but you need wl-clipboard installed so the pass -c clipboard command can use wl-copy instead of xclip. Pass detects the WAYLAND_DISPLAY environment variable and switches automatically.
Related guides
Manage Secrets with Ansible Vault
Encrypt Ansible secrets with AES-256 using ansible-vault: encrypt files and inline vars, automate with password files, and isolate group-level secrets with vault IDs.
AppArmor Explained
Learn how AppArmor profiles work, how to switch between enforce and complain mode, create new profiles, and diagnose access denials on Ubuntu, Debian, and Arch.
Apply CIS Benchmarks with OpenSCAP
Use OpenSCAP and scap-security-guide to evaluate, report on, and remediate Linux systems against CIS Benchmarks — covering install, eval, and automation.
How to Audit a Linux System with auditd
Set up auditd on Linux to track file access, syscalls, and privilege use. Covers persistent rules, file watches, ausearch, and aureport across major distros.