gopass Mounts
Managing multiple secret stores and team sharing.
Understanding Mounts
Mounts are local configuration - they tell gopass where stores are located on THIS machine. They are NOT synced with git. Each machine needs its own mount configuration.
# Conceptual model
root (default store: ~/.local/share/gopass/stores/root)
├── local/ # Entries in root store
├── personal/ # Entries in root store
└── v3/ [MOUNT] # Points to ~/.local/share/gopass/stores/v3
├── domains/ # Entries in v3 store
└── personal/ # Entries in v3 store
KEY INSIGHT: gopass ls shows a unified tree, but entries live in different stores.
Basic Mount Operations
# List all mounts
gopass mounts
# Show mount details
gopass mounts
# Output:
# root -> ~/.local/share/gopass/stores/root
# v3 -> ~/.local/share/gopass/stores/v3
# Add a mount (after store exists)
gopass mounts add v3 ~/.local/share/gopass/stores/v3
# Add mount with different path
gopass mounts add work ~/secrets/work-store
# Remove a mount
gopass mounts rm v3
# Remove mount (keeps the store, just unmounts)
gopass mounts rm work
# Store still exists at ~/secrets/work-store
GOTCHA: gopass mounts rm does NOT delete the store. It just removes the mount point.
New Machine Setup
When you set up gopass on a new machine, you must: 1. Clone the store repository 2. Mount it in gopass
# Step 1: Clone the store (if using git)
git clone git@github.com:username/gopass-v3.git ~/.local/share/gopass/stores/v3
# Step 2: Mount it
gopass mounts add v3 ~/.local/share/gopass/stores/v3
# Step 3: Verify
gopass ls v3/
gopass show v3/test/entry
# Alternative: Initialize new store (fresh)
gopass init --path ~/.local/share/gopass/stores/v3 GPGKEYID
gopass mounts add v3 ~/.local/share/gopass/stores/v3
TIP: Keep a setup script in your dotfiles that configures mounts.
Multi-Store Architecture
# Common setup: separate stores for different concerns
gopass mounts
# root -> ~/.local/share/gopass/stores/root # Default (legacy)
# v3 -> ~/.local/share/gopass/stores/v3 # Personal+infra
# work -> ~/.local/share/gopass/stores/work # Work secrets
# team -> ~/.local/share/gopass/stores/team # Shared team
# Why multiple stores?
# 1. Different recipients (who can decrypt)
# 2. Different sync locations (repos)
# 3. Different backup strategies
# 4. Different retention policies
# Create entries in specific store
gopass insert v3/domains/d000/server
gopass insert work/project/database
# Move between stores
gopass show work/old/entry | gopass insert -m v3/new/location
gopass rm work/old/entry
Recommended Directory Structure
~/.local/share/gopass/
├── stores/
│ ├── root/ # Default store (usually keep minimal)
│ │ ├── .gpg-id # Recipients for this store
│ │ ├── .git/
│ │ └── local/ # Machine-local entries
│ │
│ ├── v3/ # Main personal store
│ │ ├── .gpg-id
│ │ ├── .git/
│ │ ├── domains/
│ │ │ └── d000/
│ │ │ ├── infrastructure/
│ │ │ ├── services/
│ │ │ └── dev/
│ │ └── personal/
│ │
│ └── work/ # Work-only store
│ ├── .gpg-id # Different recipients
│ ├── .git/
│ └── projects/
│
└── config # gopass config
Team Secrets (Shared Store)
# Team store with multiple recipients
# Each team member has their GPG key in .gpg-id
# 1. Initialize team store
gopass init --path ~/.local/share/gopass/stores/team KEY1 KEY2 KEY3
# 2. Each team member clones
git clone git@github.com:org/gopass-team.git ~/.local/share/gopass/stores/team
# 3. Each team member mounts
gopass mounts add team ~/.local/share/gopass/stores/team
# 4. Verify recipients
gopass recipients --store team
# Should show all team member keys
# 5. Add new team member
gopass recipients add NEWMEMBER_KEYID --store team
gopass sync --store team
# 6. Remove team member (IMPORTANT)
gopass recipients remove LEAVING_MEMBER_KEYID --store team
# This re-encrypts ALL entries, they can no longer decrypt
gopass sync --store team
SECURITY: When someone leaves, remove their key. Old git history still has entries encrypted to them, but new entries and re-encrypted entries are safe.
Sync and Git Operations
# Sync all stores
gopass sync
# Sync specific store
gopass sync --store v3
# Check git status
gopass git status
gopass git status --store v3
# Manual git operations
cd ~/.local/share/gopass/stores/v3
git log --oneline -10
git remote -v
git pull origin main
git push origin main
# Fix diverged history
cd ~/.local/share/gopass/stores/v3
git pull --rebase origin main
gopass sync
# Force push (DANGEROUS - overwrites remote)
gopass git push --force --store v3
TIP: Enable autosync to avoid manual sync:
gopass config core.autosync true
Clone vs Init
# CLONE: Existing store from remote
git clone git@github.com:user/gopass-v3.git ~/.local/share/gopass/stores/v3
gopass mounts add v3 ~/.local/share/gopass/stores/v3
# INIT: New store from scratch
gopass init --path ~/.local/share/gopass/stores/newstore GPGKEYID
gopass mounts add newstore ~/.local/share/gopass/stores/newstore
# After init, set up remote
cd ~/.local/share/gopass/stores/newstore
git remote add origin git@github.com:user/gopass-newstore.git
git push -u origin main
# Clone includes .gpg-id (recipients)
# You must have private key for one of the recipients to decrypt
Migration Between Stores
# Copy single entry
gopass show old-store/path/entry | gopass insert -m new-store/path/entry
gopass rm old-store/path/entry
# Copy subtree (bulk)
for entry in $(gopass ls -f old-store/category/ | grep '^old-store/category/'); do
new_path=$(echo "$entry" | sed 's|old-store/|new-store/|')
gopass show "$entry" | gopass insert -m "$new_path"
echo "Migrated: $entry -> $new_path"
done
# After migration, verify and cleanup
gopass ls new-store/category/
gopass rm -r old-store/category/
# Change store path (move on filesystem)
mv ~/.local/share/gopass/stores/v2 ~/.local/share/gopass/stores/archive-v2
gopass mounts rm v2
gopass mounts add archive-v2 ~/.local/share/gopass/stores/archive-v2
Troubleshooting Mounts
# Mount not showing entries
gopass mounts # Check path is correct
ls ~/.local/share/gopass/stores/v3/ # Does it exist?
gopass recipients --store v3 # Can you decrypt?
# "Store not found"
gopass mounts add v3 ~/.local/share/gopass/stores/v3 # Re-add mount
# Wrong path in mount
gopass mounts rm v3
gopass mounts add v3 /correct/path/to/store
# Recipients mismatch
gpg --list-secret-keys # Your keys
gopass recipients --store v3 # Store recipients
# You need private key for at least one recipient
# Store corrupted
cd ~/.local/share/gopass/stores/v3
gopass fsck --store v3
git status
git fsck
# Re-clone from remote (last resort)
mv ~/.local/share/gopass/stores/v3 ~/.local/share/gopass/stores/v3.bak
git clone git@github.com:user/gopass-v3.git ~/.local/share/gopass/stores/v3
gopass mounts rm v3
gopass mounts add v3 ~/.local/share/gopass/stores/v3
Setup Script Example
#!/bin/bash
# gopass-setup.sh - Run on new machine after GPG key is imported
STORES_DIR="$HOME/.local/share/gopass/stores"
mkdir -p "$STORES_DIR"
# Clone stores
echo "Cloning v3 store..."
git clone git@github.com:user/gopass-v3.git "$STORES_DIR/v3"
echo "Cloning work store..."
git clone git@github.com:org/gopass-work.git "$STORES_DIR/work"
# Mount stores
echo "Mounting stores..."
gopass mounts add v3 "$STORES_DIR/v3"
gopass mounts add work "$STORES_DIR/work"
# Verify
echo "Verifying..."
gopass mounts
gopass ls v3/ | head -5
gopass ls work/ | head -5
echo "Setup complete!"
Backup Considerations
# Each store is a git repo - remote IS the backup
# Additional local backup
tar czf gopass-backup-$(date +%Y%m%d).tar.gz ~/.local/share/gopass/stores/
# Backup config too
tar czf gopass-config-$(date +%Y%m%d).tar.gz ~/.config/gopass/
# What to backup for disaster recovery:
# 1. GPG keys (export with gpg --export-secret-keys)
# 2. Store remotes (git@github.com:...)
# 3. Mount configuration (recreate with script)
# Restore from git remote (primary method)
git clone git@github.com:user/gopass-v3.git ~/.local/share/gopass/stores/v3
gopass mounts add v3 ~/.local/share/gopass/stores/v3
# Restore from tarball (fallback)
tar xzf gopass-backup.tar.gz -C ~/.local/share/gopass/
gopass mounts add v3 ~/.local/share/gopass/stores/v3
CRITICAL: GPG private key is the most important thing to backup. Without it, encrypted entries are unrecoverable.