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"
[routes]
"app.mydomain.com" = "myapp:latest"
Note: gordon_domain is the canonical key. Migrate older registry_domain values before restarting.
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
# Deploy behavior
[deploy]
pull_policy = "if-tag-changed" # always, if-not-present, if-tag-changed
readiness_mode = "auto" # auto, docker-health, delay
health_timeout = "90s" # Max wait for health-based readiness
readiness_delay = "5s" # Wait after running before ready
drain_mode = "auto" # auto, inflight, delay
drain_timeout = "30s" # Max wait for in-flight drain
drain_delay = "2s" # Wait after proxy invalidation before stopping the old container
# 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
[logging.container_logs]
enabled = true
dir = "~/.gordon/logs/containers" # Default location
max_size = 100
max_backups = 3
max_age = 28
# 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 # Bridge zerolog to OTLP logs
trace_sample_rate = 1.0 # 0.0 = none, 1.0 = all
# Environment variables
[env]
dir = "~/.gordon/env" # Default location
# Volume settings
[volumes]
auto_create = true # Auto-create from Dockerfile VOLUME
prefix = "gordon" # Volume name prefix
preserve = true # Keep volumes on container removal
# Network isolation
[network_isolation]
enabled = true # Per-app isolated networks
network_prefix = "gordon" # Network name prefix
internal = false # Set true to block direct egress from isolated networks
# Auto-route
[auto_route]
enabled = false # Auto-create routes from image names
# Routes (required)
[routes]
"app.mydomain.com" = "myapp:latest"
"api.mydomain.com" = "myapi:v2.1.0"
# Network groups
[network_groups]
"backend" = ["app.mydomain.com", "api.mydomain.com"]
# Attachments
[attachments]
"app.mydomain.com" = ["postgres:latest", "redis:latest"]
"backend" = ["rabbitmq:latest"]
# 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 = [] # Explicit external registries allowed for deploy/attachments
require_digest = false # Require digests for allowlisted external registries
[images.prune]
enabled = false
schedule = "daily"
keep_last = 3
Configuration Sections
| Section |
Description |
Documentation |
[server] |
Core server settings |
Server |
[auth] |
Authentication and secrets backend |
Auth |
[api.rate_limit] |
Rate limiting configuration |
Rate Limiting |
[deploy] |
Deployment behavior |
Deploy |
[logging] |
Logging configuration |
Logging |
[telemetry] |
OpenTelemetry observability export |
Telemetry |
[env] |
Environment variable settings |
Environment |
[volumes] |
Volume management |
Volumes |
[network_isolation] |
Network isolation settings |
Network Isolation |
[auto_route] |
Automatic route creation |
Auto Route |
[routes] |
Domain to image mapping |
Routes |
[external_routes] |
Non-containerized service proxying |
External Routes |
[entrypoints], [traffic], [[network_services]], [[services]] |
L4 and TLS passthrough traffic plane |
Traffic |
[network_groups] |
Shared service networks |
Network Groups |
[attachments] |
Service dependencies |
Attachments |
[backups] |
Database backups |
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" |
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 |
[] |
deploy.pull_policy |
"if-tag-changed" |
deploy.readiness_mode |
"auto" |
deploy.health_timeout |
"90s" |
deploy.readiness_delay |
"5s" |
deploy.drain_mode |
"auto" |
deploy.drain_timeout |
"30s" |
deploy.drain_delay |
"2s" |
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 |
logging.container_logs.enabled |
true |
volumes.auto_create |
true |
volumes.prefix |
"gordon" |
volumes.preserve |
true |
network_isolation.enabled |
true |
network_isolation.internal |
false |
auto_route.enabled |
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 disabled and /v2/* is loopback-only.
Hot Reload
Gordon watches the configuration file and reloads automatically when changes are detected. You can also trigger a manual reload:
gordon 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 |
Note: Routes are hot-reloaded from the config file. You can still use the API or CLI (gordon routes add/update/remove) for live route changes.
Requires restart
| Setting |
entrypoints.edge.address |
server.data_dir |
server.max_blob_chunk_size |
server.max_blob_size |
auth.* |
deploy.readiness_mode |
deploy.readiness_delay |
deploy.health_timeout |
deploy.drain_mode |
deploy.drain_timeout |
Environment Variable Override
Configuration values can be overridden with environment variables:
GORDON_SERVER_PORT=8088 gordon serve
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[routes]
24"app.mydomain.com" = "myapp:latest"
25```
26
27> **Note:** `gordon_domain` is the canonical key. Migrate older `registry_domain` values before restarting.
28>
29> 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).
30
31## Full Configuration Reference
32
33For a complete list of all configuration options with their default values, see the [Configuration Reference](./reference.md).
34
35> **Note:** This example shows production-style paths. Default paths use `~/.gordon/` for user installations.
36
37```toml
38# Server settings
39[server]
40registry_port = 5000 # Registry port (default: 5000)
41gordon_domain = "gordon.mydomain.com" # Required: Gordon domain (registry + API)
42# data_dir = "~/.gordon" # Default for user installations
43
44[entrypoints.edge]
45address = ":443" # Deployment-selected public TCP socket
46protocol = "smart_tcp"
47
48# Authentication (includes secrets backend)
49[auth]
50enabled = true # Enable registry authentication (default: true)
51secrets_backend = "pass" # "pass", "sops", or "unsafe"
52token_secret = "gordon/auth/token_secret" # Required: JWT signing secret
53token_expiry = "30d" # Duration (1y, 30d, 2w) or 0 for never
54# Token-only authentication (password login was removed in v2.30.0)
55
56# API rate limiting
57[api.rate_limit]
58enabled = true # Enable rate limiting (default: true)
59global_rps = 500 # Max requests/second globally
60per_ip_rps = 50 # Max requests/second per IP
61burst = 100 # Burst size
62trusted_proxies = [] # IPs/CIDRs trusted for X-Forwarded-For
63
64# Deploy behavior
65[deploy]
66pull_policy = "if-tag-changed" # always, if-not-present, if-tag-changed
67readiness_mode = "auto" # auto, docker-health, delay
68health_timeout = "90s" # Max wait for health-based readiness
69readiness_delay = "5s" # Wait after running before ready
70drain_mode = "auto" # auto, inflight, delay
71drain_timeout = "30s" # Max wait for in-flight drain
72drain_delay = "2s" # Wait after proxy invalidation before stopping the old container
73
74# Container runtime profile
75[containers]
76security_profile = "compat" # compat or strict
77
78# Logging
79[logging]
80level = "info" # trace, debug, info, warn, error
81format = "console" # console or json
82
83[logging.file]
84enabled = true
85path = "~/.gordon/logs/gordon.log" # Default location
86max_size = 100 # MB before rotation
87max_backups = 3 # Old files to keep
88max_age = 28 # Days to keep
89
90[logging.container_logs]
91enabled = true
92dir = "~/.gordon/logs/containers" # Default location
93max_size = 100
94max_backups = 3
95max_age = 28
96
97# Telemetry (OpenTelemetry)
98[telemetry]
99enabled = true # Enable OTLP export (default: false)
100endpoint = "http://localhost:5080/api/default" # OTLP HTTP endpoint
101auth_token = "" # Base64 user:password for Basic auth
102traces = true # Export traces
103metrics = true # Export metrics
104logs = true # Bridge zerolog to OTLP logs
105trace_sample_rate = 1.0 # 0.0 = none, 1.0 = all
106
107# Environment variables
108[env]
109dir = "~/.gordon/env" # Default location
110
111# Volume settings
112[volumes]
113auto_create = true # Auto-create from Dockerfile VOLUME
114prefix = "gordon" # Volume name prefix
115preserve = true # Keep volumes on container removal
116
117# Network isolation
118[network_isolation]
119enabled = true # Per-app isolated networks
120network_prefix = "gordon" # Network name prefix
121internal = false # Set true to block direct egress from isolated networks
122
123# Auto-route
124[auto_route]
125enabled = false # Auto-create routes from image names
126
127# Routes (required)
128[routes]
129"app.mydomain.com" = "myapp:latest"
130"api.mydomain.com" = "myapi:v2.1.0"
131
132# Network groups
133[network_groups]
134"backend" = ["app.mydomain.com", "api.mydomain.com"]
135
136# Attachments
137[attachments]
138"app.mydomain.com" = ["postgres:latest", "redis:latest"]
139"backend" = ["rabbitmq:latest"]
140
141# Backups
142[backups]
143enabled = true
144schedule = "daily" # "hourly", "daily", "weekly", "monthly"
145storage_dir = "~/.gordon/backups"
146
147[backups.retention]
148hourly = 24
149daily = 7
150weekly = 4
151monthly = 12
152
153# Images
154[images]
155allowed_registries = [] # Explicit external registries allowed for deploy/attachments
156require_digest = false # Require digests for allowlisted external registries
157
158[images.prune]
159enabled = false
160schedule = "daily"
161keep_last = 3
162```
163
164## Configuration Sections
165
166| Section | Description | Documentation |
167|---------|-------------|---------------|
168| `[server]` | Core server settings | [Server](./server.md) |
169| `[auth]` | Authentication and secrets backend | [Auth](./auth.md) |
170| `[api.rate_limit]` | Rate limiting configuration | [Rate Limiting](./rate-limiting.md) |
171| `[deploy]` | Deployment behavior | [Deploy](./deploy.md) |
172| `[logging]` | Logging configuration | [Logging](./logging.md) |
173| `[telemetry]` | OpenTelemetry observability export | [Telemetry](./telemetry.md) |
174| `[env]` | Environment variable settings | [Environment](./env.md) |
175| `[volumes]` | Volume management | [Volumes](./volumes.md) |
176| `[network_isolation]` | Network isolation settings | [Network Isolation](./network-isolation.md) |
177| `[auto_route]` | Automatic route creation | [Auto Route](./auto-route.md) |
178| `[routes]` | Domain to image mapping | [Routes](./routes.md) |
179| `[external_routes]` | Non-containerized service proxying | [External Routes](./external-routes.md) |
180| `[entrypoints]`, `[traffic]`, `[[network_services]]`, `[[services]]` | L4 and TLS passthrough traffic plane | [Traffic](./traffic.md) |
181| `[network_groups]` | Shared service networks | [Network Groups](./network-groups.md) |
182| `[attachments]` | Service dependencies | [Attachments](./attachments.md) |
183| `[backups]` | Database backups | [Backups](./backups.md) |
184| `[images.prune]` | Scheduled image cleanup | [Images](./images.md) |
185| Security hardening | Security controls and recommended knobs | [Security Hardening](./security-hardening.md) |
186
187## Default Values
188
189| Setting | Default |
190|---------|---------|
191| `server.registry_port` | `5000` |
192| `server.data_dir` | `~/.gordon` |
193| `server.max_blob_chunk_size` | `"95MB"` |
194| `server.max_blob_size` | `"1GB"` |
195| `auth.enabled` | `true` |
196| `auth.secrets_backend` | `"unsafe"` |
197| `auth.token_expiry` | `"30d"` |
198| `api.rate_limit.enabled` | `true` |
199| `api.rate_limit.global_rps` | `500` |
200| `api.rate_limit.per_ip_rps` | `50` |
201| `api.rate_limit.burst` | `100` |
202| `api.rate_limit.trusted_proxies` | `[]` |
203| `deploy.pull_policy` | `"if-tag-changed"` |
204| `deploy.readiness_mode` | `"auto"` |
205| `deploy.health_timeout` | `"90s"` |
206| `deploy.readiness_delay` | `"5s"` |
207| `deploy.drain_mode` | `"auto"` |
208| `deploy.drain_timeout` | `"30s"` |
209| `deploy.drain_delay` | `"2s"` |
210| `containers.security_profile` | `"compat"` |
211| `logging.level` | `"info"` |
212| `logging.format` | `"console"` |
213| `logging.file.enabled` | `false` |
214| `logging.file.max_size` | `100` |
215| `logging.file.max_backups` | `3` |
216| `logging.file.max_age` | `28` |
217| `logging.container_logs.enabled` | `true` |
218| `volumes.auto_create` | `true` |
219| `volumes.prefix` | `"gordon"` |
220| `volumes.preserve` | `true` |
221| `network_isolation.enabled` | `true` |
222| `network_isolation.internal` | `false` |
223| `auto_route.enabled` | `false` |
224| `backups.enabled` | `false` |
225| `backups.schedule` | `"daily"` (`"hourly"`, `"daily"`, `"weekly"`, `"monthly"`) |
226| `images.allowed_registries` | `[]` |
227| `images.require_digest` | `false` |
228| `images.prune.enabled` | `false` |
229| `images.prune.schedule` | `"daily"` |
230| `images.prune.keep_last` | `3` |
231| `telemetry.enabled` | `false` |
232| `telemetry.endpoint` | `""` |
233| `telemetry.auth_token` | `""` |
234| `telemetry.traces` | `true` |
235| `telemetry.metrics` | `true` |
236| `telemetry.logs` | `true` |
237| `telemetry.trace_sample_rate` | `1.0` |
238
239When `auth.enabled=false`, Gordon runs in local-only mode: `/admin/*` is disabled and `/v2/*` is loopback-only.
240
241## Hot Reload
242
243Gordon watches the configuration file and reloads automatically when changes are detected. You can also trigger a manual reload:
244
245```bash
246gordon reload
247```
248
249### Hot-reloaded (no restart needed)
250
251| Setting |
252|---------|
253| `server.gordon_domain` (registry domain) |
254| `server.registry_port` |
255| `server.max_proxy_body_size` |
256| `server.max_proxy_response_size` |
257| `server.max_concurrent_conns` |
258
259> **Note:** Routes are hot-reloaded from the config file. You can still use the API or CLI (`gordon routes add/update/remove`) for live route changes.
260
261### Requires restart
262
263| Setting |
264|---------|
265| `entrypoints.edge.address` |
266| `server.data_dir` |
267| `server.max_blob_chunk_size` |
268| `server.max_blob_size` |
269| `auth.*` |
270| `deploy.readiness_mode` |
271| `deploy.readiness_delay` |
272| `deploy.health_timeout` |
273| `deploy.drain_mode` |
274| `deploy.drain_timeout` |
275
276## Environment Variable Override
277
278Configuration values can be overridden with environment variables:
279
280```bash
281GORDON_SERVER_PORT=8088 gordon serve
282GORDON_LOGGING_LEVEL=debug gordon serve
283```
284
285Pattern: `GORDON_SECTION_KEY` (uppercase, underscores instead of dots)
286
287## Related
288
289- [Server Configuration](./server.md)
290- [Routes Configuration](./routes.md)
291- [External Routes](./external-routes.md)
292- [Standalone Services](./services.md)
293- [Traffic Plane](./traffic.md)
294- [Authentication](./auth.md)
295- [Telemetry](./telemetry.md)
296- [Backups](./backups.md)
297- [Images](./images.md)