detached 18f31a9

docs(auth): simplify authentication setup

commit
18f31a95de86150ec8a07791afdc1b56f288a2df
author
bnema · · 2026-01-30 20:58 UTC
parent
5498bc4
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +92 -222
M docs/config/auth.md +42 -189
@@ -2,47 +2,33 @@
22
33 Configure authentication for the Gordon registry and Admin API.
44
5-## Quick Start
5+Authentication is enabled by default. Gordon will not start without a valid `token_secret` (or `GORDON_AUTH_TOKEN_SECRET`).
66
7-Authentication is **enabled by default** for security. Gordon will not start without authentication configured.
7+## Pick a Mode
88
9-**Option 1: Password Authentication (simplest)**
10-```bash
11-# 1. Generate password hash
12-gordon auth password hash
13-# Enter your password, copy the bcrypt hash
9+### Token-only (recommended for CI/CD)
1410
15-# 2. Save hash to secrets file
16-mkdir -p ~/.gordon/secrets
17-echo '$2a$10$...' > ~/.gordon/secrets/password_hash
18-
19-# 3. Add to config.toml
20-cat >> ~/.gordon/config.toml << 'EOF'
21-[auth]
22-password_hash = "password_hash"
23-EOF
24-```
25-
26-**Option 2: Disable Authentication (development only)**
2711 ```toml
2812 [auth]
29-enabled = false
13+enabled = true
14+secrets_backend = "pass"
15+token_secret = "gordon/auth/token_secret"
16+token_expiry = "30d"
3017 ```
3118
32-## Configuration
19+### Password + Token (interactive + CI/CD)
3320
3421 ```toml
3522 [auth]
3623 enabled = true
3724 secrets_backend = "pass"
38-token_secret = "gordon/auth/token_secret"
39-token_expiry = "30d"
40-
41-# Optional: enable password authentication
4225 username = "deploy"
4326 password_hash = "gordon/auth/password_hash"
27+token_secret = "gordon/auth/token_secret"
4428 ```
4529
30+Token auth always works. Adding `username` + `password_hash` enables interactive login.
31+
4632 ## Options
4733
4834 | Option | Type | Default | Description |
@@ -54,35 +40,9 @@ password_hash = "gordon/auth/password_hash"
5440 | `username` | string | - | Username for password auth (optional) |
5541 | `password_hash` | string | - | Path to bcrypt hash in secrets backend (optional) |
5642
57-## Authentication Modes
58-
59-Gordon infers the authentication mode from your configuration:
60-
61-| Config | Mode | Description |
62-|--------|------|-------------|
63-| Only `token_secret` | Token-only | JWT tokens for all access |
64-| `token_secret` + `username` + `password_hash` | Password + Token | Password for interactive login, tokens for CI/CD |
65-
66-Tokens always work regardless of mode. The difference is whether password authentication is available.
67-
68-## Environment Variables
69-
70-Gordon supports environment variables for sensitive configuration:
71-
72-| Variable | Description |
73-|----------|-------------|
74-| `GORDON_AUTH_TOKEN_SECRET` | JWT signing secret (takes priority over config file) |
75-
76-Using environment variables is recommended for production as it avoids storing secrets on disk:
77-
78-```bash
79-export GORDON_AUTH_TOKEN_SECRET="your-32-character-secret-here"
80-gordon serve
81-```
82-
83-## Secrets Backend
43+## Secrets Backends
8444
85-The `secrets_backend` option determines how Gordon retrieves sensitive values like `token_secret` and `password_hash`:
45+`token_secret` and `password_hash` are read through the configured backend:
8646
8747 | Backend | Description |
8848 |---------|-------------|
@@ -90,23 +50,21 @@ The `secrets_backend` option determines how Gordon retrieves sensitive values li
9050 | `sops` | Mozilla SOPS encrypted files |
9151 | `unsafe` | Plain text files (development only) |
9252
93-See [Secret Providers](./secrets.md) for detailed configuration of each backend.
94-
95-## Authentication Types
53+See [Secret Providers](./secrets.md) for setup details.
9654
97-### Token-Only Mode
55+## Environment Variable
9856
99-JWT-based authentication, ideal for CI/CD pipelines when you don't need interactive login:
57+`GORDON_AUTH_TOKEN_SECRET` overrides `token_secret` in the config.
10058
101-```toml
102-[auth]
103-enabled = true
104-secrets_backend = "pass"
105-token_secret = "gordon/auth/token_secret"
106-token_expiry = "30d"
59+```bash
60+export GORDON_AUTH_TOKEN_SECRET="your-32-character-secret-here"
61+gordon serve
10762 ```
10863
109-**Setup:**
64+## Setup
65+
66+### Token-only setup
67+
11068 ```bash
11169 # Create token secret (random 32+ characters)
11270 pass insert gordon/auth/token_secret
@@ -115,83 +73,43 @@ pass insert gordon/auth/token_secret
11573 gordon auth token generate --subject ci-bot --scopes push,pull --expiry 0
11674 ```
11775
118-**Usage:**
11976 ```bash
12077 # Docker login with token
12178 docker login -u ci-bot -p <token> registry.mydomain.com
12279 ```
12380
124-**Token Management:**
125-```bash
126-# List all tokens
127-gordon auth token list
128-
129-# Revoke a specific token
130-gordon auth token revoke <token-id>
131-
132-# Revoke all tokens
133-gordon auth token revoke --all
134-```
135-
136-### Password + Token Mode
81+### Password + token setup
13782
138-Password authentication for interactive login, plus tokens for CI/CD:
139-
140-```toml
141-[auth]
142-enabled = true
143-secrets_backend = "pass"
144-username = "deploy"
145-password_hash = "gordon/auth/password_hash"
146-token_secret = "gordon/auth/token_secret"
147-```
148-
149-When `username` and `password_hash` are configured, both password and token authentication work.
150-
151-**Setup:**
15283 ```bash
15384 # Generate bcrypt hash
15485 gordon auth password hash
155-# Enter password when prompted
15686
157-# Store hash in secrets backend
87+# Store hash and token secret
15888 pass insert gordon/auth/password_hash
159-# Paste the bcrypt hash
160-
161-# Create token secret (for CI/CD token generation)
16289 pass insert gordon/auth/token_secret
163-# Enter a random 32+ character string
16490 ```
16591
166-**Usage:**
16792 ```bash
16893 # Docker registry access
16994 docker login -u deploy -p <password> registry.mydomain.com
17095
171-# Remote CLI authentication
96+# Remote CLI login (stores a token for you)
17297 gordon auth login --remote prod
173-# Enter username and password when prompted
17498 ```
17599
176-**Remote CLI Authentication:**
100+## Remote CLI Tokens
177101
178-With password authentication enabled, you can use `gordon auth login` to obtain a token for remote CLI operations:
102+If you already have a token (token-only servers), store it directly:
179103
180104 ```bash
181-gordon auth login --remote prod
182-# Username: deploy
183-# Password: ********
184-# ✓ Authentication successful!
185-# Token stored for remote 'prod'
105+gordon auth login --token <token>
106+# or
107+gordon remotes set-token prod <token>
186108 ```
187109
188-The returned token is stored automatically and used for subsequent CLI commands.
189-
190110 ## Token Scopes
191111
192-Tokens can have different permission levels:
193-
194-### Registry Scopes
112+Registry scopes:
195113
196114 | Scope | Permission |
197115 |-------|------------|
@@ -199,9 +117,7 @@ Tokens can have different permission levels:
199117 | `pull` | Pull images from registry |
200118 | `push,pull` | Both push and pull (default) |
201119
202-### Admin Scopes
203-
204-For remote CLI access via the Admin API:
120+Admin scopes (for remote CLI):
205121
206122 | Scope | Permission |
207123 |-------|------------|
@@ -214,108 +130,45 @@ For remote CLI access via the Admin API:
214130 | `admin:secrets:read` | List secret keys |
215131 | `admin:secrets:write` | Set/delete secrets |
216132
217-**Examples:**
133+Examples:
134+
218135 ```bash
219-# Pull-only token (for read-only access)
220136 gordon auth token generate --subject reader --scopes pull --expiry 30d
221-
222-# Push-only token (for CI builds)
223137 gordon auth token generate --subject builder --scopes push --expiry 0
224-
225-# Full admin access (for remote CLI)
226138 gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0
227139 ```
228140
229141 ## Token Expiry
230142
231-Control how long tokens remain valid. Supports human-friendly units:
232-
233-| Unit | Description |
234-|------|-------------|
235-| `d` | days (24 hours) |
236-| `w` | weeks (7 days) |
237-| `M` | months (30 days) |
238-| `y` | years (365 days) |
239-
240-Compound durations work too: `1y6M`, `2w3d`
143+Durations support `d`, `w`, `M`, `y` and combinations like `1y6M` or `2w3d`.
241144
242145 ```bash
243-# Never expires (for CI/CD)
244146 gordon auth token generate --subject ci --expiry 0
245-
246-# Expires in 1 year
247147 gordon auth token generate --subject deploy --expiry 1y
248-
249-# Expires in 30 days
250148 gordon auth token generate --subject temp --expiry 30d
251149 ```
252150
253-## Instance-Specific Tokens
254-
255-Tokens are signed with the `token_secret`, which is unique to each Gordon instance:
151+## Instance-specific Tokens
256152
153+- Tokens are signed with `token_secret`
257154 - Tokens from one Gordon instance won't work on another
258-- Changing the `token_secret` invalidates all existing tokens
259-- Each environment (dev, staging, prod) should have different secrets
260-
261-## Development Setup
155+- Changing `token_secret` invalidates all existing tokens
262156
263-For local development without authentication:
157+## Disable Auth (development only)
264158
265159 ```toml
266160 [auth]
267161 enabled = false
268162 ```
269163
270-## Examples
271-
272-### CI/CD Setup (Token-Only)
273-
274-```toml
275-[auth]
276-enabled = true
277-secrets_backend = "pass"
278-token_secret = "gordon/auth/token_secret"
279-```
280-
281-```bash
282-# Generate CI token
283-gordon auth token generate --subject github-actions --scopes push,pull --expiry 0
284-```
285-
286-In GitHub Actions:
287-```yaml
288-- name: Login to Gordon Registry
289- run: docker login -u github-actions -p ${{ secrets.GORDON_TOKEN }} ${{ secrets.GORDON_REGISTRY }}
290-```
291-
292-### Production with Password + Token
293-
294-```toml
295-[auth]
296-enabled = true
297-secrets_backend = "pass"
298-username = "deploy"
299-password_hash = "gordon/auth/password_hash"
300-token_secret = "gordon/auth/token_secret"
301-```
302-
303-### Enterprise with SOPS
304-
305-```toml
306-[auth]
307-enabled = true
308-secrets_backend = "sops"
309-token_secret = "gordon/auth/token_secret"
310-```
311-
312164 ## Internal Registry Auth
313165
314-Gordon generates internal credentials automatically when auth is enabled. These are used for loopback pulls when deploying containers and are regenerated on each restart.
166+Gordon generates internal credentials when auth is enabled. These are used for loopback pulls during deploys and are regenerated on each restart.
315167
316168 Gordon also generates a separate service token for its own registry-domain pulls. This token is managed internally and is not exposed via configuration or CLI.
317169
318170 To view internal credentials (for troubleshooting):
171+
319172 ```bash
320173 gordon auth internal
321174 ```
@@ -2,47 +2,33 @@
2 2
3 Configure authentication for the Gordon registry and Admin API.3 Configure authentication for the Gordon registry and Admin API.
4 4
5-## Quick Start5+Authentication is enabled by default. Gordon will not start without a valid `token_secret` (or `GORDON_AUTH_TOKEN_SECRET`).
6 6
7-Authentication is **enabled by default** for security. Gordon will not start without authentication configured.7+## Pick a Mode
8 8
9-**Option 1: Password Authentication (simplest)**9+### Token-only (recommended for CI/CD)
10-```bash
11-# 1. Generate password hash
12-gordon auth password hash
13-# Enter your password, copy the bcrypt hash
14 10
15-# 2. Save hash to secrets file
16-mkdir -p ~/.gordon/secrets
17-echo '$2a$10$...' > ~/.gordon/secrets/password_hash
18-
19-# 3. Add to config.toml
20-cat >> ~/.gordon/config.toml << 'EOF'
21-[auth]
22-password_hash = "password_hash"
23-EOF
24-```
25-
26-**Option 2: Disable Authentication (development only)**
27 ```toml11 ```toml
28 [auth]12 [auth]
29-enabled = false13+enabled = true
14+secrets_backend = "pass"
15+token_secret = "gordon/auth/token_secret"
16+token_expiry = "30d"
30 ```17 ```
31 18
32-## Configuration19+### Password + Token (interactive + CI/CD)
33 20
34 ```toml21 ```toml
35 [auth]22 [auth]
36 enabled = true23 enabled = true
37 secrets_backend = "pass"24 secrets_backend = "pass"
38-token_secret = "gordon/auth/token_secret"
39-token_expiry = "30d"
40-
41-# Optional: enable password authentication
42 username = "deploy"25 username = "deploy"
43 password_hash = "gordon/auth/password_hash"26 password_hash = "gordon/auth/password_hash"
27+token_secret = "gordon/auth/token_secret"
44 ```28 ```
45 29
30+Token auth always works. Adding `username` + `password_hash` enables interactive login.
31+
46 ## Options32 ## Options
47 33
48 | Option | Type | Default | Description |34 | Option | Type | Default | Description |
@@ -54,35 +40,9 @@ password_hash = "gordon/auth/password_hash"
54 | `username` | string | - | Username for password auth (optional) |40 | `username` | string | - | Username for password auth (optional) |
55 | `password_hash` | string | - | Path to bcrypt hash in secrets backend (optional) |41 | `password_hash` | string | - | Path to bcrypt hash in secrets backend (optional) |
56 42
57-## Authentication Modes43+## Secrets Backends
58-
59-Gordon infers the authentication mode from your configuration:
60-
61-| Config | Mode | Description |
62-|--------|------|-------------|
63-| Only `token_secret` | Token-only | JWT tokens for all access |
64-| `token_secret` + `username` + `password_hash` | Password + Token | Password for interactive login, tokens for CI/CD |
65-
66-Tokens always work regardless of mode. The difference is whether password authentication is available.
67-
68-## Environment Variables
69-
70-Gordon supports environment variables for sensitive configuration:
71-
72-| Variable | Description |
73-|----------|-------------|
74-| `GORDON_AUTH_TOKEN_SECRET` | JWT signing secret (takes priority over config file) |
75-
76-Using environment variables is recommended for production as it avoids storing secrets on disk:
77-
78-```bash
79-export GORDON_AUTH_TOKEN_SECRET="your-32-character-secret-here"
80-gordon serve
81-```
82-
83-## Secrets Backend
84 44
85-The `secrets_backend` option determines how Gordon retrieves sensitive values like `token_secret` and `password_hash`:45+`token_secret` and `password_hash` are read through the configured backend:
86 46
87 | Backend | Description |47 | Backend | Description |
88 |---------|-------------|48 |---------|-------------|
@@ -90,23 +50,21 @@ The `secrets_backend` option determines how Gordon retrieves sensitive values li
90 | `sops` | Mozilla SOPS encrypted files |50 | `sops` | Mozilla SOPS encrypted files |
91 | `unsafe` | Plain text files (development only) |51 | `unsafe` | Plain text files (development only) |
92 52
93-See [Secret Providers](./secrets.md) for detailed configuration of each backend.53+See [Secret Providers](./secrets.md) for setup details.
94-
95-## Authentication Types
96 54
97-### Token-Only Mode55+## Environment Variable
98 56
99-JWT-based authentication, ideal for CI/CD pipelines when you don't need interactive login:57+`GORDON_AUTH_TOKEN_SECRET` overrides `token_secret` in the config.
100 58
101-```toml59+```bash
102-[auth]60+export GORDON_AUTH_TOKEN_SECRET="your-32-character-secret-here"
103-enabled = true61+gordon serve
104-secrets_backend = "pass"
105-token_secret = "gordon/auth/token_secret"
106-token_expiry = "30d"
107 ```62 ```
108 63
109-**Setup:**64+## Setup
65+
66+### Token-only setup
67+
110 ```bash68 ```bash
111 # Create token secret (random 32+ characters)69 # Create token secret (random 32+ characters)
112 pass insert gordon/auth/token_secret70 pass insert gordon/auth/token_secret
@@ -115,83 +73,43 @@ pass insert gordon/auth/token_secret
115 gordon auth token generate --subject ci-bot --scopes push,pull --expiry 073 gordon auth token generate --subject ci-bot --scopes push,pull --expiry 0
116 ```74 ```
117 75
118-**Usage:**
119 ```bash76 ```bash
120 # Docker login with token77 # Docker login with token
121 docker login -u ci-bot -p <token> registry.mydomain.com78 docker login -u ci-bot -p <token> registry.mydomain.com
122 ```79 ```
123 80
124-**Token Management:**81+### Password + token setup
125-```bash
126-# List all tokens
127-gordon auth token list
128-
129-# Revoke a specific token
130-gordon auth token revoke <token-id>
131-
132-# Revoke all tokens
133-gordon auth token revoke --all
134-```
135-
136-### Password + Token Mode
137 82
138-Password authentication for interactive login, plus tokens for CI/CD:
139-
140-```toml
141-[auth]
142-enabled = true
143-secrets_backend = "pass"
144-username = "deploy"
145-password_hash = "gordon/auth/password_hash"
146-token_secret = "gordon/auth/token_secret"
147-```
148-
149-When `username` and `password_hash` are configured, both password and token authentication work.
150-
151-**Setup:**
152 ```bash83 ```bash
153 # Generate bcrypt hash84 # Generate bcrypt hash
154 gordon auth password hash85 gordon auth password hash
155-# Enter password when prompted
156 86
157-# Store hash in secrets backend87+# Store hash and token secret
158 pass insert gordon/auth/password_hash88 pass insert gordon/auth/password_hash
159-# Paste the bcrypt hash
160-
161-# Create token secret (for CI/CD token generation)
162 pass insert gordon/auth/token_secret89 pass insert gordon/auth/token_secret
163-# Enter a random 32+ character string
164 ```90 ```
165 91
166-**Usage:**
167 ```bash92 ```bash
168 # Docker registry access93 # Docker registry access
169 docker login -u deploy -p <password> registry.mydomain.com94 docker login -u deploy -p <password> registry.mydomain.com
170 95
171-# Remote CLI authentication96+# Remote CLI login (stores a token for you)
172 gordon auth login --remote prod97 gordon auth login --remote prod
173-# Enter username and password when prompted
174 ```98 ```
175 99
176-**Remote CLI Authentication:**100+## Remote CLI Tokens
177 101
178-With password authentication enabled, you can use `gordon auth login` to obtain a token for remote CLI operations:102+If you already have a token (token-only servers), store it directly:
179 103
180 ```bash104 ```bash
181-gordon auth login --remote prod105+gordon auth login --token <token>
182-# Username: deploy106+# or
183-# Password: ********107+gordon remotes set-token prod <token>
184-# ✓ Authentication successful!
185-# Token stored for remote 'prod'
186 ```108 ```
187 109
188-The returned token is stored automatically and used for subsequent CLI commands.
189-
190 ## Token Scopes110 ## Token Scopes
191 111
192-Tokens can have different permission levels:112+Registry scopes:
193-
194-### Registry Scopes
195 113
196 | Scope | Permission |114 | Scope | Permission |
197 |-------|------------|115 |-------|------------|
@@ -199,9 +117,7 @@ Tokens can have different permission levels:
199 | `pull` | Pull images from registry |117 | `pull` | Pull images from registry |
200 | `push,pull` | Both push and pull (default) |118 | `push,pull` | Both push and pull (default) |
201 119
202-### Admin Scopes120+Admin scopes (for remote CLI):
203-
204-For remote CLI access via the Admin API:
205 121
206 | Scope | Permission |122 | Scope | Permission |
207 |-------|------------|123 |-------|------------|
@@ -214,108 +130,45 @@ For remote CLI access via the Admin API:
214 | `admin:secrets:read` | List secret keys |130 | `admin:secrets:read` | List secret keys |
215 | `admin:secrets:write` | Set/delete secrets |131 | `admin:secrets:write` | Set/delete secrets |
216 132
217-**Examples:**133+Examples:
134+
218 ```bash135 ```bash
219-# Pull-only token (for read-only access)
220 gordon auth token generate --subject reader --scopes pull --expiry 30d136 gordon auth token generate --subject reader --scopes pull --expiry 30d
221-
222-# Push-only token (for CI builds)
223 gordon auth token generate --subject builder --scopes push --expiry 0137 gordon auth token generate --subject builder --scopes push --expiry 0
224-
225-# Full admin access (for remote CLI)
226 gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0138 gordon auth token generate --subject admin --scopes "push,pull,admin:*:*" --expiry 0
227 ```139 ```
228 140
229 ## Token Expiry141 ## Token Expiry
230 142
231-Control how long tokens remain valid. Supports human-friendly units:143+Durations support `d`, `w`, `M`, `y` and combinations like `1y6M` or `2w3d`.
232-
233-| Unit | Description |
234-|------|-------------|
235-| `d` | days (24 hours) |
236-| `w` | weeks (7 days) |
237-| `M` | months (30 days) |
238-| `y` | years (365 days) |
239-
240-Compound durations work too: `1y6M`, `2w3d`
241 144
242 ```bash145 ```bash
243-# Never expires (for CI/CD)
244 gordon auth token generate --subject ci --expiry 0146 gordon auth token generate --subject ci --expiry 0
245-
246-# Expires in 1 year
247 gordon auth token generate --subject deploy --expiry 1y147 gordon auth token generate --subject deploy --expiry 1y
248-
249-# Expires in 30 days
250 gordon auth token generate --subject temp --expiry 30d148 gordon auth token generate --subject temp --expiry 30d
251 ```149 ```
252 150
253-## Instance-Specific Tokens151+## Instance-specific Tokens
254-
255-Tokens are signed with the `token_secret`, which is unique to each Gordon instance:
256 152
153+- Tokens are signed with `token_secret`
257 - Tokens from one Gordon instance won't work on another154 - Tokens from one Gordon instance won't work on another
258-- Changing the `token_secret` invalidates all existing tokens155+- Changing `token_secret` invalidates all existing tokens
259-- Each environment (dev, staging, prod) should have different secrets
260-
261-## Development Setup
262 156
263-For local development without authentication:157+## Disable Auth (development only)
264 158
265 ```toml159 ```toml
266 [auth]160 [auth]
267 enabled = false161 enabled = false
268 ```162 ```
269 163
270-## Examples
271-
272-### CI/CD Setup (Token-Only)
273-
274-```toml
275-[auth]
276-enabled = true
277-secrets_backend = "pass"
278-token_secret = "gordon/auth/token_secret"
279-```
280-
281-```bash
282-# Generate CI token
283-gordon auth token generate --subject github-actions --scopes push,pull --expiry 0
284-```
285-
286-In GitHub Actions:
287-```yaml
288-- name: Login to Gordon Registry
289- run: docker login -u github-actions -p ${{ secrets.GORDON_TOKEN }} ${{ secrets.GORDON_REGISTRY }}
290-```
291-
292-### Production with Password + Token
293-
294-```toml
295-[auth]
296-enabled = true
297-secrets_backend = "pass"
298-username = "deploy"
299-password_hash = "gordon/auth/password_hash"
300-token_secret = "gordon/auth/token_secret"
301-```
302-
303-### Enterprise with SOPS
304-
305-```toml
306-[auth]
307-enabled = true
308-secrets_backend = "sops"
309-token_secret = "gordon/auth/token_secret"
310-```
311-
312 ## Internal Registry Auth164 ## Internal Registry Auth
313 165
314-Gordon generates internal credentials automatically when auth is enabled. These are used for loopback pulls when deploying containers and are regenerated on each restart.166+Gordon generates internal credentials when auth is enabled. These are used for loopback pulls during deploys and are regenerated on each restart.
315 167
316 Gordon also generates a separate service token for its own registry-domain pulls. This token is managed internally and is not exposed via configuration or CLI.168 Gordon also generates a separate service token for its own registry-domain pulls. This token is managed internally and is not exposed via configuration or CLI.
317 169
318 To view internal credentials (for troubleshooting):170 To view internal credentials (for troubleshooting):
171+
319 ```bash172 ```bash
320 gordon auth internal173 gordon auth internal
321 ```174 ```
M internal/app/run.go +50 -33
@@ -266,19 +266,8 @@ func createServices(ctx context.Context, v *viper.Viper, cfg Config, log zerowra
266266 return nil, err
267267 }
268268
269- // Generate internal registry credentials for loopback-only pulls
270- if cfg.Auth.Enabled {
271- svc.internalRegUser, svc.internalRegPass, err = generateInternalRegistryAuth()
272- if err != nil {
273- return nil, log.WrapErr(err, "failed to generate internal registry credentials")
274- }
275-
276- // Persist credentials to file for CLI access (gordon auth internal)
277- if err := persistInternalCredentials(svc.internalRegUser, svc.internalRegPass); err != nil {
278- log.Warn().Err(err).Msg("failed to persist internal credentials for CLI access")
279- }
280-
281- log.Debug().Msg("internal registry auth generated for loopback pulls")
269+ if err := setupInternalRegistryAuth(cfg, svc, log); err != nil {
270+ return nil, err
282271 }
283272
284273 // Create use case services
@@ -287,28 +276,13 @@ func createServices(ctx context.Context, v *viper.Viper, cfg Config, log zerowra
287276 return nil, log.WrapErr(err, "failed to load configuration")
288277 }
289278
290- // Determine env directory for admin API
291- svc.envDir = resolveEnvDir(cfg)
292-
293- backend := resolveSecretsBackend(cfg.Auth.SecretsBackend)
294- var domainSecretStore out.DomainSecretStore
279+ var backend domain.SecretsBackend
295280 var passStore *domainsecrets.PassStore
281+ var domainSecretStore out.DomainSecretStore
296282
297- switch backend {
298- case domain.SecretsBackendPass:
299- passStore, err = domainsecrets.NewPassStore(log)
300- if err != nil {
301- return nil, log.WrapErr(err, "failed to create pass domain secret store")
302- }
303- if err := migrateEnvFilesToPass(svc.envDir, passStore, log); err != nil {
304- return nil, log.WrapErr(err, "failed to migrate env files to pass")
305- }
306- domainSecretStore = passStore
307- default:
308- domainSecretStore, err = domainsecrets.NewFileStore(svc.envDir, log)
309- if err != nil {
310- return nil, log.WrapErr(err, "failed to create domain secret store")
311- }
283+ svc.envDir, backend, passStore, domainSecretStore, err = createDomainSecretStore(cfg, log)
284+ if err != nil {
285+ return nil, err
312286 }
313287
314288 if svc.envLoader, err = createEnvLoader(backend, svc.envDir, passStore, log); err != nil {
@@ -348,6 +322,49 @@ func createServices(ctx context.Context, v *viper.Viper, cfg Config, log zerowra
348322 return svc, nil
349323 }
350324
325+func setupInternalRegistryAuth(cfg Config, svc *services, log zerowrap.Logger) error {
326+ if !cfg.Auth.Enabled {
327+ return nil
328+ }
329+
330+ var err error
331+ svc.internalRegUser, svc.internalRegPass, err = generateInternalRegistryAuth()
332+ if err != nil {
333+ return log.WrapErr(err, "failed to generate internal registry credentials")
334+ }
335+
336+ // Persist credentials to file for CLI access (gordon auth internal)
337+ if err := persistInternalCredentials(svc.internalRegUser, svc.internalRegPass); err != nil {
338+ log.Warn().Err(err).Msg("failed to persist internal credentials for CLI access")
339+ }
340+
341+ log.Debug().Msg("internal registry auth generated for loopback pulls")
342+ return nil
343+}
344+
345+func createDomainSecretStore(cfg Config, log zerowrap.Logger) (string, domain.SecretsBackend, *domainsecrets.PassStore, out.DomainSecretStore, error) {
346+ envDir := resolveEnvDir(cfg)
347+ backend := resolveSecretsBackend(cfg.Auth.SecretsBackend)
348+
349+ switch backend {
350+ case domain.SecretsBackendPass:
351+ passStore, err := domainsecrets.NewPassStore(log)
352+ if err != nil {
353+ return "", backend, nil, nil, log.WrapErr(err, "failed to create pass domain secret store")
354+ }
355+ if err := migrateEnvFilesToPass(envDir, passStore, log); err != nil {
356+ return "", backend, nil, nil, log.WrapErr(err, "failed to migrate env files to pass")
357+ }
358+ return envDir, backend, passStore, passStore, nil
359+ default:
360+ store, err := domainsecrets.NewFileStore(envDir, log)
361+ if err != nil {
362+ return "", backend, nil, nil, log.WrapErr(err, "failed to create domain secret store")
363+ }
364+ return envDir, backend, nil, store, nil
365+ }
366+}
367+
351368 // resolveLogFilePath returns the configured log file path or a default.
352369 func resolveLogFilePath(cfg Config) string {
353370 if cfg.Logging.File.Path != "" {
@@ -266,19 +266,8 @@ func createServices(ctx context.Context, v *viper.Viper, cfg Config, log zerowra
266 return nil, err266 return nil, err
267 }267 }
268 268
269- // Generate internal registry credentials for loopback-only pulls269+ if err := setupInternalRegistryAuth(cfg, svc, log); err != nil {
270- if cfg.Auth.Enabled {270+ return nil, err
271- svc.internalRegUser, svc.internalRegPass, err = generateInternalRegistryAuth()
272- if err != nil {
273- return nil, log.WrapErr(err, "failed to generate internal registry credentials")
274- }
275-
276- // Persist credentials to file for CLI access (gordon auth internal)
277- if err := persistInternalCredentials(svc.internalRegUser, svc.internalRegPass); err != nil {
278- log.Warn().Err(err).Msg("failed to persist internal credentials for CLI access")
279- }
280-
281- log.Debug().Msg("internal registry auth generated for loopback pulls")
282 }271 }
283 272
284 // Create use case services273 // Create use case services
@@ -287,28 +276,13 @@ func createServices(ctx context.Context, v *viper.Viper, cfg Config, log zerowra
287 return nil, log.WrapErr(err, "failed to load configuration")276 return nil, log.WrapErr(err, "failed to load configuration")
288 }277 }
289 278
290- // Determine env directory for admin API279+ var backend domain.SecretsBackend
291- svc.envDir = resolveEnvDir(cfg)
292-
293- backend := resolveSecretsBackend(cfg.Auth.SecretsBackend)
294- var domainSecretStore out.DomainSecretStore
295 var passStore *domainsecrets.PassStore280 var passStore *domainsecrets.PassStore
281+ var domainSecretStore out.DomainSecretStore
296 282
297- switch backend {283+ svc.envDir, backend, passStore, domainSecretStore, err = createDomainSecretStore(cfg, log)
298- case domain.SecretsBackendPass:284+ if err != nil {
299- passStore, err = domainsecrets.NewPassStore(log)285+ return nil, err
300- if err != nil {
301- return nil, log.WrapErr(err, "failed to create pass domain secret store")
302- }
303- if err := migrateEnvFilesToPass(svc.envDir, passStore, log); err != nil {
304- return nil, log.WrapErr(err, "failed to migrate env files to pass")
305- }
306- domainSecretStore = passStore
307- default:
308- domainSecretStore, err = domainsecrets.NewFileStore(svc.envDir, log)
309- if err != nil {
310- return nil, log.WrapErr(err, "failed to create domain secret store")
311- }
312 }286 }
313 287
314 if svc.envLoader, err = createEnvLoader(backend, svc.envDir, passStore, log); err != nil {288 if svc.envLoader, err = createEnvLoader(backend, svc.envDir, passStore, log); err != nil {
@@ -348,6 +322,49 @@ func createServices(ctx context.Context, v *viper.Viper, cfg Config, log zerowra
348 return svc, nil322 return svc, nil
349 }323 }
350 324
325+func setupInternalRegistryAuth(cfg Config, svc *services, log zerowrap.Logger) error {
326+ if !cfg.Auth.Enabled {
327+ return nil
328+ }
329+
330+ var err error
331+ svc.internalRegUser, svc.internalRegPass, err = generateInternalRegistryAuth()
332+ if err != nil {
333+ return log.WrapErr(err, "failed to generate internal registry credentials")
334+ }
335+
336+ // Persist credentials to file for CLI access (gordon auth internal)
337+ if err := persistInternalCredentials(svc.internalRegUser, svc.internalRegPass); err != nil {
338+ log.Warn().Err(err).Msg("failed to persist internal credentials for CLI access")
339+ }
340+
341+ log.Debug().Msg("internal registry auth generated for loopback pulls")
342+ return nil
343+}
344+
345+func createDomainSecretStore(cfg Config, log zerowrap.Logger) (string, domain.SecretsBackend, *domainsecrets.PassStore, out.DomainSecretStore, error) {
346+ envDir := resolveEnvDir(cfg)
347+ backend := resolveSecretsBackend(cfg.Auth.SecretsBackend)
348+
349+ switch backend {
350+ case domain.SecretsBackendPass:
351+ passStore, err := domainsecrets.NewPassStore(log)
352+ if err != nil {
353+ return "", backend, nil, nil, log.WrapErr(err, "failed to create pass domain secret store")
354+ }
355+ if err := migrateEnvFilesToPass(envDir, passStore, log); err != nil {
356+ return "", backend, nil, nil, log.WrapErr(err, "failed to migrate env files to pass")
357+ }
358+ return envDir, backend, passStore, passStore, nil
359+ default:
360+ store, err := domainsecrets.NewFileStore(envDir, log)
361+ if err != nil {
362+ return "", backend, nil, nil, log.WrapErr(err, "failed to create domain secret store")
363+ }
364+ return envDir, backend, nil, store, nil
365+ }
366+}
367+
351 // resolveLogFilePath returns the configured log file path or a default.368 // resolveLogFilePath returns the configured log file path or a default.
352 func resolveLogFilePath(cfg Config) string {369 func resolveLogFilePath(cfg Config) string {
353 if cfg.Logging.File.Path != "" {370 if cfg.Logging.File.Path != "" {

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