detached 7d6918a

docs(wiki): add comprehensive pass secrets guide

Add dedicated guide covering pass installation, GPG key setup,
storing Gordon secrets, team workflows with multiple GPG keys,
Git integration, automation with passphrase-less keys, and
troubleshooting common issues.
commit
7d6918aacd88e11be0d5e176f4ed27dc0ea51852
author
brice · · 2026-01-16 06:36 UTC
parent
b8937bb
signature
unsigned
1 file · +293 -0
A wiki/guides/secrets-pass.md +293 -0
@@ -0,0 +1,293 @@
1+# Using Pass for Secrets
2+
3+Set up the Unix password manager (`pass`) as Gordon's secrets backend for secure credential storage.
4+
5+## What You'll Learn
6+
7+- Installing and initializing pass
8+- Storing Gordon secrets securely
9+- Configuring Gordon to use pass
10+- Team workflows with shared GPG keys
11+- Troubleshooting common issues
12+
13+## Prerequisites
14+
15+- Linux or macOS system
16+- GPG installed
17+- Basic understanding of GPG keys
18+
19+## Why Pass?
20+
21+Pass is a simple, Unix-philosophy password manager that:
22+
23+- Stores secrets as GPG-encrypted files
24+- Integrates with Git for version control
25+- Works with standard Unix tools
26+- Supports multiple GPG keys for team access
27+
28+## Installation
29+
30+### Ubuntu/Debian
31+
32+```bash
33+sudo apt install pass gnupg
34+```
35+
36+### macOS
37+
38+```bash
39+brew install pass gnupg
40+```
41+
42+### Arch Linux
43+
44+```bash
45+sudo pacman -S pass gnupg
46+```
47+
48+## Initial Setup
49+
50+### 1. Generate a GPG Key (if needed)
51+
52+```bash
53+# Generate a new GPG key
54+gpg --gen-key
55+
56+# Follow prompts:
57+# - Real name: Gordon Server
58+# - Email: gordon@yourdomain.com
59+# - Passphrase: (use a strong passphrase or leave empty for automation)
60+```
61+
62+List your keys to find the key ID:
63+
64+```bash
65+gpg --list-keys
66+```
67+
68+Output:
69+
70+```
71+pub ed25519 2024-01-15 [SC]
72+ ABC123DEF456... <-- This is your key ID
73+uid [ultimate] Gordon Server <gordon@yourdomain.com>
74+```
75+
76+### 2. Initialize Pass Store
77+
78+```bash
79+pass init ABC123DEF456... # Use your GPG key ID
80+```
81+
82+This creates `~/.password-store/`.
83+
84+### 3. Create Gordon Secrets
85+
86+```bash
87+# Registry password hash (bcrypt)
88+# Generate with: htpasswd -nbB admin yourpassword | cut -d: -f2
89+pass insert gordon/registry/password_hash
90+
91+# Token secret (random 32+ chars for JWT signing)
92+pass insert gordon/registry/token_secret
93+# Or generate automatically:
94+openssl rand -base64 32 | pass insert -m gordon/registry/token_secret
95+```
96+
97+## Gordon Configuration
98+
99+### Enable Pass Backend
100+
101+```toml
102+[secrets]
103+backend = "pass"
104+
105+[registry_auth]
106+enabled = true
107+type = "token"
108+username = "admin"
109+password_hash = "gordon/registry/password_hash"
110+token_secret = "gordon/registry/token_secret"
111+```
112+
113+### Using Secrets in Environment Files
114+
115+Reference pass secrets in your app's environment files:
116+
117+```bash
118+# ~/.gordon/env/app_mydomain_com.env
119+DATABASE_URL=postgresql://user:${pass:myapp/db/password}@postgres:5432/app
120+API_KEY=${pass:myapp/api/key}
121+JWT_SECRET=${pass:myapp/jwt/secret}
122+```
123+
124+## Organizing Secrets
125+
126+Recommended directory structure in pass:
127+
128+```
129+~/.password-store/
130+├── gordon/
131+│ └── registry/
132+│ ├── password_hash.gpg
133+│ └── token_secret.gpg
134+├── myapp/
135+│ ├── db/
136+│ │ └── password.gpg
137+│ ├── api/
138+│ │ └── key.gpg
139+│ └── jwt/
140+│ └── secret.gpg
141+└── production/
142+ └── stripe/
143+ └── secret_key.gpg
144+```
145+
146+## Team Workflows
147+
148+### Multiple GPG Keys
149+
150+Allow multiple team members to decrypt secrets:
151+
152+```bash
153+# Initialize with multiple keys
154+pass init KEY_ID_1 KEY_ID_2 KEY_ID_3
155+
156+# Or add keys later
157+pass init --path=gordon KEY_ID_1 KEY_ID_2
158+```
159+
160+### Git Integration
161+
162+Version control your encrypted secrets:
163+
164+```bash
165+# Initialize git in pass store
166+pass git init
167+
168+# Add remote
169+pass git remote add origin git@github.com:yourorg/secrets.git
170+
171+# Commit and push
172+pass git push -u origin main
173+```
174+
175+### Pull Secrets on New Server
176+
177+```bash
178+# Clone the pass store
179+git clone git@github.com:yourorg/secrets.git ~/.password-store
180+
181+# Import team GPG keys
182+gpg --import team-member.pub
183+```
184+
185+## Automation (Passphrase-less Keys)
186+
187+For servers running Gordon automatically, use a GPG key without a passphrase:
188+
189+```bash
190+# Generate key without passphrase
191+gpg --batch --gen-key <<EOF
192+Key-Type: EdDSA
193+Key-Curve: ed25519
194+Name-Real: Gordon Automation
195+Name-Email: gordon@server.local
196+Expire-Date: 0
197+%no-protection
198+%commit
199+EOF
200+```
201+
202+> **Security Note**: Protect access to the server itself when using passphrase-less keys.
203+
204+## Running in Containers
205+
206+See [Running Gordon in a Container](/wiki/guides/running-in-container.md#using-pass-secrets-backend) for container-specific setup.
207+
208+Quick summary:
209+
210+```bash
211+docker run -d \
212+ --name gordon \
213+ -v $HOME/.gnupg:/home/gordon/.gnupg:ro \
214+ -v $HOME/.password-store:/home/gordon/.password-store:ro \
215+ gordon-with-pass
216+```
217+
218+## Troubleshooting
219+
220+### "gpg: decryption failed: No secret key"
221+
222+Your GPG private key isn't available.
223+
224+```bash
225+# List available secret keys
226+gpg --list-secret-keys
227+
228+# If empty, import your key
229+gpg --import your-private-key.asc
230+```
231+
232+### "pass: command not found"
233+
234+Pass isn't installed.
235+
236+```bash
237+# Ubuntu/Debian
238+sudo apt install pass
239+
240+# macOS
241+brew install pass
242+```
243+
244+### "Error: password store is empty"
245+
246+Initialize pass first:
247+
248+```bash
249+pass init YOUR_GPG_KEY_ID
250+```
251+
252+### "gpg: public key decryption failed: Inappropriate ioctl for device"
253+
254+GPG needs a TTY for passphrase entry:
255+
256+```bash
257+export GPG_TTY=$(tty)
258+```
259+
260+Add to `~/.bashrc` for persistence.
261+
262+### "gpg-agent: no running gpg-agent"
263+
264+Start the GPG agent:
265+
266+```bash
267+gpg-agent --daemon
268+```
269+
270+### Permissions Issues
271+
272+Ensure correct permissions:
273+
274+```bash
275+chmod 700 ~/.gnupg
276+chmod 600 ~/.gnupg/*
277+chmod 700 ~/.password-store
278+```
279+
280+## Security Best Practices
281+
282+1. **Protect GPG keys**: Back up securely, use strong passphrases for interactive use
283+2. **Limit access**: Use separate GPG keys per environment (dev, staging, prod)
284+3. **Rotate secrets**: Periodically update passwords and tokens
285+4. **Audit access**: Review who has GPG keys for each environment
286+5. **Use Git**: Track changes to secrets with pass git integration
287+
288+## Related
289+
290+- [Secrets Configuration](/docs/config/secrets.md)
291+- [Registry Authentication](/docs/config/registry-auth.md)
292+- [Running in Containers](/wiki/guides/running-in-container.md)
293+- [Using SOPS for Secrets](./secrets-sops.md)
@@ -0,0 +1,293 @@
1+# Using Pass for Secrets
2+
3+Set up the Unix password manager (`pass`) as Gordon's secrets backend for secure credential storage.
4+
5+## What You'll Learn
6+
7+- Installing and initializing pass
8+- Storing Gordon secrets securely
9+- Configuring Gordon to use pass
10+- Team workflows with shared GPG keys
11+- Troubleshooting common issues
12+
13+## Prerequisites
14+
15+- Linux or macOS system
16+- GPG installed
17+- Basic understanding of GPG keys
18+
19+## Why Pass?
20+
21+Pass is a simple, Unix-philosophy password manager that:
22+
23+- Stores secrets as GPG-encrypted files
24+- Integrates with Git for version control
25+- Works with standard Unix tools
26+- Supports multiple GPG keys for team access
27+
28+## Installation
29+
30+### Ubuntu/Debian
31+
32+```bash
33+sudo apt install pass gnupg
34+```
35+
36+### macOS
37+
38+```bash
39+brew install pass gnupg
40+```
41+
42+### Arch Linux
43+
44+```bash
45+sudo pacman -S pass gnupg
46+```
47+
48+## Initial Setup
49+
50+### 1. Generate a GPG Key (if needed)
51+
52+```bash
53+# Generate a new GPG key
54+gpg --gen-key
55+
56+# Follow prompts:
57+# - Real name: Gordon Server
58+# - Email: gordon@yourdomain.com
59+# - Passphrase: (use a strong passphrase or leave empty for automation)
60+```
61+
62+List your keys to find the key ID:
63+
64+```bash
65+gpg --list-keys
66+```
67+
68+Output:
69+
70+```
71+pub ed25519 2024-01-15 [SC]
72+ ABC123DEF456... <-- This is your key ID
73+uid [ultimate] Gordon Server <gordon@yourdomain.com>
74+```
75+
76+### 2. Initialize Pass Store
77+
78+```bash
79+pass init ABC123DEF456... # Use your GPG key ID
80+```
81+
82+This creates `~/.password-store/`.
83+
84+### 3. Create Gordon Secrets
85+
86+```bash
87+# Registry password hash (bcrypt)
88+# Generate with: htpasswd -nbB admin yourpassword | cut -d: -f2
89+pass insert gordon/registry/password_hash
90+
91+# Token secret (random 32+ chars for JWT signing)
92+pass insert gordon/registry/token_secret
93+# Or generate automatically:
94+openssl rand -base64 32 | pass insert -m gordon/registry/token_secret
95+```
96+
97+## Gordon Configuration
98+
99+### Enable Pass Backend
100+
101+```toml
102+[secrets]
103+backend = "pass"
104+
105+[registry_auth]
106+enabled = true
107+type = "token"
108+username = "admin"
109+password_hash = "gordon/registry/password_hash"
110+token_secret = "gordon/registry/token_secret"
111+```
112+
113+### Using Secrets in Environment Files
114+
115+Reference pass secrets in your app's environment files:
116+
117+```bash
118+# ~/.gordon/env/app_mydomain_com.env
119+DATABASE_URL=postgresql://user:${pass:myapp/db/password}@postgres:5432/app
120+API_KEY=${pass:myapp/api/key}
121+JWT_SECRET=${pass:myapp/jwt/secret}
122+```
123+
124+## Organizing Secrets
125+
126+Recommended directory structure in pass:
127+
128+```
129+~/.password-store/
130+├── gordon/
131+│ └── registry/
132+│ ├── password_hash.gpg
133+│ └── token_secret.gpg
134+├── myapp/
135+│ ├── db/
136+│ │ └── password.gpg
137+│ ├── api/
138+│ │ └── key.gpg
139+│ └── jwt/
140+│ └── secret.gpg
141+└── production/
142+ └── stripe/
143+ └── secret_key.gpg
144+```
145+
146+## Team Workflows
147+
148+### Multiple GPG Keys
149+
150+Allow multiple team members to decrypt secrets:
151+
152+```bash
153+# Initialize with multiple keys
154+pass init KEY_ID_1 KEY_ID_2 KEY_ID_3
155+
156+# Or add keys later
157+pass init --path=gordon KEY_ID_1 KEY_ID_2
158+```
159+
160+### Git Integration
161+
162+Version control your encrypted secrets:
163+
164+```bash
165+# Initialize git in pass store
166+pass git init
167+
168+# Add remote
169+pass git remote add origin git@github.com:yourorg/secrets.git
170+
171+# Commit and push
172+pass git push -u origin main
173+```
174+
175+### Pull Secrets on New Server
176+
177+```bash
178+# Clone the pass store
179+git clone git@github.com:yourorg/secrets.git ~/.password-store
180+
181+# Import team GPG keys
182+gpg --import team-member.pub
183+```
184+
185+## Automation (Passphrase-less Keys)
186+
187+For servers running Gordon automatically, use a GPG key without a passphrase:
188+
189+```bash
190+# Generate key without passphrase
191+gpg --batch --gen-key <<EOF
192+Key-Type: EdDSA
193+Key-Curve: ed25519
194+Name-Real: Gordon Automation
195+Name-Email: gordon@server.local
196+Expire-Date: 0
197+%no-protection
198+%commit
199+EOF
200+```
201+
202+> **Security Note**: Protect access to the server itself when using passphrase-less keys.
203+
204+## Running in Containers
205+
206+See [Running Gordon in a Container](/wiki/guides/running-in-container.md#using-pass-secrets-backend) for container-specific setup.
207+
208+Quick summary:
209+
210+```bash
211+docker run -d \
212+ --name gordon \
213+ -v $HOME/.gnupg:/home/gordon/.gnupg:ro \
214+ -v $HOME/.password-store:/home/gordon/.password-store:ro \
215+ gordon-with-pass
216+```
217+
218+## Troubleshooting
219+
220+### "gpg: decryption failed: No secret key"
221+
222+Your GPG private key isn't available.
223+
224+```bash
225+# List available secret keys
226+gpg --list-secret-keys
227+
228+# If empty, import your key
229+gpg --import your-private-key.asc
230+```
231+
232+### "pass: command not found"
233+
234+Pass isn't installed.
235+
236+```bash
237+# Ubuntu/Debian
238+sudo apt install pass
239+
240+# macOS
241+brew install pass
242+```
243+
244+### "Error: password store is empty"
245+
246+Initialize pass first:
247+
248+```bash
249+pass init YOUR_GPG_KEY_ID
250+```
251+
252+### "gpg: public key decryption failed: Inappropriate ioctl for device"
253+
254+GPG needs a TTY for passphrase entry:
255+
256+```bash
257+export GPG_TTY=$(tty)
258+```
259+
260+Add to `~/.bashrc` for persistence.
261+
262+### "gpg-agent: no running gpg-agent"
263+
264+Start the GPG agent:
265+
266+```bash
267+gpg-agent --daemon
268+```
269+
270+### Permissions Issues
271+
272+Ensure correct permissions:
273+
274+```bash
275+chmod 700 ~/.gnupg
276+chmod 600 ~/.gnupg/*
277+chmod 700 ~/.password-store
278+```
279+
280+## Security Best Practices
281+
282+1. **Protect GPG keys**: Back up securely, use strong passphrases for interactive use
283+2. **Limit access**: Use separate GPG keys per environment (dev, staging, prod)
284+3. **Rotate secrets**: Periodically update passwords and tokens
285+4. **Audit access**: Review who has GPG keys for each environment
286+5. **Use Git**: Track changes to secrets with pass git integration
287+
288+## Related
289+
290+- [Secrets Configuration](/docs/config/secrets.md)
291+- [Registry Authentication](/docs/config/registry-auth.md)
292+- [Running in Containers](/wiki/guides/running-in-container.md)
293+- [Using SOPS for Secrets](./secrets-sops.md)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close