v2.11.0 dca6537

secrets.md RawHistoryFolder

Secrets Configuration

Configure how Gordon stores and retrieves sensitive data.

Configuration

The secrets backend is configured within the [auth] section:

[auth]
secrets_backend = "pass"  # "pass", "sops", or "unsafe"

Options

Option Type Default Description
secrets_backend string "unsafe" Secrets storage backend

Backends

Uses the Unix password manager (pass) for secure secret storage:

[auth]
secrets_backend = "pass"

Setup:

# Install pass
sudo apt install pass

# Initialize with GPG key
pass init your-gpg-key-id

# Store secrets
pass insert gordon/auth/password_hash
pass insert gordon/auth/token_secret

Usage in config:

[auth]
password_hash = "gordon/auth/password_hash"  # Path in pass store
token_secret = "gordon/auth/token_secret"

Benefits:

  • GPG-encrypted storage
  • Version control friendly (encrypted files)
  • Standard Unix tooling
  • Works with team GPG keys

Route secrets storage:

  • gordon secrets set stores per-domain secrets in pass under gordon/env/<sanitized-domain>/<KEY> (dots/colons/slashes → underscores)
  • Existing .env files are auto-migrated on startup and renamed to .env.migrated
  • Attachment secrets are stored under gordon/env/attachments/<container-name>/<KEY> with a .keys manifest
  • Use gordon secrets set <domain> --attachment <service> KEY=value to manage them

SOPS

Uses Mozilla SOPS for encrypted file-based secrets:

[auth]
secrets_backend = "sops"

Setup:

# Install sops
brew install sops  # macOS
# or download from https://github.com/getsops/sops/releases

# Create encrypted secrets file
sops secrets.yaml

Usage in env files:

# ~/.gordon/env/app_mydomain_com.env
API_SECRET=${sops:secrets.yaml:api.secret}
DB_PASSWORD=${sops:secrets.yaml:database.password}

Benefits:

  • Multiple encryption backends (AWS KMS, GCP KMS, Azure Key Vault, PGP)
  • YAML/JSON file encryption
  • Git-friendly (encrypted files in repo)

Security:

  • Absolute paths are rejected to prevent arbitrary file access
  • Path traversal (..) is blocked
  • Only relative paths from your config directory are allowed

Route secrets storage:

  • Domain secrets stay in .env files
  • Use ${sops:...} syntax to resolve encrypted values

Attachment secrets storage:

  • Attachment secrets are stored in gordon-<container-name>.env files alongside domain env files
  • Use ${sops:...} syntax inside attachment env files to resolve encrypted values
  • Use gordon secrets set <domain> --attachment <service> KEY=value to manage them

Unsafe (Development Only)

Stores secrets as plain text files:

[auth]
secrets_backend = "unsafe"

Storage location:

{data_dir}/secrets/
├── gordon/
│   └── auth/
│       ├── password_hash
│       └── token_secret

Attachment secrets:

  • Stored as gordon-<container-name>.env files in the env directory
  • Example: gordon-app__mydomain__com-postgres.env
  • Use gordon secrets set <domain> --attachment <service> KEY=value to manage them

Usage:

# Create secret
mkdir -p ~/.gordon/secrets/gordon/auth
echo "your-bcrypt-hash" > ~/.gordon/secrets/gordon/auth/password_hash

Warning: Only use for local development. Secrets are stored in plain text.

Secret Provider Syntax

In environment files, reference secrets using provider syntax:

Pass Provider

# ${pass:<path>}
DATABASE_PASSWORD=${pass:myapp/database/password}
API_KEY=${pass:myapp/api-key}

SOPS Provider

# ${sops:<file>:<key.path>}
DATABASE_PASSWORD=${sops:secrets.yaml:database.password}
API_SECRET=${sops:production.yaml:api.secret.key}

Examples

Production with Pass

[auth]
enabled = true
secrets_backend = "pass"
token_secret = "gordon/auth/token_secret"
# Setup
pass insert gordon/auth/token_secret
# Enter a random 32+ character string

# Generate tokens
gordon auth token generate --subject deploy --expiry 0

Development with Unsafe

[auth]
enabled = false
secrets_backend = "unsafe"

Enterprise with SOPS

[auth]
enabled = true
secrets_backend = "sops"
token_secret = "gordon/auth/token_secret"

Environment file:

# ~/.gordon/env/app_company_com.env
NODE_ENV=production
DATABASE_URL=postgresql://db:5432/app
DATABASE_PASSWORD=${sops:secrets.yaml:database.password}
API_KEY=${sops:secrets.yaml:api.key}
JWT_SECRET=${sops:secrets.yaml:jwt.secret}

Security Recommendations

  1. Production: Always use pass or sops backend
  2. Never commit: Don't commit unencrypted secrets to git
  3. Rotate regularly: Regenerate tokens and passwords periodically
  4. Least privilege: Use separate secrets per environment
  5. Path validation: SOPS provider rejects absolute paths and path traversal attempts for security
source
1# Secrets Configuration
2
3Configure how Gordon stores and retrieves sensitive data.
4
5## Configuration
6
7The secrets backend is configured within the `[auth]` section:
8
9```toml
10[auth]
11secrets_backend = "pass"  # "pass", "sops", or "unsafe"
12```
13
14## Options
15
16| Option | Type | Default | Description |
17|--------|------|---------|-------------|
18| `secrets_backend` | string | `"unsafe"` | Secrets storage backend |
19
20## Backends
21
22### Pass (Recommended for Production)
23
24Uses the Unix password manager (`pass`) for secure secret storage:
25
26```toml
27[auth]
28secrets_backend = "pass"
29```
30
31**Setup:**
32```bash
33# Install pass
34sudo apt install pass
35
36# Initialize with GPG key
37pass init your-gpg-key-id
38
39# Store secrets
40pass insert gordon/auth/password_hash
41pass insert gordon/auth/token_secret
42```
43
44**Usage in config:**
45```toml
46[auth]
47password_hash = "gordon/auth/password_hash"  # Path in pass store
48token_secret = "gordon/auth/token_secret"
49```
50
51**Benefits:**
52- GPG-encrypted storage
53- Version control friendly (encrypted files)
54- Standard Unix tooling
55- Works with team GPG keys
56
57**Route secrets storage:**
58- `gordon secrets set` stores per-domain secrets in pass under `gordon/env/<sanitized-domain>/<KEY>` (dots/colons/slashes → underscores)
59- Existing `.env` files are auto-migrated on startup and renamed to `.env.migrated`
60- Attachment secrets are stored under `gordon/env/attachments/<container-name>/<KEY>` with a `.keys` manifest
61- Use `gordon secrets set <domain> --attachment <service> KEY=value` to manage them
62
63### SOPS
64
65Uses Mozilla SOPS for encrypted file-based secrets:
66
67```toml
68[auth]
69secrets_backend = "sops"
70```
71
72**Setup:**
73```bash
74# Install sops
75brew install sops  # macOS
76# or download from https://github.com/getsops/sops/releases
77
78# Create encrypted secrets file
79sops secrets.yaml
80```
81
82**Usage in env files:**
83```bash
84# ~/.gordon/env/app_mydomain_com.env
85API_SECRET=${sops:secrets.yaml:api.secret}
86DB_PASSWORD=${sops:secrets.yaml:database.password}
87```
88
89**Benefits:**
90- Multiple encryption backends (AWS KMS, GCP KMS, Azure Key Vault, PGP)
91- YAML/JSON file encryption
92- Git-friendly (encrypted files in repo)
93
94**Security:**
95- Absolute paths are rejected to prevent arbitrary file access
96- Path traversal (`..`) is blocked
97- Only relative paths from your config directory are allowed
98
99**Route secrets storage:**
100- Domain secrets stay in `.env` files
101- Use `${sops:...}` syntax to resolve encrypted values
102
103**Attachment secrets storage:**
104- Attachment secrets are stored in `gordon-<container-name>.env` files alongside domain env files
105- Use `${sops:...}` syntax inside attachment env files to resolve encrypted values
106- Use `gordon secrets set <domain> --attachment <service> KEY=value` to manage them
107
108### Unsafe (Development Only)
109
110Stores secrets as plain text files:
111
112```toml
113[auth]
114secrets_backend = "unsafe"
115```
116
117**Storage location:**
118```
119{data_dir}/secrets/
120├── gordon/
121│   └── auth/
122│       ├── password_hash
123│       └── token_secret
124```
125
126**Attachment secrets:**
127- Stored as `gordon-<container-name>.env` files in the env directory
128- Example: `gordon-app__mydomain__com-postgres.env`
129- Use `gordon secrets set <domain> --attachment <service> KEY=value` to manage them
130
131**Usage:**
132```bash
133# Create secret
134mkdir -p ~/.gordon/secrets/gordon/auth
135echo "your-bcrypt-hash" > ~/.gordon/secrets/gordon/auth/password_hash
136```
137
138> **Warning:** Only use for local development. Secrets are stored in plain text.
139
140## Secret Provider Syntax
141
142In environment files, reference secrets using provider syntax:
143
144### Pass Provider
145
146```bash
147# ${pass:<path>}
148DATABASE_PASSWORD=${pass:myapp/database/password}
149API_KEY=${pass:myapp/api-key}
150```
151
152### SOPS Provider
153
154```bash
155# ${sops:<file>:<key.path>}
156DATABASE_PASSWORD=${sops:secrets.yaml:database.password}
157API_SECRET=${sops:production.yaml:api.secret.key}
158```
159
160## Examples
161
162### Production with Pass
163
164```toml
165[auth]
166enabled = true
167secrets_backend = "pass"
168token_secret = "gordon/auth/token_secret"
169```
170
171```bash
172# Setup
173pass insert gordon/auth/token_secret
174# Enter a random 32+ character string
175
176# Generate tokens
177gordon auth token generate --subject deploy --expiry 0
178```
179
180### Development with Unsafe
181
182```toml
183[auth]
184enabled = false
185secrets_backend = "unsafe"
186```
187
188### Enterprise with SOPS
189
190```toml
191[auth]
192enabled = true
193secrets_backend = "sops"
194token_secret = "gordon/auth/token_secret"
195```
196
197Environment file:
198```bash
199# ~/.gordon/env/app_company_com.env
200NODE_ENV=production
201DATABASE_URL=postgresql://db:5432/app
202DATABASE_PASSWORD=${sops:secrets.yaml:database.password}
203API_KEY=${sops:secrets.yaml:api.key}
204JWT_SECRET=${sops:secrets.yaml:jwt.secret}
205```
206
207## Security Recommendations
208
2091. **Production**: Always use `pass` or `sops` backend
2102. **Never commit**: Don't commit unencrypted secrets to git
2113. **Rotate regularly**: Regenerate tokens and passwords periodically
2124. **Least privilege**: Use separate secrets per environment
2135. **Path validation**: SOPS provider rejects absolute paths and path traversal attempts for security
214
215## Related
216
217- [Authentication](./auth.md)
218- [Environment Variables](./env.md)
219- [Configuration Overview](./index.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