gopass - Password Store

Overview

gopass is a GPG-encrypted password store with git sync. Used for infrastructure credentials, API keys, and service accounts.

Location: ~/.password-store/

Store Structure

~/.password-store/
├── v2/                      # Current structure (use this)
│   ├── DOMUS/
│   │   ├── servers/         # Server credentials
│   │   │   ├── ise-01/      # ISE 3.4
│   │   │   │   ├── (main)   # GUI admin
│   │   │   │   ├── cli      # CLI admin (SSH)
│   │   │   │   ├── dataconnect
│   │   │   │   └── ers
│   │   │   └── ise-02/      # ISE 3.2 (deprecated)
│   │   └── network/         # Network devices
│   └── ARCANA/
│       └── api/             # API credentials
├── ADMINISTRATIO/           # Legacy (placeholders → v2)
├── ARCANA/                  # Legacy (placeholders → v2)
└── infra/                   # Legacy (placeholders → v2)

Basic Commands

Command Description

gopass show path

Display password and metadata

gopass show -o path

Password only (no metadata)

gopass -c path

Copy password to clipboard

gopass generate -p path 24

Generate 24-char password and print

gopass edit path

Edit entry in $EDITOR

gopass ls

List all entries (tree view)

gopass ls -f

List all entries (flat, full paths)

gopass sync

Sync with git remote

gopass rm path

Delete entry

gopass mv old new

Move/rename entry

gopass cp old new

Copy entry (keeps original)

Copy and Move Entries

Copy to new location (preserve original)

gopass cp ARCANA/ssh/gitea v2/ARCANA/ssh/personal/gitea

Move to new location (delete original)

gopass mv ARCANA/ssh/gitea v2/ARCANA/ssh/personal/gitea

Copy with placeholder at old location

For migrations, leave a redirect at the old path:

# Copy to new location
gopass cp ARCANA/ssh/gitea v2/ARCANA/ssh/personal/gitea

# Replace old with placeholder
cat << 'EOF' | gopass insert -f -m ARCANA/ssh/gitea
MOVED_TO_V2
---
status: deprecated
moved_to: v2/ARCANA/ssh/personal/gitea
EOF

Multiline Insert (Heredoc)

Insert structured entries with YAML metadata:

cat << 'EOF' | gopass insert -f -m v2/DOMUS/servers/myserver
<PASSWORD>
---
type: service-type
node: myserver

connection:
  host: myserver.inside.domusdigitalis.dev
  ip: 10.50.1.X
  port: 443
  protocol: https

credentials:
  username: admin
  auth: password

meta:
  created: 2026-02-11
  version: "1.0"
  notes: Service description
EOF

Flags

Flag Description

-f

Force overwrite existing entry

-m

Multiline mode (read from stdin until EOF)

Server Entry Template

Standard structure for server credentials:

cat << 'EOF' | gopass insert -f -m v2/DOMUS/servers/<hostname>
<PASSWORD>
---
type: <service-type>
node: <hostname>
role: <role>

connection:
  host: <hostname>.inside.domusdigitalis.dev
  ip: 10.50.1.X
  port: 443
  protocol: https
  url: https://<hostname>.inside.domusdigitalis.dev/admin

credentials:
  username: admin
  auth: password

bootstrap:
  hostname: <hostname>
  ip: 10.50.1.X
  netmask: 255.255.255.0
  gateway: 10.50.1.1
  dns_domain: inside.domusdigitalis.dev
  dns_primary: 10.50.1.90
  ntp: 10.50.1.1
  timezone: America/Los_Angeles

meta:
  created: 2026-02-11
  version: "1.0"
  notes: Service description
EOF

Common Types

Type Usage

cisco-ise

ISE GUI admin

cisco-ise-cli

ISE CLI/SSH admin

cisco-ise-ers

ISE ERS API

database

DataConnect, Oracle, PostgreSQL

keycloak

Keycloak admin

vyos

VyOS router/firewall admin

cisco-wlc

Wireless controller

CLI Entry Template

Separate CLI credentials from GUI:

cat << 'EOF' | gopass insert -f -m v2/DOMUS/servers/<hostname>/cli
<PASSWORD>
---
type: <service-type>-cli
node: <hostname>
service: CLI Admin (SSH/Console)

connection:
  host: <hostname>.inside.domusdigitalis.dev
  ip: 10.50.1.X
  port: 22
  protocol: ssh

credentials:
  username: admin
  auth: password

bootstrap:
  hostname: <hostname>
  gateway: 10.50.1.1
  dns_domain: inside.domusdigitalis.dev
  dns_primary: 10.50.1.90
  ntp: 10.50.1.1
  timezone: America/Los_Angeles

meta:
  created: 2026-02-11
  version: "1.0"
  notes: CLI admin credentials
EOF

API Entry Template

For REST/API credentials:

cat << 'EOF' | gopass insert -f -m v2/DOMUS/servers/<hostname>/ers
<PASSWORD>
---
type: <service-type>-ers
service: ERS API
host: <hostname>.inside.domusdigitalis.dev
ip: 10.50.1.X
port: 9060
protocol: https
endpoint: /ers/config
username: ersadmin
auth: basic

meta:
  created: 2026-02-11
  notes: ERS API for automation
EOF

Migration Placeholders

When moving entries to new paths, leave redirects:

cat << 'EOF' | gopass insert -f -m old/path/entry
MOVED_TO_V2
---
status: deprecated
moved_to: v2/new/path/entry
note: Use gopass show v2/new/path/entry
EOF

This ensures anyone using old paths gets directed to new location.

Generate and Update

Generate password, then add metadata:

# Generate password
gopass generate -p v2/DOMUS/servers/newserver 24

# Add metadata
gopass edit v2/DOMUS/servers/newserver

Or generate with immediate edit:

gopass generate -e v2/DOMUS/servers/newserver 24

Search and Filter

# Find entries by name
gopass ls -f | grep -i ise

# Search within entry content
gopass grep "admin"

# Show specific field
gopass show v2/DOMUS/servers/ise-01 username

Subentry Structure

Organize related credentials under parent:

v2/DOMUS/servers/ise-01/
├── (main)        # gopass show v2/DOMUS/servers/ise-01
├── cli           # gopass show v2/DOMUS/servers/ise-01/cli
├── dataconnect   # gopass show v2/DOMUS/servers/ise-01/dataconnect
└── ers           # gopass show v2/DOMUS/servers/ise-01/ers

Sync and Backup

# Sync with remote (requires SSH key)
gopass sync

# Manual git operations
cd ~/.password-store && git status

# Export for backup (encrypted)
gopass export > backup.gpg

Troubleshooting

Git Push Fails (SSH)

ssh_askpass: exec(/usr/lib/ssh/ssh-askpass): No such file or directory

Cause: YubiKey not touched or SSH agent not running.

Fix: Touch YubiKey, then gopass sync.

Entry Not Found After Move

Check if placeholder exists at old path:

gopass show old/path/entry
# Should show: MOVED_TO_V2 with new location

v3 Store - Domain-Aligned Structure

v3 is the current recommended structure. It mirrors dsec domain organization for consistency across secrets management tools.

v3 Architecture

~/.local/share/gopass/stores/v3/
├── domains/
│   ├── d000/                    # Personal infrastructure
│   │   ├── hardware/            # Physical devices, BIOS, iLO
│   │   ├── identity/            # SSO, AD accounts
│   │   ├── network/             # Network secrets (consolidated)
│   │   │   ├── devices/         # Switch, AP, WLC passwords
│   │   │   ├── radius/          # RADIUS shared secrets
│   │   │   ├── snmp/            # SNMP community strings
│   │   │   ├── routing/         # OSPF, EIGRP, BGP keys
│   │   │   └── tacacs/          # TACACS+ keys
│   │   ├── servers/             # Server credentials
│   │   ├── storage/             # NAS, SAN, backup
│   │   └── wifi/                # PSK, iPSK, WPA-E
│   └── d001/                    # Client domains
│       ├── identity/
│       └── network/
├── keys/
│   ├── ssh/
│   │   ├── personal/            # Personal SSH keys
│   │   └── service/             # Service account keys
│   ├── age/                     # Age encryption keys
│   ├── gpg/                     # GPG key metadata
│   └── encryption/              # Other encryption keys
├── certificates/                # PKI certificates
├── licenses/                    # Software licenses
└── personal/                    # Personal passwords
    ├── finance/                 # Banking, investments
    ├── shopping/                # E-commerce
    ├── social/                  # Social media
    ├── streaming/               # Netflix, Spotify
    ├── gaming/                  # Steam, Epic
    ├── email/                   # Email accounts
    ├── documents/               # Document services
    ├── recovery/                # Recovery codes, 2FA backup
    ├── travel/                  # Airlines, hotels
    ├── health/                  # Healthcare portals
    └── government/              # Tax, DMV, etc.

Design Principles

Principle Implementation

Domain Alignment

Mirrors dsec structure (d000, d001+)

No Top-Level Sprawl

Network secrets nested under domains, not at root

Hardware Security

GPG keys on YubiKey (touch required)

Multi-Remote Sync

GitHub, GitLab, Gitea (3-way redundancy)

YAML Metadata

Structured metadata for all entries

v3 Commands

# List v3 store
gopass ls v3

# Show entry from v3
gopass show v3/domains/d000/servers/ise-01

# Add to v3 with YAML metadata
cat << 'EOF' | gopass insert -f -m v3/domains/d000/network/radius/ise-shared-secret
<SECRET>
---
type: radius-shared-secret
device: all-network-devices
created: 2026-02-17
rotation: 180-days
EOF

# Sync all stores
gopass sync

v3 Mount Configuration

v3 runs as a mounted substore:

# Check mounts
gopass mounts

# Expected output:
# gopass (~/.password-store)
# ├── v2 (~/.local/share/gopass/stores/v2)
# └── v3 (~/.local/share/gopass/stores/v3)

Multi-Remote Setup

v3 syncs to multiple git remotes for redundancy:

# Check remotes
git -C ~/.local/share/gopass/stores/v3 remote -v

# Expected:
# origin    git@github.com:user/gopass-v3.git (push)
# gitlab    git@gitlab.com:user/gopass-v3.git (push)
# gitea     git@gitea.example.com:user/gopass-v3.git (push)

# Push to all remotes
git -C ~/.local/share/gopass/stores/v3 push origin main
git -C ~/.local/share/gopass/stores/v3 push gitlab main
git -C ~/.local/share/gopass/stores/v3 push gitea main

Migration from v2

# Copy entry from v2 to v3
gopass cp v2/DOMUS/servers/ise-01 v3/domains/d000/servers/ise-01

# Leave placeholder at old location
cat << 'EOF' | gopass insert -f -m v2/DOMUS/servers/ise-01
MOVED_TO_V3
---
status: deprecated
moved_to: v3/domains/d000/servers/ise-01
EOF

OTP / TOTP Management

gopass supports TOTP (Time-based One-Time Passwords) for 2FA.

Add OTP from QR Code

Scan and add directly:

gopass otp add v3/personal/site.com
# Paste otpauth:// URI when prompted

Add OTP from Hex Key

Some sites display the secret as spaced hex instead of base32:

Site shows: DE AD BE EF 12 34 56 78
TOTP needs: Base32 encoded

Convert hex to base32:

HEX="DE AD BE EF 12 34 56 78"
HEX_CLEAN=$(echo "$HEX" | tr -d ' ')
echo "$HEX_CLEAN" | xxd -r -p | base32

Output: 32W353YSGRLHQ===

Add to gopass:

gopass insert -m v3/personal/site.com/otp << 'EOF'
otpauth://totp/site.com:username?secret=32W353YSGRLHQ&issuer=site.com
EOF

One-Liner: Hex to gopass OTP

HEX="DE AD BE EF 12 34 56 78"
SECRET=$(echo "$HEX" | tr -d ' ' | xxd -r -p | base32 | tr -d '=')
echo "otpauth://totp/SITE:USER?secret=$SECRET&issuer=SITE" | gopass insert -m v3/personal/site/otp

Generate OTP Codes

# Show current TOTP code
gopass otp v3/personal/site.com/otp

# Copy to clipboard
gopass otp -c v3/personal/site.com/otp

OTP Entry Format

The entry must contain an otpauth:// URI:

otpauth://totp/LABEL?secret=BASE32SECRET&issuer=ISSUER&digits=6&period=30
Parameter Description

secret

Base32-encoded secret (required)

issuer

Service name (optional but recommended)

digits

Code length, usually 6 (default)

period

Rotation interval in seconds, usually 30 (default)