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.databases.enabled |
false |
backups.databases.schedule |
"daily" ("hourly", "daily", "weekly", "monthly") |
backups.databases.time |
"" (preset default, server local time) |
backups.volumes.enabled |
false |
backups.volumes.schedule |
"daily" |
backups.volumes.time |
"" (preset default, server local time) |
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.databases.enabled` | `false` |
187| `backups.databases.schedule` | `"daily"` (`"hourly"`, `"daily"`, `"weekly"`, `"monthly"`) |
188| `backups.databases.time` | `""` (preset default, server local time) |
189| `backups.volumes.enabled` | `false` |
190| `backups.volumes.schedule` | `"daily"` |
191| `backups.volumes.time` | `""` (preset default, server local time) |
192| `images.allowed_registries` | `[]` |
193| `images.require_digest` | `false` |
194| `images.prune.enabled` | `false` |
195| `images.prune.schedule` | `"daily"` |
196| `images.prune.keep_last` | `3` |
197| `telemetry.enabled` | `false` |
198| `telemetry.endpoint` | `""` |
199| `telemetry.auth_token` | `""` |
200| `telemetry.traces` | `true` |
201| `telemetry.metrics` | `true` |
202| `telemetry.logs` | `true` |
203| `telemetry.trace_sample_rate` | `1.0` |
204
205When `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).
206
207## Hot Reload
208
209Gordon watches the configuration file and reloads automatically when changes are detected. You can also trigger a manual reload:
210
211```bash
212gordon daemon reload
213```
214
215### Hot-reloaded (no restart needed)
216
217| Setting |
218|---------|
219| `server.gordon_domain` (registry domain) |
220| `server.registry_port` |
221| `server.max_proxy_body_size` |
222| `server.max_proxy_response_size` |
223| `server.max_concurrent_conns` |
224| `traffic.http.*` (new connections after the traffic graph is applied) |
225
226
227### Requires restart
228
229| Setting |
230|---------|
231| `entrypoints.edge.address` |
232| `server.data_dir` |
233| `server.max_blob_chunk_size` |
234| `server.max_blob_size` |
235| `server.http.*` |
236| `auth.*` |
237
238## Environment Variable Override
239
240Configuration values can be overridden with environment variables:
241
242```bash
243GORDON_LOGGING_LEVEL=debug gordon serve
244```
245
246Pattern: `GORDON_SECTION_KEY` (uppercase, underscores instead of dots)
247
248## Related
249
250- [Server Configuration](./server.md)
251- [App Manifest](./apps.md)
252- [External Routes](./external-routes.md)
253- [Standalone Services](./services.md)
254- [Traffic Plane](./traffic.md)
255- [Authentication](./auth.md)
256- [Telemetry](./telemetry.md)
257- [Backups](./backups.md)
258- [Images](./images.md)