Server Configuration
Core server settings for Gordon.
Configuration
[server]
port = 8088 # HTTP proxy port
registry_port = 5000 # Container registry port
tls_port = 8443 # HTTPS listener port (0 = disabled)
# tls_cert_file = "" # Optional: PEM certificate for static TLS
# tls_key_file = "" # Optional: PEM key for static TLS
# force_https_redirect = false # Redirect all HTTP traffic to HTTPS
gordon_domain = "gordon.mydomain.com" # Gordon domain (required)
# data_dir = "~/.gordon" # Data storage directory (default)
Options
| Option |
Type |
Default |
Description |
port |
int |
8088 |
HTTP proxy port for routing traffic to containers |
registry_port |
int |
5000 |
Docker registry port for image push/pull |
tls_port |
int |
8443 |
HTTPS listener port with internal CA. Set to 0 to disable TLS entirely |
tls_cert_file |
string |
"" |
Path to PEM certificate file. When set (with tls_key_file), this cert is served for matching SNI domains; unmatched domains fall through to the internal CA |
tls_key_file |
string |
"" |
Path to PEM private key file. Must be set together with tls_cert_file |
force_https_redirect |
bool |
false |
Redirect all HTTP requests to the HTTPS port. For direct-access setups without a TLS-terminating proxy |
gordon_domain |
string |
required |
Domain for Gordon (registry + admin API) |
registry_domain |
string |
- |
Deprecated alias for gordon_domain |
data_dir |
string |
~/.gordon |
Directory for registry data, logs, and env files |
max_proxy_body_size |
string |
"512MB" |
Maximum request body size for proxied requests |
max_blob_chunk_size |
string |
"95MB" |
Maximum request body size for a single registry blob upload chunk |
registry_allowed_ips |
[]string |
[] |
IPs or CIDR ranges allowed to access the registry (empty = allow all) |
proxy_allowed_ips |
[]string |
[] |
IPs or CIDR ranges allowed to reach the proxy (empty = allow all) |
registry_listen_address |
string |
"" |
Bind address for registry (empty = all interfaces) |
Port Configuration
Proxy Port
The port setting controls where Gordon listens for HTTP traffic:
[server]
port = 8080 # Use 8080 for rootless containers with port forwarding
For rootless containers, you'll typically use a high port and configure firewall port forwarding:
# Forward port 80 to 8080
sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
Internal CA and TLS
Gordon includes an internal certificate authority that issues on-demand TLS certificates for proxied domains. The HTTPS listener is enabled by default on tls_port (8443).
[server]
tls_port = 8443 # Default. Set to 0 to disable TLS entirely.
With TLS enabled:
- Gordon runs an internal CA (root + intermediate) stored in
{data_dir}/pki/
- Leaf certificates are issued on-demand per domain (SNI-based) and cached in memory
- The intermediate CA auto-renews before expiry
- An onboarding page at
https://<gordon-host>:<tls_port>/ca lets clients download the root CA certificate
- The root CA is stable across restarts (generated once, persisted to disk)
Custom certificates
To use your own certificate (e.g. from Tailscale, Let's Encrypt, or a corporate CA) alongside the internal CA:
[server]
tls_cert_file = "/etc/gordon/tls/cert.pem"
tls_key_file = "/etc/gordon/tls/key.pem"
The static certificate is served for SNI-matching domains (including wildcards). All other domains get on-demand certs from the internal CA.
HTTP to HTTPS redirect
When clients connect directly (no Cloudflare or reverse proxy in front), enable force_https_redirect to redirect all HTTP traffic to the HTTPS port:
[server]
force_https_redirect = true
When proxy_allowed_ips is configured, non-proxy clients are redirected automatically even without this flag — trusted proxy IPs pass through to serve Cloudflare-proxied traffic.
Disabling TLS
For setups where TLS is handled entirely by an external proxy (Cloudflare, nginx, etc.):
[server]
tls_port = 0 # No HTTPS listener, no internal CA generated
Firewall port forwarding
For rootless user services, forward 443 to the high port at the firewall:
# Forward 443 -> 8443
sudo firewall-cmd --permanent --add-forward-port=port=443:proto=tcp:toport=8443
sudo firewall-cmd --reload
With firewalld and Tailscale:
# Verify tailscale0 is in trusted zone
sudo firewall-cmd --get-zone-of-interface=tailscale0
# If needed, place tailscale0 in trusted
sudo firewall-cmd --permanent --zone=trusted --add-interface=tailscale0
sudo firewall-cmd --reload
# Forward 443 -> 8443 permanently (IPv4 + IPv6)
sudo firewall-cmd --permanent --zone=trusted --add-rich-rule='rule family=ipv4 forward-port port=443 protocol=tcp to-port=8443'
sudo firewall-cmd --permanent --zone=trusted --add-rich-rule='rule family=ipv6 forward-port port=443 protocol=tcp to-port=8443'
sudo firewall-cmd --reload
Registry Port
The registry_port setting controls where Gordon accepts image pushes:
[server]
registry_port = 5000
Docker/Podman clients push to this port:
docker push registry.mydomain.com:5000/myapp:latest
If the registry is served over plain HTTP (no TLS), clients must be configured to allow insecure access. See Troubleshooting: insecure registry for Docker and Podman instructions.
Gordon Domain
The gordon_domain is required and must match your DNS configuration:
[server]
gordon_domain = "gordon.mydomain.com"
This domain is used for:
- Docker login and image push/pull operations
- Admin API access (
/admin/* endpoints)
- CLI remote targeting (
gordon routes --remote https://gordon.mydomain.com)
- Authentication endpoints (
/auth/*)
When requests arrive on the proxy port with this domain as the Host header, Gordon routes them to the backend services (registry and admin API).
Security note:
- Direct access to
/admin/* on registry_port is blocked for non-loopback clients.
- Admin API traffic should go through the main proxy listener (
server.port/server.tls_port).
Note: registry_domain is supported as a deprecated alias for backwards compatibility.
Data Directory
The data_dir setting controls where Gordon stores data:
[server]
data_dir = "~/.gordon" # Default for user installations
Directory Structure
~/.gordon/
├── registry/ # Container images and manifests
│ ├── blobs/
│ └── manifests/
├── env/ # Environment files per domain
│ ├── app_mydomain_com.env
│ └── api_mydomain_com.env
├── logs/ # Application and container logs
│ ├── gordon.log
│ ├── proxy.log
│ └── containers/
└── secrets/ # Secrets (unsafe backend only)
Permissions
Gordon creates directories with secure permissions:
- Directories:
0700 (owner only)
- Files:
0600 (owner only)
Maximum Proxy Body Size
The max_proxy_body_size setting limits the size of request bodies that Gordon will forward to backend containers:
[server]
max_proxy_body_size = "512MB" # Default
Purpose: Prevents resource exhaustion attacks from extremely large uploads through the proxy.
Supported units: B, KB, MB, GB, TB (case-insensitive, decimal/1024-based)
Examples:
max_proxy_body_size = "100MB" # Stricter limit
max_proxy_body_size = "1GB" # Allow larger uploads
max_proxy_body_size = "0" # No limit (not recommended)
Behavior:
- When a request exceeds the limit, Gordon returns
413 Request Entity Too Large
- The limit is applied before the request reaches the backend container
- Uploads in progress are terminated when the limit is exceeded
Use cases:
- File upload services: increase to
1GB or higher
- CI/CD artifact uploads: adjust based on your largest artifacts
- Tight security: reduce to
100MB or lower
- Default (512MB): suitable for most applications
Warning: Setting this to 0 (no limit) allows unlimited upload sizes, which can lead to disk exhaustion and DoS vulnerabilities. Always set a reasonable limit for production deployments.
Maximum Registry Blob Chunk Size
The max_blob_chunk_size setting limits the size of a single blob upload request to the registry (PATCH/PUT under /v2/*/blobs/uploads/*):
[server]
max_blob_chunk_size = "95MB" # Default
Purpose: Prevents excessive memory usage during blob uploads while allowing large real-world image layers.
Supported units: B, KB, MB, GB, TB (case-insensitive, decimal/1024-based)
Examples:
max_blob_chunk_size = "256MB" # Stricter limit
max_blob_chunk_size = "1GB" # Allow larger layers
Behavior:
- When a blob chunk exceeds the limit, Gordon returns
413 Request Entity Too Large
- Gordon CLI uploads image layers in 50MB chunks by default, and this setting caps the maximum chunk accepted per request
- Keep this below Cloudflare's 100MB per-request limit when operating behind Cloudflare; the default (
95MB) is fine
- Increase it only if you expect larger direct registry uploads from other clients
Registry IP Allowlist
The registry_allowed_ips setting restricts registry access to specific IPs or IP ranges. Accepts both CIDR notation (100.64.0.0/10) and individual IPs (203.0.113.50). When set, only requests from listed addresses (plus localhost) can reach registry and auth endpoints. An empty list allows all traffic (default).
[server]
registry_allowed_ips = [
"100.64.0.0/10", # Tailscale CGNAT range
"203.0.113.50", # single IP (treated as /32)
]
Behavior:
- Single IPs are automatically converted to
/32 (IPv4) or /128 (IPv6)
- Denied requests receive
403 Forbidden
- Localhost (
127.0.0.0/8, ::1) is always allowed so Gordon can pull from its own registry
- Respects
trusted_proxies for accurate client IP extraction behind reverse proxies
- Applied before rate limiting and authentication
- Changes require a Gordon server restart; not picked up by config hot-reload
Use cases:
- Restrict registry to Tailscale network:
["100.64.0.0/10"]
- Restrict to private subnets:
["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
- Allow a specific CI server:
["100.64.0.0/10", "203.0.113.50"]
Via environment variable:
GORDON_SERVER_REGISTRY_ALLOWED_IPS=100.64.0.0/10
Proxy Origin IP Allowlist
The proxy_allowed_ips setting restricts which IPs can reach the proxy server. This prevents direct-to-origin attacks that bypass CDN protections (e.g. Cloudflare WAF, DDoS mitigation). When set, only connections from listed CIDRs (plus localhost) are accepted.
[server]
# Only accept proxy traffic from Cloudflare edge IPs
proxy_allowed_ips = [
"173.245.48.0/20", "103.21.244.0/22", "103.22.200.0/22",
"103.31.4.0/22", "141.101.64.0/18", "108.162.192.0/18",
"190.93.240.0/20", "188.114.96.0/20", "197.234.240.0/22",
"198.41.128.0/17", "162.158.0.0/15", "104.16.0.0/13",
"104.24.0.0/14", "172.64.0.0/13", "131.0.72.0/22",
]
Behavior:
- Checks the direct connection IP (
RemoteAddr), not X-Forwarded-For
- Localhost is always allowed
- Denied requests receive
403 Forbidden
- An empty list allows all traffic (default)
Important: Cloudflare publishes their IP ranges at cloudflare.com/ips. Keep your allowlist updated when Cloudflare adds new ranges.
Registry Listen Address
The registry_listen_address controls which interface the registry server binds to. By default it binds to all interfaces. Set to 127.0.0.1 to restrict registry access to localhost only, preventing containers from reaching the registry via the Docker bridge gateway.
[server]
registry_listen_address = "127.0.0.1" # Loopback only
HSTS
HSTS headers are sent automatically on the HTTPS listener (when r.TLS != nil). When Gordon runs behind a TLS-terminating proxy (Cloudflare, Tailscale) and only receives plain HTTP, HSTS is not sent — the edge proxy is expected to handle it.
Examples
Development Configuration
[server]
port = 8080
registry_port = 5000
gordon_domain = "gordon.local"
data_dir = "./dev-data"
Production Configuration
[server]
port = 8080
registry_port = 5000
gordon_domain = "gordon.company.com"
data_dir = "/var/lib/gordon"
Rootless Container Setup
[server]
port = 8080 # High port for rootless
registry_port = 5000
gordon_domain = "gordon.mydomain.com"
With firewall port forwarding:
sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
sudo firewall-cmd --reload
source
1# Server Configuration
2
3Core server settings for Gordon.
4
5## Configuration
6
7```toml
8[server]
9port = 8088 # HTTP proxy port
10registry_port = 5000 # Container registry port
11tls_port = 8443 # HTTPS listener port (0 = disabled)
12# tls_cert_file = "" # Optional: PEM certificate for static TLS
13# tls_key_file = "" # Optional: PEM key for static TLS
14# force_https_redirect = false # Redirect all HTTP traffic to HTTPS
15gordon_domain = "gordon.mydomain.com" # Gordon domain (required)
16# data_dir = "~/.gordon" # Data storage directory (default)
17```
18
19## Options
20
21| Option | Type | Default | Description |
22|--------|------|---------|-------------|
23| `port` | int | `8088` | HTTP proxy port for routing traffic to containers |
24| `registry_port` | int | `5000` | Docker registry port for image push/pull |
25| `tls_port` | int | `8443` | HTTPS listener port with internal CA. Set to `0` to disable TLS entirely |
26| `tls_cert_file` | string | `""` | Path to PEM certificate file. When set (with `tls_key_file`), this cert is served for matching SNI domains; unmatched domains fall through to the internal CA |
27| `tls_key_file` | string | `""` | Path to PEM private key file. Must be set together with `tls_cert_file` |
28| `force_https_redirect` | bool | `false` | Redirect all HTTP requests to the HTTPS port. For direct-access setups without a TLS-terminating proxy |
29| `gordon_domain` | string | **required** | Domain for Gordon (registry + admin API) |
30| `registry_domain` | string | - | Deprecated alias for `gordon_domain` |
31| `data_dir` | string | `~/.gordon` | Directory for registry data, logs, and env files |
32| `max_proxy_body_size` | string | `"512MB"` | Maximum request body size for proxied requests |
33| `max_blob_chunk_size` | string | `"95MB"` | Maximum request body size for a single registry blob upload chunk |
34| `registry_allowed_ips` | []string | `[]` | IPs or CIDR ranges allowed to access the registry (empty = allow all) |
35| `proxy_allowed_ips` | []string | `[]` | IPs or CIDR ranges allowed to reach the proxy (empty = allow all) |
36| `registry_listen_address` | string | `""` | Bind address for registry (empty = all interfaces) |
37
38## Port Configuration
39
40### Proxy Port
41
42The `port` setting controls where Gordon listens for HTTP traffic:
43
44```toml
45[server]
46port = 8080 # Use 8080 for rootless containers with port forwarding
47```
48
49For rootless containers, you'll typically use a high port and configure firewall port forwarding:
50
51```bash
52# Forward port 80 to 8080
53sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
54```
55
56### Internal CA and TLS
57
58Gordon includes an internal certificate authority that issues on-demand TLS certificates for proxied domains. The HTTPS listener is enabled by default on `tls_port` (8443).
59
60```toml
61[server]
62tls_port = 8443 # Default. Set to 0 to disable TLS entirely.
63```
64
65With TLS enabled:
66- Gordon runs an internal CA (root + intermediate) stored in `{data_dir}/pki/`
67- Leaf certificates are issued on-demand per domain (SNI-based) and cached in memory
68- The intermediate CA auto-renews before expiry
69- An onboarding page at `https://<gordon-host>:<tls_port>/ca` lets clients download the root CA certificate
70- The root CA is stable across restarts (generated once, persisted to disk)
71
72#### Custom certificates
73
74To use your own certificate (e.g. from Tailscale, Let's Encrypt, or a corporate CA) alongside the internal CA:
75
76```toml
77[server]
78tls_cert_file = "/etc/gordon/tls/cert.pem"
79tls_key_file = "/etc/gordon/tls/key.pem"
80```
81
82The static certificate is served for SNI-matching domains (including wildcards). All other domains get on-demand certs from the internal CA.
83
84#### HTTP to HTTPS redirect
85
86When clients connect directly (no Cloudflare or reverse proxy in front), enable `force_https_redirect` to redirect all HTTP traffic to the HTTPS port:
87
88```toml
89[server]
90force_https_redirect = true
91```
92
93When `proxy_allowed_ips` is configured, non-proxy clients are redirected automatically even without this flag — trusted proxy IPs pass through to serve Cloudflare-proxied traffic.
94
95#### Disabling TLS
96
97For setups where TLS is handled entirely by an external proxy (Cloudflare, nginx, etc.):
98
99```toml
100[server]
101tls_port = 0 # No HTTPS listener, no internal CA generated
102```
103
104#### Firewall port forwarding
105
106For rootless user services, forward 443 to the high port at the firewall:
107
108```bash
109# Forward 443 -> 8443
110sudo firewall-cmd --permanent --add-forward-port=port=443:proto=tcp:toport=8443
111sudo firewall-cmd --reload
112```
113
114With firewalld and Tailscale:
115
116```bash
117# Verify tailscale0 is in trusted zone
118sudo firewall-cmd --get-zone-of-interface=tailscale0
119
120# If needed, place tailscale0 in trusted
121sudo firewall-cmd --permanent --zone=trusted --add-interface=tailscale0
122sudo firewall-cmd --reload
123
124# Forward 443 -> 8443 permanently (IPv4 + IPv6)
125sudo firewall-cmd --permanent --zone=trusted --add-rich-rule='rule family=ipv4 forward-port port=443 protocol=tcp to-port=8443'
126sudo firewall-cmd --permanent --zone=trusted --add-rich-rule='rule family=ipv6 forward-port port=443 protocol=tcp to-port=8443'
127sudo firewall-cmd --reload
128```
129
130### Registry Port
131
132The `registry_port` setting controls where Gordon accepts image pushes:
133
134```toml
135[server]
136registry_port = 5000
137```
138
139Docker/Podman clients push to this port:
140
141```bash
142docker push registry.mydomain.com:5000/myapp:latest
143```
144
145If the registry is served over plain HTTP (no TLS), clients must be configured to allow insecure access. See [Troubleshooting: insecure registry](../reference/troubleshooting.md#server-gave-http-response-to-https-client) for Docker and Podman instructions.
146
147## Gordon Domain
148
149The `gordon_domain` is required and must match your DNS configuration:
150
151```toml
152[server]
153gordon_domain = "gordon.mydomain.com"
154```
155
156This domain is used for:
157- Docker login and image push/pull operations
158- Admin API access (`/admin/*` endpoints)
159- CLI remote targeting (`gordon routes --remote https://gordon.mydomain.com`)
160- Authentication endpoints (`/auth/*`)
161
162When requests arrive on the proxy port with this domain as the Host header, Gordon routes them to the backend services (registry and admin API).
163
164Security note:
165- Direct access to `/admin/*` on `registry_port` is blocked for non-loopback clients.
166- Admin API traffic should go through the main proxy listener (`server.port`/`server.tls_port`).
167
168> **Note:** `registry_domain` is supported as a deprecated alias for backwards compatibility.
169
170## Data Directory
171
172The `data_dir` setting controls where Gordon stores data:
173
174```toml
175[server]
176data_dir = "~/.gordon" # Default for user installations
177```
178
179### Directory Structure
180
181```
182~/.gordon/
183├── registry/ # Container images and manifests
184│ ├── blobs/
185│ └── manifests/
186├── env/ # Environment files per domain
187│ ├── app_mydomain_com.env
188│ └── api_mydomain_com.env
189├── logs/ # Application and container logs
190│ ├── gordon.log
191│ ├── proxy.log
192│ └── containers/
193└── secrets/ # Secrets (unsafe backend only)
194```
195
196### Permissions
197
198 Gordon creates directories with secure permissions:
199 - Directories: `0700` (owner only)
200 - Files: `0600` (owner only)
201
202 ## Maximum Proxy Body Size
203
204 The `max_proxy_body_size` setting limits the size of request bodies that Gordon will forward to backend containers:
205
206 ```toml
207 [server]
208 max_proxy_body_size = "512MB" # Default
209 ```
210
211 **Purpose:** Prevents resource exhaustion attacks from extremely large uploads through the proxy.
212
213 **Supported units:** B, KB, MB, GB, TB (case-insensitive, decimal/1024-based)
214
215 **Examples:**
216 ```toml
217 max_proxy_body_size = "100MB" # Stricter limit
218 max_proxy_body_size = "1GB" # Allow larger uploads
219 max_proxy_body_size = "0" # No limit (not recommended)
220 ```
221
222 **Behavior:**
223 - When a request exceeds the limit, Gordon returns `413 Request Entity Too Large`
224 - The limit is applied before the request reaches the backend container
225 - Uploads in progress are terminated when the limit is exceeded
226
227 **Use cases:**
228 - File upload services: increase to `1GB` or higher
229 - CI/CD artifact uploads: adjust based on your largest artifacts
230 - Tight security: reduce to `100MB` or lower
231 - Default (512MB): suitable for most applications
232
233 > **Warning:** Setting this to `0` (no limit) allows unlimited upload sizes, which can lead to disk exhaustion and DoS vulnerabilities. Always set a reasonable limit for production deployments.
234
235## Maximum Registry Blob Chunk Size
236
237The `max_blob_chunk_size` setting limits the size of a single blob upload request to the registry (`PATCH`/`PUT` under `/v2/*/blobs/uploads/*`):
238
239```toml
240[server]
241max_blob_chunk_size = "95MB" # Default
242```
243
244**Purpose:** Prevents excessive memory usage during blob uploads while allowing large real-world image layers.
245
246**Supported units:** B, KB, MB, GB, TB (case-insensitive, decimal/1024-based)
247
248**Examples:**
249
250```toml
251max_blob_chunk_size = "256MB" # Stricter limit
252max_blob_chunk_size = "1GB" # Allow larger layers
253```
254
255**Behavior:**
256- When a blob chunk exceeds the limit, Gordon returns `413 Request Entity Too Large`
257- Gordon CLI uploads image layers in 50MB chunks by default, and this setting caps the maximum chunk accepted per request
258- Keep this below Cloudflare's 100MB per-request limit when operating behind Cloudflare; the default (`95MB`) is fine
259- Increase it only if you expect larger direct registry uploads from other clients
260
261## Registry IP Allowlist
262
263The `registry_allowed_ips` setting restricts registry access to specific IPs or IP ranges. Accepts both CIDR notation (`100.64.0.0/10`) and individual IPs (`203.0.113.50`). When set, only requests from listed addresses (plus localhost) can reach registry and auth endpoints. An empty list allows all traffic (default).
264
265```toml
266[server]
267registry_allowed_ips = [
268 "100.64.0.0/10", # Tailscale CGNAT range
269 "203.0.113.50", # single IP (treated as /32)
270]
271```
272
273**Behavior:**
274- Single IPs are automatically converted to `/32` (IPv4) or `/128` (IPv6)
275- Denied requests receive `403 Forbidden`
276- Localhost (`127.0.0.0/8`, `::1`) is always allowed so Gordon can pull from its own registry
277- Respects `trusted_proxies` for accurate client IP extraction behind reverse proxies
278- Applied before rate limiting and authentication
279- Changes require a Gordon server restart; not picked up by config hot-reload
280
281**Use cases:**
282- Restrict registry to Tailscale network: `["100.64.0.0/10"]`
283- Restrict to private subnets: `["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]`
284- Allow a specific CI server: `["100.64.0.0/10", "203.0.113.50"]`
285
286Via environment variable:
287
288```bash
289GORDON_SERVER_REGISTRY_ALLOWED_IPS=100.64.0.0/10
290```
291
292## Proxy Origin IP Allowlist
293
294The `proxy_allowed_ips` setting restricts which IPs can reach the proxy server. This prevents direct-to-origin attacks that bypass CDN protections (e.g. Cloudflare WAF, DDoS mitigation). When set, only connections from listed CIDRs (plus localhost) are accepted.
295
296```toml
297[server]
298# Only accept proxy traffic from Cloudflare edge IPs
299proxy_allowed_ips = [
300 "173.245.48.0/20", "103.21.244.0/22", "103.22.200.0/22",
301 "103.31.4.0/22", "141.101.64.0/18", "108.162.192.0/18",
302 "190.93.240.0/20", "188.114.96.0/20", "197.234.240.0/22",
303 "198.41.128.0/17", "162.158.0.0/15", "104.16.0.0/13",
304 "104.24.0.0/14", "172.64.0.0/13", "131.0.72.0/22",
305]
306```
307
308**Behavior:**
309- Checks the direct connection IP (`RemoteAddr`), not `X-Forwarded-For`
310- Localhost is always allowed
311- Denied requests receive `403 Forbidden`
312- An empty list allows all traffic (default)
313
314**Important:** Cloudflare publishes their IP ranges at [cloudflare.com/ips](https://www.cloudflare.com/ips/). Keep your allowlist updated when Cloudflare adds new ranges.
315
316## Registry Listen Address
317
318The `registry_listen_address` controls which interface the registry server binds to. By default it binds to all interfaces. Set to `127.0.0.1` to restrict registry access to localhost only, preventing containers from reaching the registry via the Docker bridge gateway.
319
320```toml
321[server]
322registry_listen_address = "127.0.0.1" # Loopback only
323```
324
325## HSTS
326
327HSTS headers are sent automatically on the HTTPS listener (when `r.TLS != nil`). When Gordon runs behind a TLS-terminating proxy (Cloudflare, Tailscale) and only receives plain HTTP, HSTS is not sent — the edge proxy is expected to handle it.
328
329## Examples
330
331### Development Configuration
332
333```toml
334[server]
335port = 8080
336registry_port = 5000
337gordon_domain = "gordon.local"
338data_dir = "./dev-data"
339```
340
341### Production Configuration
342
343```toml
344[server]
345port = 8080
346registry_port = 5000
347gordon_domain = "gordon.company.com"
348data_dir = "/var/lib/gordon"
349```
350
351### Rootless Container Setup
352
353```toml
354[server]
355port = 8080 # High port for rootless
356registry_port = 5000
357gordon_domain = "gordon.mydomain.com"
358```
359
360With firewall port forwarding:
361```bash
362sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
363sudo firewall-cmd --reload
364```
365
366## Related
367
368- [Configuration Overview](./index.md)
369- [Installation Guide](../installation.md)
370- [Routes Configuration](./routes.md)