v3.3.0 b164fe9

index.md RawHistoryFolder

Configuration Overview

Gordon uses a single TOML configuration file located at ~/.config/gordon/gordon.toml.

Configuration File Location

Location Purpose
~/.config/gordon/gordon.toml Default configuration file
Custom path via --config flag gordon serve --config /path/to/config.toml

Minimal Configuration

[server]
registry_port = 5000
gordon_domain = "gordon.mydomain.com"

[entrypoints.edge]
address = ":443"
protocol = "smart_tcp"

Application workloads live in standalone app files, not in gordon.toml — see App Manifest. Retired workload keys such as [routes], [attachments], [network_groups], [service_routes], [auto_route], and [previews] are rejected at startup. Installation-level [[services]] for standalone L4 workloads remains valid.

Note: gordon_domain is the canonical registry and Admin API host.

For a staged registry host rename, set the new server.gordon_domain and keep old Gordon registry hosts in server.legacy_registry_domains until clients move. See Server and Upgrading.

Full Configuration Reference

For a complete list of all configuration options with their default values, see the Configuration Reference.

Note: This example shows production-style paths. Default paths use ~/.gordon/ for user installations.

# Server settings
[server]
registry_port = 5000                     # Registry port (default: 5000)
gordon_domain = "gordon.mydomain.com"    # Required: Gordon domain (registry + API)
# data_dir = "~/.gordon"                 # Default for user installations

[entrypoints.edge]
address = ":443"                         # Deployment-selected public TCP socket
protocol = "smart_tcp"

# Authentication (includes secrets backend)
[auth]
enabled = true                           # Enable registry authentication (default: true)
secrets_backend = "pass"                 # "pass", "sops", or "unsafe"
token_secret = "gordon/auth/token_secret"  # Required: JWT signing secret
token_expiry = "30d"                     # Duration (1y, 30d, 2w) or 0 for never
# Token-only authentication (password login was removed in v2.30.0)

# API rate limiting
[api.rate_limit]
enabled = true                           # Enable rate limiting (default: true)
global_rps = 500                         # Max requests/second globally
per_ip_rps = 50                          # Max requests/second per IP
burst = 100                              # Burst size
trusted_proxies = []                     # IPs/CIDRs trusted for X-Forwarded-For

# Container runtime profile
[containers]
security_profile = "compat"              # compat or strict

# Logging
[logging]
level = "info"                           # trace, debug, info, warn, error
format = "console"                       # console or json

[logging.file]
enabled = true
path = "~/.gordon/logs/gordon.log"       # Default location
max_size = 100                           # MB before rotation
max_backups = 3                          # Old files to keep
max_age = 28                             # Days to keep

# Workload logs are streamed directly from the container runtime with
# `gordon apps logs APP --service SERVICE`.

# Telemetry (OpenTelemetry)
[telemetry]
enabled = true                           # Enable OTLP export (default: false)
endpoint = "http://localhost:5080/api/default"  # OTLP HTTP endpoint
auth_token = ""                          # Base64 user:password for Basic auth
traces = true                            # Export traces
metrics = true                           # Export metrics
logs = true                              # Export Gordon, access, and app logs
trace_sample_rate = 1.0                  # 0.0 = none, 1.0 = all

# Volume settings
[volumes]
auto_create = true                       # Auto-create from Dockerfile VOLUME
prefix = "gordon"                        # Volume name prefix
preserve = true                          # Keep volumes on container removal

# Installation network policy (prefix filter for `gordon daemon networks`)
[network_isolation]
enabled = true                           # Gordon-managed network policy
network_prefix = "gordon"                # Network name prefix
internal = false                          # Set true to block direct egress from isolated networks

# REMOVED in v3 (declare apps in standalone files, see ./apps.md):
# [routes], [attachments], [network_groups],
# [service_routes], [auto_route], [previews]

# Backups
[backups]
enabled = true
schedule = "daily"                        # "hourly", "daily", "weekly", "monthly"
storage_dir = "~/.gordon/backups"

[backups.retention]
hourly = 24
daily = 7
weekly = 4
monthly = 12

# Images
[images]
allowed_registries = []                   # Additional exact registry hostname+port entries
require_digest = false                    # Require SHA-256 digests for every image registry

[images.prune]
enabled = false
schedule = "daily"
keep_last = 3

Docker Hub (docker.io and registry-1.docker.io), ghcr.io, quay.io, and Gordon's registry are allowed by default. Add private or other registries with exact hostname+port entries. This hostname policy does not enforce resolved IP destinations or runtime egress; see Images.

Configuration Sections

Section Description Documentation
[server] Core server settings Server
[auth] Authentication and secrets backend Auth
[api.rate_limit] Rate limiting configuration Rate Limiting
[logging] Logging configuration Logging
[telemetry] OpenTelemetry observability export Telemetry
[volumes] Volume management Volumes
[network_isolation] Installation network policy Network Isolation
[external_routes] Non-containerized service proxying External Routes
[entrypoints], [traffic], [[network_services]], [[services]] L4 and TLS passthrough traffic plane Traffic
App files (<app>.toml) Declarative apps: services, hosts, secrets, volumes, backup targets App Manifest
[backups] Database backup storage, scheduling, and retention Backups
[images.prune] Scheduled image cleanup Images
Security hardening Security controls and recommended knobs Security Hardening

Default Values

Setting Default
server.registry_port 5000
server.data_dir ~/.gordon
server.max_blob_chunk_size "95MB"
server.max_blob_size "1GB"
server.http.read_header_timeout "10s"
server.http.read_timeout "5m"
server.http.write_timeout "5m"
server.http.idle_timeout "120s"
traffic.http.read_header_timeout "5s"
traffic.http.idle_timeout "30s"
traffic.http.transfer_idle_timeout "2m"
auth.enabled true
auth.secrets_backend "unsafe"
auth.token_expiry "30d"
api.rate_limit.enabled true
api.rate_limit.global_rps 500
api.rate_limit.per_ip_rps 50
api.rate_limit.burst 100
api.rate_limit.trusted_proxies []
containers.security_profile "compat"
logging.level "info"
logging.format "console"
logging.file.enabled false
logging.file.max_size 100
logging.file.max_backups 3
logging.file.max_age 28
volumes.auto_create true
volumes.prefix "gordon"
volumes.preserve true
network_isolation.enabled true
network_isolation.internal false
backups.enabled false
backups.schedule "daily" ("hourly", "daily", "weekly", "monthly")
images.allowed_registries []
images.require_digest false
images.prune.enabled false
images.prune.schedule "daily"
images.prune.keep_last 3
telemetry.enabled false
telemetry.endpoint ""
telemetry.auth_token ""
telemetry.traces true
telemetry.metrics true
telemetry.logs true
telemetry.trace_sample_rate 1.0

When auth.enabled=false, Gordon runs in local-only mode: /admin/* is not registered on the TCP listener and /v2/* is loopback-only. Local gordon apps commands discover the daemon's owner-only admin socket in $XDG_RUNTIME_DIR/gordon, /run/user/<uid>/gordon, or ~/.gordon/run; the daemon itself uses the XDG location when configured and otherwise the home fallback. See Authentication.

Hot Reload

Gordon watches the configuration file and reloads automatically when changes are detected. You can also trigger a manual reload:

gordon daemon reload

Hot-reloaded (no restart needed)

Setting
server.gordon_domain (registry domain)
server.registry_port
server.max_proxy_body_size
server.max_proxy_response_size
server.max_concurrent_conns
traffic.http.* (new connections after the traffic graph is applied)

Requires restart

Setting
entrypoints.edge.address
server.data_dir
server.max_blob_chunk_size
server.max_blob_size
server.http.*
auth.*

Environment Variable Override

Configuration values can be overridden with environment variables:

GORDON_LOGGING_LEVEL=debug gordon serve

Pattern: GORDON_SECTION_KEY (uppercase, underscores instead of dots)

source
1# Configuration Overview
2
3Gordon uses a single TOML configuration file located at `~/.config/gordon/gordon.toml`.
4
5## Configuration File Location
6
7| Location | Purpose |
8|----------|---------|
9| `~/.config/gordon/gordon.toml` | Default configuration file |
10| Custom path via `--config` flag | `gordon serve --config /path/to/config.toml` |
11
12## Minimal Configuration
13
14```toml
15[server]
16registry_port = 5000
17gordon_domain = "gordon.mydomain.com"
18
19[entrypoints.edge]
20address = ":443"
21protocol = "smart_tcp"
22```
23
24Application workloads live in standalone app files, not in `gordon.toml` — see [App Manifest](./apps.md). Retired workload keys such as `[routes]`, `[attachments]`, `[network_groups]`, `[service_routes]`, `[auto_route]`, and `[previews]` are rejected at startup. Installation-level `[[services]]` for standalone L4 workloads remains valid.
25
26> **Note:** `gordon_domain` is the canonical registry and Admin API host.
27>
28> For a staged registry host rename, set the new `server.gordon_domain` and keep old Gordon registry hosts in `server.legacy_registry_domains` until clients move. See [Server](./server.md#gordon-domain) and [Upgrading](../upgrading.md#staged-registry-host-rename).
29
30## Full Configuration Reference
31
32For a complete list of all configuration options with their default values, see the [Configuration Reference](./reference.md).
33
34> **Note:** This example shows production-style paths. Default paths use `~/.gordon/` for user installations.
35
36```toml
37# Server settings
38[server]
39registry_port = 5000                     # Registry port (default: 5000)
40gordon_domain = "gordon.mydomain.com"    # Required: Gordon domain (registry + API)
41# data_dir = "~/.gordon"                 # Default for user installations
42
43[entrypoints.edge]
44address = ":443"                         # Deployment-selected public TCP socket
45protocol = "smart_tcp"
46
47# Authentication (includes secrets backend)
48[auth]
49enabled = true                           # Enable registry authentication (default: true)
50secrets_backend = "pass"                 # "pass", "sops", or "unsafe"
51token_secret = "gordon/auth/token_secret"  # Required: JWT signing secret
52token_expiry = "30d"                     # Duration (1y, 30d, 2w) or 0 for never
53# Token-only authentication (password login was removed in v2.30.0)
54
55# API rate limiting
56[api.rate_limit]
57enabled = true                           # Enable rate limiting (default: true)
58global_rps = 500                         # Max requests/second globally
59per_ip_rps = 50                          # Max requests/second per IP
60burst = 100                              # Burst size
61trusted_proxies = []                     # IPs/CIDRs trusted for X-Forwarded-For
62
63# Container runtime profile
64[containers]
65security_profile = "compat"              # compat or strict
66
67# Logging
68[logging]
69level = "info"                           # trace, debug, info, warn, error
70format = "console"                       # console or json
71
72[logging.file]
73enabled = true
74path = "~/.gordon/logs/gordon.log"       # Default location
75max_size = 100                           # MB before rotation
76max_backups = 3                          # Old files to keep
77max_age = 28                             # Days to keep
78
79# Workload logs are streamed directly from the container runtime with
80# `gordon apps logs APP --service SERVICE`.
81
82# Telemetry (OpenTelemetry)
83[telemetry]
84enabled = true                           # Enable OTLP export (default: false)
85endpoint = "http://localhost:5080/api/default"  # OTLP HTTP endpoint
86auth_token = ""                          # Base64 user:password for Basic auth
87traces = true                            # Export traces
88metrics = true                           # Export metrics
89logs = true                              # Export Gordon, access, and app logs
90trace_sample_rate = 1.0                  # 0.0 = none, 1.0 = all
91
92# Volume settings
93[volumes]
94auto_create = true                       # Auto-create from Dockerfile VOLUME
95prefix = "gordon"                        # Volume name prefix
96preserve = true                          # Keep volumes on container removal
97
98# Installation network policy (prefix filter for `gordon daemon networks`)
99[network_isolation]
100enabled = true                           # Gordon-managed network policy
101network_prefix = "gordon"                # Network name prefix
102internal = false                          # Set true to block direct egress from isolated networks
103
104# REMOVED in v3 (declare apps in standalone files, see ./apps.md):
105# [routes], [attachments], [network_groups],
106# [service_routes], [auto_route], [previews]
107
108# Backups
109[backups]
110enabled = true
111schedule = "daily"                        # "hourly", "daily", "weekly", "monthly"
112storage_dir = "~/.gordon/backups"
113
114[backups.retention]
115hourly = 24
116daily = 7
117weekly = 4
118monthly = 12
119
120# Images
121[images]
122allowed_registries = []                   # Additional exact registry hostname+port entries
123require_digest = false                    # Require SHA-256 digests for every image registry
124
125[images.prune]
126enabled = false
127schedule = "daily"
128keep_last = 3
129```
130
131Docker Hub (`docker.io` and `registry-1.docker.io`), `ghcr.io`, `quay.io`, and Gordon's registry are allowed by default. Add private or other registries with exact hostname+port entries. This hostname policy does not enforce resolved IP destinations or runtime egress; see [Images](./images.md).
132
133## Configuration Sections
134
135| Section | Description | Documentation |
136|---------|-------------|---------------|
137| `[server]` | Core server settings | [Server](./server.md) |
138| `[auth]` | Authentication and secrets backend | [Auth](./auth.md) |
139| `[api.rate_limit]` | Rate limiting configuration | [Rate Limiting](./rate-limiting.md) |
140| `[logging]` | Logging configuration | [Logging](./logging.md) |
141| `[telemetry]` | OpenTelemetry observability export | [Telemetry](./telemetry.md) |
142| `[volumes]` | Volume management | [Volumes](./volumes.md) |
143| `[network_isolation]` | Installation network policy | [Network Isolation](./network-isolation.md) |
144| `[external_routes]` | Non-containerized service proxying | [External Routes](./external-routes.md) |
145| `[entrypoints]`, `[traffic]`, `[[network_services]]`, `[[services]]` | L4 and TLS passthrough traffic plane | [Traffic](./traffic.md) |
146| App files (`<app>.toml`) | Declarative apps: services, hosts, secrets, volumes, backup targets | [App Manifest](./apps.md) |
147| `[backups]` | Database backup storage, scheduling, and retention | [Backups](./backups.md) |
148| `[images.prune]` | Scheduled image cleanup | [Images](./images.md) |
149| Security hardening | Security controls and recommended knobs | [Security Hardening](./security-hardening.md) |
150
151## Default Values
152
153| Setting | Default |
154|---------|---------|
155| `server.registry_port` | `5000` |
156| `server.data_dir` | `~/.gordon` |
157| `server.max_blob_chunk_size` | `"95MB"` |
158| `server.max_blob_size` | `"1GB"` |
159| `server.http.read_header_timeout` | `"10s"` |
160| `server.http.read_timeout` | `"5m"` |
161| `server.http.write_timeout` | `"5m"` |
162| `server.http.idle_timeout` | `"120s"` |
163| `traffic.http.read_header_timeout` | `"5s"` |
164| `traffic.http.idle_timeout` | `"30s"` |
165| `traffic.http.transfer_idle_timeout` | `"2m"` |
166| `auth.enabled` | `true` |
167| `auth.secrets_backend` | `"unsafe"` |
168| `auth.token_expiry` | `"30d"` |
169| `api.rate_limit.enabled` | `true` |
170| `api.rate_limit.global_rps` | `500` |
171| `api.rate_limit.per_ip_rps` | `50` |
172| `api.rate_limit.burst` | `100` |
173| `api.rate_limit.trusted_proxies` | `[]` |
174| `containers.security_profile` | `"compat"` |
175| `logging.level` | `"info"` |
176| `logging.format` | `"console"` |
177| `logging.file.enabled` | `false` |
178| `logging.file.max_size` | `100` |
179| `logging.file.max_backups` | `3` |
180| `logging.file.max_age` | `28` |
181| `volumes.auto_create` | `true` |
182| `volumes.prefix` | `"gordon"` |
183| `volumes.preserve` | `true` |
184| `network_isolation.enabled` | `true` |
185| `network_isolation.internal` | `false` |
186| `backups.enabled` | `false` |
187| `backups.schedule` | `"daily"` (`"hourly"`, `"daily"`, `"weekly"`, `"monthly"`) |
188| `images.allowed_registries` | `[]` |
189| `images.require_digest` | `false` |
190| `images.prune.enabled` | `false` |
191| `images.prune.schedule` | `"daily"` |
192| `images.prune.keep_last` | `3` |
193| `telemetry.enabled` | `false` |
194| `telemetry.endpoint` | `""` |
195| `telemetry.auth_token` | `""` |
196| `telemetry.traces` | `true` |
197| `telemetry.metrics` | `true` |
198| `telemetry.logs` | `true` |
199| `telemetry.trace_sample_rate` | `1.0` |
200
201When `auth.enabled=false`, Gordon runs in local-only mode: `/admin/*` is not registered on the TCP listener and `/v2/*` is loopback-only. Local `gordon apps` commands discover the daemon's owner-only admin socket in `$XDG_RUNTIME_DIR/gordon`, `/run/user/<uid>/gordon`, or `~/.gordon/run`; the daemon itself uses the XDG location when configured and otherwise the home fallback. See [Authentication](./auth.md#local-only-mode).
202
203## Hot Reload
204
205Gordon watches the configuration file and reloads automatically when changes are detected. You can also trigger a manual reload:
206
207```bash
208gordon daemon reload
209```
210
211### Hot-reloaded (no restart needed)
212
213| Setting |
214|---------|
215| `server.gordon_domain` (registry domain) |
216| `server.registry_port` |
217| `server.max_proxy_body_size` |
218| `server.max_proxy_response_size` |
219| `server.max_concurrent_conns` |
220| `traffic.http.*` (new connections after the traffic graph is applied) |
221
222
223### Requires restart
224
225| Setting |
226|---------|
227| `entrypoints.edge.address` |
228| `server.data_dir` |
229| `server.max_blob_chunk_size` |
230| `server.max_blob_size` |
231| `server.http.*` |
232| `auth.*` |
233
234## Environment Variable Override
235
236Configuration values can be overridden with environment variables:
237
238```bash
239GORDON_LOGGING_LEVEL=debug gordon serve
240```
241
242Pattern: `GORDON_SECTION_KEY` (uppercase, underscores instead of dots)
243
244## Related
245
246- [Server Configuration](./server.md)
247- [App Manifest](./apps.md)
248- [External Routes](./external-routes.md)
249- [Standalone Services](./services.md)
250- [Traffic Plane](./traffic.md)
251- [Authentication](./auth.md)
252- [Telemetry](./telemetry.md)
253- [Backups](./backups.md)
254- [Images](./images.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