v2.30.0-pre2 f03ab25

upgrading.md RawHistoryFolder

Upgrading Gordon

This guide covers breaking changes and migration steps between major versions.

v2.16.0 to v2.30.0

Breaking: Password Authentication Removed

Gordon v2.30.0 removes password-based authentication entirely. Only token-based authentication is supported.

What changed:

  • auth.type = "password" is no longer accepted
  • auth.password and auth.password_hash config fields are removed
  • The gordon auth password hash CLI command is removed
  • The gordon auth login command no longer accepts --username or --password flags
  • The /auth/password endpoint now returns 410 Gone

New features:

  • auth.access_token_ttl configures the lifetime of ephemeral access tokens issued by /auth/token (default: "15m")
  • Admin scopes (admin:*:*, admin:routes:read, etc.) allow fine-grained access control for remote CLI operations

Migration steps:

  1. Before upgrading, generate a token on your current Gordon instance:

    gordon auth token generate --subject deploy --scopes "push,pull" --expiry 0
    

    Save this token securely. You will need it after upgrading. Admin scopes (admin:*:*) are only available after upgrading to v2.30.0 — regenerate your token with admin scopes after the upgrade if needed.

  2. Update remotes to use the generated token:

    gordon auth login --token <token>
    # or
    gordon remotes set-token prod <token>
    
  3. Update your config to remove password fields:

    Before (v2.16.0):

    [auth]
    enabled = true
    secrets_backend = "pass"
    username = "deploy"
    password_hash = "gordon/auth/password_hash"
    token_secret = "gordon/auth/token_secret"
    

    After (v2.30.0):

    [auth]
    enabled = true
    secrets_backend = "pass"
    token_secret = "gordon/auth/token_secret"
    access_token_ttl = "15m"
    
  4. Update CI/CD pipelines to use GORDON_TOKEN environment variable for authentication. See the deployment guides.

  5. Upgrade the binary and restart:

    curl -fsSL https://gordon.bnema.dev/install | bash
    systemctl --user restart gordon
    
  6. Verify the server starts without errors:

    journalctl --user -u gordon -f
    

New: Configurable Access Token TTL

Ephemeral access tokens issued by /auth/token now have a configurable lifetime via auth.access_token_ttl (default "15m", maximum "1h").

Tokens with a lifetime at or below MaxAccessTokenLifetime (1 hour) are treated as ephemeral: they skip token store validation for performance, which means they cannot be individually revoked. They become invalid only when they naturally expire. Shortening auth.access_token_ttl only reduces the exposure window; it does not enable per-token revocation. If you need explicit revocation, use a stored long-lived token instead of /auth/token.

[auth]
access_token_ttl = "30m"

New: Admin Scopes

Tokens can now include fine-grained admin scopes for remote CLI operations:

# Full admin access
gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0

# Read-only monitoring
gordon auth token generate --subject monitor --scopes "admin:status:read" --expiry 30d

# CI deploy with route read + config write
gordon auth token generate --subject ci --scopes "push,pull,admin:routes:read,admin:config:write" --expiry 0

See Token Scopes for the full list.

v2.6.0 to v2.7.0

Breaking: Token Secret Required

Gordon v2.7.0 requires a token_secret for JWT authentication. The server will not start without it configured.

Error you'll see:

Error: token_secret is required for JWT token generation; set GORDON_AUTH_TOKEN_SECRET environment variable or configure auth.token_secret

Choose one of these migration options:

Option A: Environment Variable (simplest)

# Generate a random secret
export GORDON_AUTH_TOKEN_SECRET="$(openssl rand -base64 32)"

# Add to your shell profile or systemd service
echo 'export GORDON_AUTH_TOKEN_SECRET="your-secret"' >> ~/.bashrc

For systemd services:

mkdir -p ~/.config/systemd/user/gordon.service.d
cat > ~/.config/systemd/user/gordon.service.d/token.conf << EOF
[Service]
Environment="GORDON_AUTH_TOKEN_SECRET=$(openssl rand -base64 32)"
EOF
systemctl --user daemon-reload
systemctl --user restart gordon
# Generate and store secret in pass
openssl rand -base64 32 | pass insert -e gordon/auth/token_secret

# Update your gordon.toml
[auth]
enabled = true
secrets_backend = "pass"
token_secret = "gordon/auth/token_secret"

Option C: Config File with Unsafe Backend (development only)

# Generate secret file
mkdir -p ~/.gordon/secrets
openssl rand -base64 32 > ~/.gordon/secrets/token_secret
chmod 600 ~/.gordon/secrets/token_secret
[auth]
enabled = true
secrets_backend = "unsafe"
token_secret = "token_secret"

Breaking: Unsafe Token Store Warning

Using secrets_backend = "unsafe" now logs a warning on startup:

WRN using unsafe secrets backend - secrets are stored in plain text

This is intentional to encourage secure secret storage in production. The warning can be ignored for development.

New Features

  • Attachment secrets discovery: gordon secrets list <domain> now shows secrets for attachment containers
  • Auth login command: gordon auth login --remote <name> for password authentication
  • Rate limiting: Configurable rate limits under [api.rate_limit]

Security Improvements

v2.7.0 includes a comprehensive security audit with:

  • JWT tokens now include "not before" (nbf) claim
  • SSRF protection for external routes
  • Security headers middleware
  • Rate limiting on registry and token endpoints
  • Command injection prevention in pass provider
  • Path traversal prevention in secrets store

v2.5.0 to v2.6.0

Breaking: Config Restructure

The [secrets] and [registry_auth] sections were merged into [auth].

Before (v2.5.0):

[secrets]
backend = "pass"

[registry_auth]
enabled = true
type = "password"
password_hash = "gordon/registry/password_hash"

After (v2.6.0+):

[auth]
enabled = true
secrets_backend = "pass"
password_hash = "gordon/auth/password_hash"

Breaking: Auth Enabled by Default

Gordon keeps auth enabled by default. If you set auth.enabled = false, Gordon runs in local-only mode (/admin/* disabled, /v2/* loopback-only).

Breaking: Secret Paths Changed

If using pass or sops, update your secret paths:

  • gordon/registry/* → gordon/auth/*

General Upgrade Process

  1. Read the changelog for your target version
  2. Backup your config before upgrading
  3. Test in staging if possible
  4. Upgrade the binary:
    curl -fsSL https://gordon.bnema.dev/install | bash
    
  5. Restart Gordon:
    systemctl --user restart gordon
    
  6. Check logs for any errors:
    gordon logs
    

Getting Help

source
1# Upgrading Gordon
2
3This guide covers breaking changes and migration steps between major versions.
4
5## v2.16.0 to v2.30.0
6
7### Breaking: Password Authentication Removed
8
9Gordon v2.30.0 removes password-based authentication entirely. Only token-based authentication is supported.
10
11**What changed:**
12
13- `auth.type = "password"` is no longer accepted
14- `auth.password` and `auth.password_hash` config fields are removed
15- The `gordon auth password hash` CLI command is removed
16- The `gordon auth login` command no longer accepts `--username` or `--password` flags
17- The `/auth/password` endpoint now returns `410 Gone`
18
19**New features:**
20
21- `auth.access_token_ttl` configures the lifetime of ephemeral access tokens issued by `/auth/token` (default: `"15m"`)
22- Admin scopes (`admin:*:*`, `admin:routes:read`, etc.) allow fine-grained access control for remote CLI operations
23
24**Migration steps:**
25
261. **Before upgrading**, generate a token on your current Gordon instance:
27
28   ```bash
29   gordon auth token generate --subject deploy --scopes "push,pull" --expiry 0
30   ```
31
32   Save this token securely. You will need it after upgrading. Admin scopes (`admin:*:*`) are only available after upgrading to v2.30.0 — regenerate your token with admin scopes after the upgrade if needed.
33
342. **Update remotes** to use the generated token:
35
36   ```bash
37   gordon auth login --token <token>
38   # or
39   gordon remotes set-token prod <token>
40   ```
41
423. **Update your config** to remove password fields:
43
44   **Before (v2.16.0):**
45
46   ```toml
47   [auth]
48   enabled = true
49   secrets_backend = "pass"
50   username = "deploy"
51   password_hash = "gordon/auth/password_hash"
52   token_secret = "gordon/auth/token_secret"
53   ```
54
55   **After (v2.30.0):**
56
57   ```toml
58   [auth]
59   enabled = true
60   secrets_backend = "pass"
61   token_secret = "gordon/auth/token_secret"
62   access_token_ttl = "15m"
63   ```
64
654. **Update CI/CD pipelines** to use `GORDON_TOKEN` environment variable for authentication. See the [deployment guides](./deployment/index.md).
66
675. **Upgrade the binary** and restart:
68
69   ```bash
70   curl -fsSL https://gordon.bnema.dev/install | bash
71   systemctl --user restart gordon
72   ```
73
746. **Verify** the server starts without errors:
75
76   ```bash
77   journalctl --user -u gordon -f
78   ```
79
80### New: Configurable Access Token TTL
81
82Ephemeral access tokens issued by `/auth/token` now have a configurable lifetime via `auth.access_token_ttl` (default `"15m"`, maximum `"1h"`).
83
84Tokens with a lifetime at or below `MaxAccessTokenLifetime` (1 hour) are treated as ephemeral: they skip token store validation for performance, which means they **cannot be individually revoked**. They become invalid only when they naturally expire. Shortening `auth.access_token_ttl` only reduces the exposure window; it does not enable per-token revocation. If you need explicit revocation, use a stored long-lived token instead of `/auth/token`.
85
86```toml
87[auth]
88access_token_ttl = "30m"
89```
90
91### New: Admin Scopes
92
93Tokens can now include fine-grained admin scopes for remote CLI operations:
94
95```bash
96# Full admin access
97gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0
98
99# Read-only monitoring
100gordon auth token generate --subject monitor --scopes "admin:status:read" --expiry 30d
101
102# CI deploy with route read + config write
103gordon auth token generate --subject ci --scopes "push,pull,admin:routes:read,admin:config:write" --expiry 0
104```
105
106See [Token Scopes](./config/auth.md#token-scopes) for the full list.
107
108## v2.6.0 to v2.7.0
109
110### Breaking: Token Secret Required
111
112Gordon v2.7.0 requires a `token_secret` for JWT authentication. The server will not start without it configured.
113
114**Error you'll see:**
115```
116Error: token_secret is required for JWT token generation; set GORDON_AUTH_TOKEN_SECRET environment variable or configure auth.token_secret
117```
118
119**Choose one of these migration options:**
120
121#### Option A: Environment Variable (simplest)
122
123```bash
124# Generate a random secret
125export GORDON_AUTH_TOKEN_SECRET="$(openssl rand -base64 32)"
126
127# Add to your shell profile or systemd service
128echo 'export GORDON_AUTH_TOKEN_SECRET="your-secret"' >> ~/.bashrc
129```
130
131For systemd services:
132```bash
133mkdir -p ~/.config/systemd/user/gordon.service.d
134cat > ~/.config/systemd/user/gordon.service.d/token.conf << EOF
135[Service]
136Environment="GORDON_AUTH_TOKEN_SECRET=$(openssl rand -base64 32)"
137EOF
138systemctl --user daemon-reload
139systemctl --user restart gordon
140```
141
142#### Option B: Config File with Pass (recommended for production)
143
144```bash
145# Generate and store secret in pass
146openssl rand -base64 32 | pass insert -e gordon/auth/token_secret
147
148# Update your gordon.toml
149```
150
151```toml
152[auth]
153enabled = true
154secrets_backend = "pass"
155token_secret = "gordon/auth/token_secret"
156```
157
158#### Option C: Config File with Unsafe Backend (development only)
159
160```bash
161# Generate secret file
162mkdir -p ~/.gordon/secrets
163openssl rand -base64 32 > ~/.gordon/secrets/token_secret
164chmod 600 ~/.gordon/secrets/token_secret
165```
166
167```toml
168[auth]
169enabled = true
170secrets_backend = "unsafe"
171token_secret = "token_secret"
172```
173
174### Breaking: Unsafe Token Store Warning
175
176Using `secrets_backend = "unsafe"` now logs a warning on startup:
177```
178WRN using unsafe secrets backend - secrets are stored in plain text
179```
180
181This is intentional to encourage secure secret storage in production. The warning can be ignored for development.
182
183### New Features
184
185- **Attachment secrets discovery**: `gordon secrets list <domain>` now shows secrets for attachment containers
186- **Auth login command**: `gordon auth login --remote <name>` for password authentication
187- **Rate limiting**: Configurable rate limits under `[api.rate_limit]`
188
189### Security Improvements
190
191v2.7.0 includes a comprehensive security audit with:
192
193- JWT tokens now include "not before" (nbf) claim
194- SSRF protection for external routes
195- Security headers middleware
196- Rate limiting on registry and token endpoints
197- Command injection prevention in pass provider
198- Path traversal prevention in secrets store
199
200## v2.5.0 to v2.6.0
201
202### Breaking: Config Restructure
203
204The `[secrets]` and `[registry_auth]` sections were merged into `[auth]`.
205
206**Before (v2.5.0):**
207```toml
208[secrets]
209backend = "pass"
210
211[registry_auth]
212enabled = true
213type = "password"
214password_hash = "gordon/registry/password_hash"
215```
216
217**After (v2.6.0+):**
218```toml
219[auth]
220enabled = true
221secrets_backend = "pass"
222password_hash = "gordon/auth/password_hash"
223```
224
225### Breaking: Auth Enabled by Default
226
227Gordon keeps auth enabled by default. If you set `auth.enabled = false`, Gordon runs in local-only mode (`/admin/*` disabled, `/v2/*` loopback-only).
228
229### Breaking: Secret Paths Changed
230
231If using pass or sops, update your secret paths:
232- `gordon/registry/*` → `gordon/auth/*`
233
234## General Upgrade Process
235
2361. **Read the changelog** for your target version
2372. **Backup your config** before upgrading
2383. **Test in staging** if possible
2394. **Upgrade the binary**:
240   ```bash
241   curl -fsSL https://gordon.bnema.dev/install | bash
242   ```
2435. **Restart Gordon**:
244   ```bash
245   systemctl --user restart gordon
246   ```
2476. **Check logs** for any errors:
248   ```bash
249   gordon logs
250   ```
251
252## Getting Help
253
254- [GitHub Issues](https://github.com/bnema/gordon/issues)
255- [Documentation](https://gordon.bnema.dev/docs)

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