Pass & Passage Credential Management
Comprehensive guide to managing credentials in pass (GPG-based) and passage (age-based) password stores using heredocs for structured, multi-line entries.
Quick Reference
Understanding Pass vs Passage
| Feature | pass | passage |
|---|---|---|
Encryption |
GPG |
age |
Key Management |
GPG keyring |
age identity files |
Yubikey Support |
Yes (GPG) |
Yes (age plugin) |
Speed |
Slower |
Faster |
Store Location |
|
|
Recipients File |
|
|
Entry Format Convention
Standard format for infrastructure credentials:
PASSWORD_ON_FIRST_LINE
---
hostname: server-name
fqdn: server.domain.com
ip: 10.0.0.1
username: admin
password: same-as-first-line
hash: $6$...SHA512-hash-for-cloud-init...
ssh_port: 22
os: Fedora/Ubuntu/Arch
purpose: Brief description
created: YYYY-MM-DD
notes: Additional information
Why password on first line? Convention for pass -c (clipboard) which copies only the first line.
Complete Workflows
Workflow 1: New Server/VM Credential
3. Store in pass (heredoc)
pass insert -m ADMINISTRATIO/servers/myserver-01 << EOF
$PASS
---
hostname: myserver-01
fqdn: myserver-01.inside.domain.com
ip: 10.50.1.100
username: ansible
password: $PASS
hash: $HASH
ssh_port: 22
os: Fedora Cloud 41
purpose: Application server
created: $(date +%Y-%m-%d)
notes: Created via automation
EOF
4. Store in passage (same format)
passage insert -m servers/myserver-01 << EOF
$PASS
---
hostname: myserver-01
fqdn: myserver-01.inside.domain.com
ip: 10.50.1.100
username: ansible
password: $PASS
hash: $HASH
ssh_port: 22
os: Fedora Cloud 41
purpose: Application server
created: $(date +%Y-%m-%d)
notes: Created via automation
EOF
Workflow 2: API Credentials
pass insert -m ARCANA/api/cloudflare << 'EOF'
cf_api_token_here
---
service: Cloudflare
type: API Token
scope: Zone DNS Edit - domusdigitalis.dev
username: admin@domain.com
token: cf_api_token_here
created: 2026-01-13
expires: never
notes: Used for Let's Encrypt DNS-01 challenge
EOF
Workflow 3: Network Device Credentials
pass insert -m ADMINISTRATIO/network/switch-core-01 << 'EOF'
enable_password_here
---
hostname: switch-core-01
ip: 10.50.1.1
type: Cisco 3560CX
username: admin
password: login_password
enable: enable_password_here
ssh_port: 22
snmp_community: readonly_community
created: 2026-01-13
notes: Core switch - management VLAN
EOF
Workflow 4: Database Credentials
pass insert -m ARCANA/api/ise-dataconnect << 'EOF'
db_password_here
---
service: ISE DataConnect
type: Oracle Database
host: 10.50.1.21
port: 2484
database: cpm
username: dataconnect
password: db_password_here
ssl: required
created: 2026-01-13
notes: Read-only access to ISE operational data
EOF
Heredoc Variants
Literal Heredoc (No Variable Expansion)
Use << 'EOF' (quoted) when the content contains $ that should NOT be expanded:
pass insert -m example << 'EOF'
password123
---
notes: Cost is $500 per month
regex: ^[a-z]+$
EOF
Scripted Entry Creation
Function for Servers
Add to your shell config (~/.bashrc, ~/.zshrc, ~/.config/fish/config.fish):
Bash/Zsh version
new-server-cred() {
local name="$1"
local ip="$2"
local purpose="${3:-General purpose server}"
if [[ -z "$name" || -z "$ip" ]]; then
echo "Usage: new-server-cred <hostname> <ip> [purpose]"
return 1
fi
local PASS=$(openssl rand -base64 16 | tr -d '/+=' | head -c 16)
local HASH=$(echo "$PASS" | openssl passwd -6 -stdin)
pass insert -m "ADMINISTRATIO/servers/$name" << EOF
$PASS
---
hostname: $name
fqdn: $name.inside.domusdigitalis.dev
ip: $ip
username: ansible
password: $PASS
hash: $HASH
ssh_port: 22
os: Fedora Cloud 41
purpose: $purpose
created: $(date +%Y-%m-%d)
notes: Auto-generated credentials
EOF
echo "Created: ADMINISTRATIO/servers/$name"
echo "Password: $PASS"
echo "Hash stored for cloud-init use"
}
Fish version
function new-server-cred
set name $argv[1]
set ip $argv[2]
set purpose (test -n "$argv[3]" && echo $argv[3] || echo "General purpose server")
if test -z "$name" -o -z "$ip"
echo "Usage: new-server-cred <hostname> <ip> [purpose]"
return 1
end
set PASS (openssl rand -base64 16 | tr -d '/+=' | head -c 16)
set HASH (echo "$PASS" | openssl passwd -6 -stdin)
pass insert -m "ADMINISTRATIO/servers/$name" << EOF
$PASS
---
hostname: $name
fqdn: $name.inside.domusdigitalis.dev
ip: $ip
username: ansible
password: $PASS
hash: $HASH
ssh_port: 22
os: Fedora Cloud 41
purpose: $purpose
created: (date +%Y-%m-%d)
notes: Auto-generated credentials
EOF
echo "Created: ADMINISTRATIO/servers/$name"
echo "Password: $PASS"
end
Extracting Fields
Get Specific Field
Directory Organization
Recommended Structure for pass
~/.password-store/
├── ADMINISTRATIO/
│ ├── servers/
│ │ ├── vault-01
│ │ ├── monitoring-01
│ │ ├── home-dc01
│ │ └── template
│ ├── network/
│ │ ├── switch-core-01
│ │ ├── ise-02
│ │ └── template
│ ├── devices/
│ │ └── template
│ └── work/
│ └── template
├── ARCANA/
│ ├── api/
│ │ ├── cloudflare
│ │ ├── ise-02
│ │ ├── ise-dataconnect
│ │ └── template
│ ├── ssh/
│ │ ├── github
│ │ ├── gitlab
│ │ └── template
│ └── crypto/
│ └── template
└── .gpg-id
Syncing Between Pass and Passage
Security Best Practices
Troubleshooting
Real-World Examples
Example: ISE Certificate Manager VM
PASS=$(openssl rand -base64 16 | tr -d '/+=' | head -c 16)
HASH=$(echo "$PASS" | openssl passwd -6 -stdin)
pass insert -m ADMINISTRATIO/servers/vault-01 << EOF
$PASS
---
hostname: vault-01
fqdn: vault-01.inside.domusdigitalis.dev
ip: 10.50.1.60
username: ansible
password: $PASS
hash: $HASH
ssh_port: 22
os: Fedora Cloud 41
purpose: Let's Encrypt certificate automation for ISE portals
created: $(date +%Y-%m-%d)
notes: DNS-01 challenge via Cloudflare API
EOF
Example: Cloudflare API Token
pass insert -m ARCANA/api/cloudflare-dns << 'EOF'
your_cloudflare_api_token_here
---
service: Cloudflare
type: API Token
zone: domusdigitalis.dev
permissions: Zone DNS Edit, Zone Read
created: 2026-01-13
expires: never
usage: certbot DNS-01 challenge for Let's Encrypt
notes: Created from dash.cloudflare.com > My Profile > API Tokens
EOF
Example: Network Switch
pass insert -m ADMINISTRATIO/network/switch-3560cx-01 << 'EOF'
enable_secret_here
---
hostname: switch-3560cx-01
ip: 10.50.1.1
model: Cisco 3560CX-8PC-S
ios_version: 15.2(7)E7
username: admin
password: login_password_here
enable: enable_secret_here
console_port: /dev/ttyUSB0
console_speed: 9600
mgmt_vlan: 1
created: 2026-01-13
notes: Core switch - 8-port PoE+
EOF
Quick Command Reference
| Task | Command |
|---|---|
List all entries |
|
Show entry |
|
Copy password to clipboard |
|
Insert with heredoc |
|
Generate and store |
|
Edit existing |
|
Delete entry |
|
Search entries |
|
Git operations (pass) |
|