feat(server): add tls_port=0 opt-out and use unprivileged default ports
Allow disabling the HTTPS listener and internal CA entirely by setting tls_port=0, for setups where TLS is handled externally (Tailscale, Cloudflare, etc.). Change default ports from privileged (80/443) to unprivileged (8088/8443) to match the common rootless + firewalld port-forward pattern. Update all docs to reflect the new internal CA architecture and remove references to deprecated tls_enabled, tls_cert_file, tls_key_file, and force_hsts config fields.
- commit
- 63f113ebd15223096b2f9c5f4c96f9b59fcb9a55
- author
- brice · · 2026-03-30 18:38 UTC
- committer
- brice · · 2026-03-30 18:40 UTC
- parent
- 30b9539
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
10 files · +69 -71
M docs/cli/remotes.md +1 -4
| @@ -341,10 +341,7 @@ Configure Gordon to use them: | |||
| 341 | 341 | ||
| 342 | 342 | ```toml | |
| 343 | 343 | [server] | |
| 344 | - | tls_enabled = true | |
| 345 | - | tls_port = 443 | |
| 346 | - | tls_cert_file = "/etc/gordon/tls/cert.pem" | |
| 347 | - | tls_key_file = "/etc/gordon/tls/key.pem" | |
| 344 | + | tls_port = 8443 # Gordon's internal CA handles certificates automatically | |
| 348 | 345 | ``` | |
| 349 | 346 | ||
| 350 | 347 | `insecure_tls` only affects CLI -> Gordon admin HTTPS verification. It does not change runtime routing: Gordon reverse proxy and container routes can still serve wildcard app domains like `*.example.com`. | |
| @@ -341,10 +341,7 @@ Configure Gordon to use them: | |||||
| 341 | 341 | ||||
| 342 | ```toml | 342 | ```toml | ||
| 343 | [server] | 343 | [server] | ||
| 344 | - | tls_enabled = true | 344 | + | tls_port = 8443 # Gordon's internal CA handles certificates automatically |
| 345 | - | tls_port = 443 | |||
| 346 | - | tls_cert_file = "/etc/gordon/tls/cert.pem" | |||
| 347 | - | tls_key_file = "/etc/gordon/tls/key.pem" | |||
| 348 | ``` | 345 | ``` | ||
| 349 | 346 | ||||
| 350 | `insecure_tls` only affects CLI -> Gordon admin HTTPS verification. It does not change runtime routing: Gordon reverse proxy and container routes can still serve wildcard app domains like `*.example.com`. | 347 | `insecure_tls` only affects CLI -> Gordon admin HTTPS verification. It does not change runtime routing: Gordon reverse proxy and container routes can still serve wildcard app domains like `*.example.com`. | ||
M docs/config/index.md +2 -2
| @@ -30,7 +30,7 @@ For a complete list of all configuration options with their default values, see | |||
| 30 | 30 | ```toml | |
| 31 | 31 | # Server settings | |
| 32 | 32 | [server] | |
| 33 | - | port = 8080 # HTTP proxy port (default: 80) | |
| 33 | + | port = 8088 # HTTP proxy port (default: 8088) | |
| 34 | 34 | registry_port = 5000 # Registry port (default: 5000) | |
| 35 | 35 | gordon_domain = "gordon.mydomain.com" # Required: Gordon domain (registry + API) | |
| 36 | 36 | # data_dir = "~/.gordon" # Default for user installations | |
| @@ -167,7 +167,7 @@ keep_last = 3 | |||
| 167 | 167 | ||
| 168 | 168 | | Setting | Default | | |
| 169 | 169 | |---------|---------| | |
| 170 | - | | `server.port` | `80` | | |
| 170 | + | | `server.port` | `8088` | | |
| 171 | 171 | | `server.registry_port` | `5000` | | |
| 172 | 172 | | `server.data_dir` | `~/.gordon` | | |
| 173 | 173 | | `auth.enabled` | `true` | | |
| @@ -30,7 +30,7 @@ For a complete list of all configuration options with their default values, see | |||||
| 30 | ```toml | 30 | ```toml | ||
| 31 | # Server settings | 31 | # Server settings | ||
| 32 | [server] | 32 | [server] | ||
| 33 | - | port = 8080 # HTTP proxy port (default: 80) | 33 | + | port = 8088 # HTTP proxy port (default: 8088) |
| 34 | registry_port = 5000 # Registry port (default: 5000) | 34 | registry_port = 5000 # Registry port (default: 5000) | ||
| 35 | gordon_domain = "gordon.mydomain.com" # Required: Gordon domain (registry + API) | 35 | gordon_domain = "gordon.mydomain.com" # Required: Gordon domain (registry + API) | ||
| 36 | # data_dir = "~/.gordon" # Default for user installations | 36 | # data_dir = "~/.gordon" # Default for user installations | ||
| @@ -167,7 +167,7 @@ keep_last = 3 | |||||
| 167 | 167 | ||||
| 168 | | Setting | Default | | 168 | | Setting | Default | | ||
| 169 | |---------|---------| | 169 | |---------|---------| | ||
| 170 | - | | `server.port` | `80` | | 170 | + | | `server.port` | `8088` | |
| 171 | | `server.registry_port` | `5000` | | 171 | | `server.registry_port` | `5000` | | ||
| 172 | | `server.data_dir` | `~/.gordon` | | 172 | | `server.data_dir` | `~/.gordon` | | ||
| 173 | | `auth.enabled` | `true` | | 173 | | `auth.enabled` | `true` | | ||
M docs/config/rate-limiting.md +1 -1
| @@ -150,7 +150,7 @@ A burst of `100` with `per_ip_rps = 50` means a client can send 100 requests ins | |||
| 150 | 150 | ||
| 151 | 151 | **Critical for correct IP detection in production.** | |
| 152 | 152 | ||
| 153 | - | Gordon is a reverse proxy that routes requests to your containers. In production you can either terminate TLS directly in Gordon (`server.tls_enabled = true`) or place it behind a TLS-terminating proxy like Cloudflare, nginx, or a load balancer. | |
| 153 | + | Gordon is a reverse proxy that routes requests to your containers. In production you can either terminate TLS directly in Gordon (via its internal CA on `server.tls_port`) or place it behind a TLS-terminating proxy like Cloudflare, nginx, or a load balancer. | |
| 154 | 154 | ||
| 155 | 155 | ``` | |
| 156 | 156 | Internet → [Cloudflare/nginx] → Gordon → Containers | |
| @@ -150,7 +150,7 @@ A burst of `100` with `per_ip_rps = 50` means a client can send 100 requests ins | |||||
| 150 | 150 | ||||
| 151 | **Critical for correct IP detection in production.** | 151 | **Critical for correct IP detection in production.** | ||
| 152 | 152 | ||||
| 153 | - | Gordon is a reverse proxy that routes requests to your containers. In production you can either terminate TLS directly in Gordon (`server.tls_enabled = true`) or place it behind a TLS-terminating proxy like Cloudflare, nginx, or a load balancer. | 153 | + | Gordon is a reverse proxy that routes requests to your containers. In production you can either terminate TLS directly in Gordon (via its internal CA on `server.tls_port`) or place it behind a TLS-terminating proxy like Cloudflare, nginx, or a load balancer. |
| 154 | 154 | ||||
| 155 | ``` | 155 | ``` | ||
| 156 | Internet → [Cloudflare/nginx] → Gordon → Containers | 156 | Internet → [Cloudflare/nginx] → Gordon → Containers | ||
M docs/config/reference.md +4 -12
| @@ -9,19 +9,15 @@ Complete configuration reference with all options and their default values. | |||
| 9 | 9 | # SERVER | |
| 10 | 10 | # ============================================================================= | |
| 11 | 11 | [server] | |
| 12 | - | port = 80 # HTTP proxy port | |
| 12 | + | port = 8088 # HTTP proxy port | |
| 13 | 13 | registry_port = 5000 # Container registry port | |
| 14 | - | tls_enabled = false # Enable native HTTPS listener | |
| 15 | - | tls_port = 443 # HTTPS proxy port when enabled | |
| 16 | - | tls_cert_file = "" # PEM cert path (auto-generated if empty and TLS enabled) | |
| 17 | - | tls_key_file = "" # PEM key path (auto-generated if empty and TLS enabled) | |
| 14 | + | tls_port = 8443 # HTTPS proxy port (0 = disabled, no internal CA) | |
| 18 | 15 | gordon_domain = "" # Required: Gordon domain (registry + API) | |
| 19 | 16 | data_dir = "~/.gordon" # Data directory (varies by install type) | |
| 20 | 17 | max_blob_chunk_size = "512MB" # Max size per registry blob upload chunk | |
| 21 | 18 | registry_allowed_ips = [] # IPs or CIDR ranges allowed to access the registry (empty = allow all) | |
| 22 | 19 | proxy_allowed_ips = [] # IPs or CIDR ranges allowed to reach the proxy (empty = allow all, e.g. Cloudflare IPs) | |
| 23 | 20 | registry_listen_address = "" # Bind address for registry (empty = all interfaces, "127.0.0.1" = loopback only) | |
| 24 | - | force_hsts = false # Always send HSTS header (enable when behind TLS-terminating proxy) | |
| 25 | 21 | ||
| 26 | 22 | # ============================================================================= | |
| 27 | 23 | # AUTHENTICATION (required - Gordon won't start without credentials configured) | |
| @@ -170,19 +166,15 @@ keep_last = 3 # Keep N newest tags per repository | |||
| 170 | 166 | ||
| 171 | 167 | | Setting | Default | Description | | |
| 172 | 168 | |---------|---------|-------------| | |
| 173 | - | | `server.port` | `80` | HTTP proxy port | | |
| 169 | + | | `server.port` | `8088` | HTTP proxy port | | |
| 174 | 170 | | `server.registry_port` | `5000` | Container registry port | | |
| 175 | - | | `server.tls_enabled` | `false` | Enable native HTTPS listener | | |
| 176 | - | | `server.tls_port` | `443` | HTTPS listener port | | |
| 177 | - | | `server.tls_cert_file` | `""` | TLS cert path (auto-generated when empty) | | |
| 178 | - | | `server.tls_key_file` | `""` | TLS key path (auto-generated when empty) | | |
| 171 | + | | `server.tls_port` | `8443` | HTTPS listener port (0 = disabled) | | |
| 179 | 172 | | `server.gordon_domain` | `""` | **Required** - Gordon domain | | |
| 180 | 173 | | `server.data_dir` | `~/.gordon` | Data directory | | |
| 181 | 174 | | `server.max_blob_chunk_size` | `"512MB"` | Max size per registry blob upload chunk | | |
| 182 | 175 | | `server.registry_allowed_ips` | `[]` | IPs or CIDR ranges allowed to access the registry (empty = allow all) | | |
| 183 | 176 | | `server.proxy_allowed_ips` | `[]` | IPs or CIDR ranges allowed to reach the proxy (empty = allow all) | | |
| 184 | 177 | | `server.registry_listen_address` | `""` | Bind address for registry (empty = all interfaces) | | |
| 185 | - | | `server.force_hsts` | `false` | Always send HSTS header (for TLS-terminating proxy setups) | | |
| 186 | 178 | | `auth.enabled` | `true` | Enable authentication; when `false`, run local-only mode (loopback-only `/v2/*`, `/admin/*` disabled) | | |
| 187 | 179 | | `auth.secrets_backend` | `"unsafe"` | Secrets storage | | |
| 188 | 180 | | `auth.token_expiry` | `"720h"` | 30 days | | |
| @@ -9,19 +9,15 @@ Complete configuration reference with all options and their default values. | |||||
| 9 | # SERVER | 9 | # SERVER | ||
| 10 | # ============================================================================= | 10 | # ============================================================================= | ||
| 11 | [server] | 11 | [server] | ||
| 12 | - | port = 80 # HTTP proxy port | 12 | + | port = 8088 # HTTP proxy port |
| 13 | registry_port = 5000 # Container registry port | 13 | registry_port = 5000 # Container registry port | ||
| 14 | - | tls_enabled = false # Enable native HTTPS listener | 14 | + | tls_port = 8443 # HTTPS proxy port (0 = disabled, no internal CA) |
| 15 | - | tls_port = 443 # HTTPS proxy port when enabled | |||
| 16 | - | tls_cert_file = "" # PEM cert path (auto-generated if empty and TLS enabled) | |||
| 17 | - | tls_key_file = "" # PEM key path (auto-generated if empty and TLS enabled) | |||
| 18 | gordon_domain = "" # Required: Gordon domain (registry + API) | 15 | gordon_domain = "" # Required: Gordon domain (registry + API) | ||
| 19 | data_dir = "~/.gordon" # Data directory (varies by install type) | 16 | data_dir = "~/.gordon" # Data directory (varies by install type) | ||
| 20 | max_blob_chunk_size = "512MB" # Max size per registry blob upload chunk | 17 | max_blob_chunk_size = "512MB" # Max size per registry blob upload chunk | ||
| 21 | registry_allowed_ips = [] # IPs or CIDR ranges allowed to access the registry (empty = allow all) | 18 | registry_allowed_ips = [] # IPs or CIDR ranges allowed to access the registry (empty = allow all) | ||
| 22 | proxy_allowed_ips = [] # IPs or CIDR ranges allowed to reach the proxy (empty = allow all, e.g. Cloudflare IPs) | 19 | proxy_allowed_ips = [] # IPs or CIDR ranges allowed to reach the proxy (empty = allow all, e.g. Cloudflare IPs) | ||
| 23 | registry_listen_address = "" # Bind address for registry (empty = all interfaces, "127.0.0.1" = loopback only) | 20 | registry_listen_address = "" # Bind address for registry (empty = all interfaces, "127.0.0.1" = loopback only) | ||
| 24 | - | force_hsts = false # Always send HSTS header (enable when behind TLS-terminating proxy) | |||
| 25 | 21 | ||||
| 26 | # ============================================================================= | 22 | # ============================================================================= | ||
| 27 | # AUTHENTICATION (required - Gordon won't start without credentials configured) | 23 | # AUTHENTICATION (required - Gordon won't start without credentials configured) | ||
| @@ -170,19 +166,15 @@ keep_last = 3 # Keep N newest tags per repository | |||||
| 170 | 166 | ||||
| 171 | | Setting | Default | Description | | 167 | | Setting | Default | Description | | ||
| 172 | |---------|---------|-------------| | 168 | |---------|---------|-------------| | ||
| 173 | - | | `server.port` | `80` | HTTP proxy port | | 169 | + | | `server.port` | `8088` | HTTP proxy port | |
| 174 | | `server.registry_port` | `5000` | Container registry port | | 170 | | `server.registry_port` | `5000` | Container registry port | | ||
| 175 | - | | `server.tls_enabled` | `false` | Enable native HTTPS listener | | 171 | + | | `server.tls_port` | `8443` | HTTPS listener port (0 = disabled) | |
| 176 | - | | `server.tls_port` | `443` | HTTPS listener port | | |||
| 177 | - | | `server.tls_cert_file` | `""` | TLS cert path (auto-generated when empty) | | |||
| 178 | - | | `server.tls_key_file` | `""` | TLS key path (auto-generated when empty) | | |||
| 179 | | `server.gordon_domain` | `""` | **Required** - Gordon domain | | 172 | | `server.gordon_domain` | `""` | **Required** - Gordon domain | | ||
| 180 | | `server.data_dir` | `~/.gordon` | Data directory | | 173 | | `server.data_dir` | `~/.gordon` | Data directory | | ||
| 181 | | `server.max_blob_chunk_size` | `"512MB"` | Max size per registry blob upload chunk | | 174 | | `server.max_blob_chunk_size` | `"512MB"` | Max size per registry blob upload chunk | | ||
| 182 | | `server.registry_allowed_ips` | `[]` | IPs or CIDR ranges allowed to access the registry (empty = allow all) | | 175 | | `server.registry_allowed_ips` | `[]` | IPs or CIDR ranges allowed to access the registry (empty = allow all) | | ||
| 183 | | `server.proxy_allowed_ips` | `[]` | IPs or CIDR ranges allowed to reach the proxy (empty = allow all) | | 176 | | `server.proxy_allowed_ips` | `[]` | IPs or CIDR ranges allowed to reach the proxy (empty = allow all) | | ||
| 184 | | `server.registry_listen_address` | `""` | Bind address for registry (empty = all interfaces) | | 177 | | `server.registry_listen_address` | `""` | Bind address for registry (empty = all interfaces) | | ||
| 185 | - | | `server.force_hsts` | `false` | Always send HSTS header (for TLS-terminating proxy setups) | | |||
| 186 | | `auth.enabled` | `true` | Enable authentication; when `false`, run local-only mode (loopback-only `/v2/*`, `/admin/*` disabled) | | 178 | | `auth.enabled` | `true` | Enable authentication; when `false`, run local-only mode (loopback-only `/v2/*`, `/admin/*` disabled) | | ||
| 187 | | `auth.secrets_backend` | `"unsafe"` | Secrets storage | | 179 | | `auth.secrets_backend` | `"unsafe"` | Secrets storage | | ||
| 188 | | `auth.token_expiry` | `"720h"` | 30 days | | 180 | | `auth.token_expiry` | `"720h"` | 30 days | | ||
M docs/config/server.md +28 -31
| @@ -6,12 +6,9 @@ Core server settings for Gordon. | |||
| 6 | 6 | ||
| 7 | 7 | ```toml | |
| 8 | 8 | [server] | |
| 9 | - | port = 8080 # HTTP proxy port | |
| 9 | + | port = 8088 # HTTP proxy port | |
| 10 | 10 | registry_port = 5000 # Container registry port | |
| 11 | - | tls_enabled = false # Enable native TLS listener | |
| 12 | - | tls_port = 443 # HTTPS listener port | |
| 13 | - | tls_cert_file = "" # PEM certificate file (required when TLS enabled) | |
| 14 | - | tls_key_file = "" # PEM key file (required when TLS enabled) | |
| 11 | + | tls_port = 8443 # HTTPS listener port (0 = disabled) | |
| 15 | 12 | gordon_domain = "gordon.mydomain.com" # Gordon domain (required) | |
| 16 | 13 | # data_dir = "~/.gordon" # Data storage directory (default) | |
| 17 | 14 | ``` | |
| @@ -20,12 +17,9 @@ gordon_domain = "gordon.mydomain.com" # Gordon domain (required) | |||
| 20 | 17 | ||
| 21 | 18 | | Option | Type | Default | Description | | |
| 22 | 19 | |--------|------|---------|-------------| | |
| 23 | - | | `port` | int | `80` | HTTP proxy port for routing traffic to containers | | |
| 20 | + | | `port` | int | `8088` | HTTP proxy port for routing traffic to containers | | |
| 24 | 21 | | `registry_port` | int | `5000` | Docker registry port for image push/pull | | |
| 25 | - | | `tls_enabled` | bool | `false` | Enable native HTTPS listener for proxy traffic | | |
| 26 | - | | `tls_port` | int | `443` | HTTPS listener port when `tls_enabled` is true | | |
| 27 | - | | `tls_cert_file` | string | `""` | Path to PEM certificate file | | |
| 28 | - | | `tls_key_file` | string | `""` | Path to PEM private key file | | |
| 22 | + | | `tls_port` | int | `8443` | HTTPS listener port with internal CA. Set to `0` to disable TLS entirely | | |
| 29 | 23 | | `gordon_domain` | string | **required** | Domain for Gordon (registry + admin API) | | |
| 30 | 24 | | `registry_domain` | string | - | Deprecated alias for `gordon_domain` | | |
| 31 | 25 | | `data_dir` | string | `~/.gordon` | Directory for registry data, logs, and env files | | |
| @@ -34,7 +28,6 @@ gordon_domain = "gordon.mydomain.com" # Gordon domain (required) | |||
| 34 | 28 | | `registry_allowed_ips` | []string | `[]` | IPs or CIDR ranges allowed to access the registry (empty = allow all) | | |
| 35 | 29 | | `proxy_allowed_ips` | []string | `[]` | IPs or CIDR ranges allowed to reach the proxy (empty = allow all) | | |
| 36 | 30 | | `registry_listen_address` | string | `""` | Bind address for registry (empty = all interfaces) | | |
| 37 | - | | `force_hsts` | bool | `false` | Always send HSTS header (for TLS-terminating proxy setups) | | |
| 38 | 31 | ||
| 39 | 32 | ## Port Configuration | |
| 40 | 33 | ||
| @@ -54,30 +47,39 @@ For rootless containers, you'll typically use a high port and configure firewall | |||
| 54 | 47 | sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080 | |
| 55 | 48 | ``` | |
| 56 | 49 | ||
| 57 | - | ### Native TLS Listener | |
| 50 | + | ### Internal CA and TLS | |
| 58 | 51 | ||
| 59 | - | Enable native HTTPS directly in Gordon: | |
| 52 | + | 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). | |
| 60 | 53 | ||
| 61 | 54 | ```toml | |
| 62 | 55 | [server] | |
| 63 | - | tls_enabled = true | |
| 64 | - | tls_port = 443 | |
| 65 | - | tls_cert_file = "/etc/gordon/certs/fullchain.pem" | |
| 66 | - | tls_key_file = "/etc/gordon/certs/privkey.pem" | |
| 56 | + | tls_port = 8443 # Default. Set to 0 to disable TLS entirely. | |
| 67 | 57 | ``` | |
| 68 | 58 | ||
| 69 | 59 | With TLS enabled: | |
| 70 | - | - Gordon terminates HTTPS on `tls_port` | |
| 71 | - | - Host-based routing still works (apps, `/v2/*`, `/auth/*`, `/admin/*`) | |
| 72 | - | - `port` remains available for plain HTTP unless you restrict it externally | |
| 73 | - | - If `tls_cert_file`/`tls_key_file` are empty, Gordon auto-generates a self-signed pair in `{data_dir}/tls/` | |
| 60 | + | - Gordon runs an internal CA (root + intermediate) stored in `{data_dir}/pki/` | |
| 61 | + | - Leaf certificates are issued on-demand per domain (SNI-based) and cached in memory | |
| 62 | + | - The intermediate CA auto-renews before expiry | |
| 63 | + | - An onboarding page at `http://{host}/ca` lets clients download the root CA certificate | |
| 64 | + | - The root CA is stable across restarts (generated once, persisted to disk) | |
| 74 | 65 | ||
| 75 | - | For rootless user services, do not bind directly to `443`. Use an unprivileged TLS port (for example `8443`) and forward `443` to it at the firewall or edge proxy. | |
| 66 | + | #### Disabling TLS | |
| 67 | + | ||
| 68 | + | For setups where TLS is handled externally (Tailscale, Cloudflare, etc.): | |
| 76 | 69 | ||
| 77 | 70 | ```toml | |
| 78 | 71 | [server] | |
| 79 | - | tls_enabled = true | |
| 80 | - | tls_port = 8443 | |
| 72 | + | tls_port = 0 # No HTTPS listener, no internal CA generated | |
| 73 | + | ``` | |
| 74 | + | ||
| 75 | + | #### Firewall port forwarding | |
| 76 | + | ||
| 77 | + | For rootless user services, forward 443 to the high port at the firewall: | |
| 78 | + | ||
| 79 | + | ```bash | |
| 80 | + | # Forward 443 -> 8443 | |
| 81 | + | sudo firewall-cmd --permanent --add-forward-port=port=443:proto=tcp:toport=8443 | |
| 82 | + | sudo firewall-cmd --reload | |
| 81 | 83 | ``` | |
| 82 | 84 | ||
| 83 | 85 | With firewalld and Tailscale: | |
| @@ -291,14 +293,9 @@ The `registry_listen_address` controls which interface the registry server binds | |||
| 291 | 293 | registry_listen_address = "127.0.0.1" # Loopback only | |
| 292 | 294 | ``` | |
| 293 | 295 | ||
| 294 | - | ## Force HSTS | |
| 295 | - | ||
| 296 | - | When Gordon runs behind a TLS-terminating proxy (e.g. Cloudflare), `r.TLS` is nil so the HSTS header is not sent by default. Enable `force_hsts` to always include the `Strict-Transport-Security` header. | |
| 296 | + | ## HSTS | |
| 297 | 297 | ||
| 298 | - | ```toml | |
| 299 | - | [server] | |
| 300 | - | force_hsts = true | |
| 301 | - | ``` | |
| 298 | + | 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. | |
| 302 | 299 | ||
| 303 | 300 | ## Examples | |
| 304 | 301 | ||
| @@ -6,12 +6,9 @@ Core server settings for Gordon. | |||||
| 6 | 6 | ||||
| 7 | ```toml | 7 | ```toml | ||
| 8 | [server] | 8 | [server] | ||
| 9 | - | port = 8080 # HTTP proxy port | 9 | + | port = 8088 # HTTP proxy port |
| 10 | registry_port = 5000 # Container registry port | 10 | registry_port = 5000 # Container registry port | ||
| 11 | - | tls_enabled = false # Enable native TLS listener | 11 | + | tls_port = 8443 # HTTPS listener port (0 = disabled) |
| 12 | - | tls_port = 443 # HTTPS listener port | |||
| 13 | - | tls_cert_file = "" # PEM certificate file (required when TLS enabled) | |||
| 14 | - | tls_key_file = "" # PEM key file (required when TLS enabled) | |||
| 15 | gordon_domain = "gordon.mydomain.com" # Gordon domain (required) | 12 | gordon_domain = "gordon.mydomain.com" # Gordon domain (required) | ||
| 16 | # data_dir = "~/.gordon" # Data storage directory (default) | 13 | # data_dir = "~/.gordon" # Data storage directory (default) | ||
| 17 | ``` | 14 | ``` | ||
| @@ -20,12 +17,9 @@ gordon_domain = "gordon.mydomain.com" # Gordon domain (required) | |||||
| 20 | 17 | ||||
| 21 | | Option | Type | Default | Description | | 18 | | Option | Type | Default | Description | | ||
| 22 | |--------|------|---------|-------------| | 19 | |--------|------|---------|-------------| | ||
| 23 | - | | `port` | int | `80` | HTTP proxy port for routing traffic to containers | | 20 | + | | `port` | int | `8088` | HTTP proxy port for routing traffic to containers | |
| 24 | | `registry_port` | int | `5000` | Docker registry port for image push/pull | | 21 | | `registry_port` | int | `5000` | Docker registry port for image push/pull | | ||
| 25 | - | | `tls_enabled` | bool | `false` | Enable native HTTPS listener for proxy traffic | | 22 | + | | `tls_port` | int | `8443` | HTTPS listener port with internal CA. Set to `0` to disable TLS entirely | |
| 26 | - | | `tls_port` | int | `443` | HTTPS listener port when `tls_enabled` is true | | |||
| 27 | - | | `tls_cert_file` | string | `""` | Path to PEM certificate file | | |||
| 28 | - | | `tls_key_file` | string | `""` | Path to PEM private key file | | |||
| 29 | | `gordon_domain` | string | **required** | Domain for Gordon (registry + admin API) | | 23 | | `gordon_domain` | string | **required** | Domain for Gordon (registry + admin API) | | ||
| 30 | | `registry_domain` | string | - | Deprecated alias for `gordon_domain` | | 24 | | `registry_domain` | string | - | Deprecated alias for `gordon_domain` | | ||
| 31 | | `data_dir` | string | `~/.gordon` | Directory for registry data, logs, and env files | | 25 | | `data_dir` | string | `~/.gordon` | Directory for registry data, logs, and env files | | ||
| @@ -34,7 +28,6 @@ gordon_domain = "gordon.mydomain.com" # Gordon domain (required) | |||||
| 34 | | `registry_allowed_ips` | []string | `[]` | IPs or CIDR ranges allowed to access the registry (empty = allow all) | | 28 | | `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) | | 29 | | `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) | | 30 | | `registry_listen_address` | string | `""` | Bind address for registry (empty = all interfaces) | | ||
| 37 | - | | `force_hsts` | bool | `false` | Always send HSTS header (for TLS-terminating proxy setups) | | |||
| 38 | 31 | ||||
| 39 | ## Port Configuration | 32 | ## Port Configuration | ||
| 40 | 33 | ||||
| @@ -54,30 +47,39 @@ For rootless containers, you'll typically use a high port and configure firewall | |||||
| 54 | sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080 | 47 | sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080 | ||
| 55 | ``` | 48 | ``` | ||
| 56 | 49 | ||||
| 57 | - | ### Native TLS Listener | 50 | + | ### Internal CA and TLS |
| 58 | 51 | ||||
| 59 | - | Enable native HTTPS directly in Gordon: | 52 | + | 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). |
| 60 | 53 | ||||
| 61 | ```toml | 54 | ```toml | ||
| 62 | [server] | 55 | [server] | ||
| 63 | - | tls_enabled = true | 56 | + | tls_port = 8443 # Default. Set to 0 to disable TLS entirely. |
| 64 | - | tls_port = 443 | |||
| 65 | - | tls_cert_file = "/etc/gordon/certs/fullchain.pem" | |||
| 66 | - | tls_key_file = "/etc/gordon/certs/privkey.pem" | |||
| 67 | ``` | 57 | ``` | ||
| 68 | 58 | ||||
| 69 | With TLS enabled: | 59 | With TLS enabled: | ||
| 70 | - | - Gordon terminates HTTPS on `tls_port` | 60 | + | - Gordon runs an internal CA (root + intermediate) stored in `{data_dir}/pki/` |
| 71 | - | - Host-based routing still works (apps, `/v2/*`, `/auth/*`, `/admin/*`) | 61 | + | - Leaf certificates are issued on-demand per domain (SNI-based) and cached in memory |
| 72 | - | - `port` remains available for plain HTTP unless you restrict it externally | 62 | + | - The intermediate CA auto-renews before expiry |
| 73 | - | - If `tls_cert_file`/`tls_key_file` are empty, Gordon auto-generates a self-signed pair in `{data_dir}/tls/` | 63 | + | - An onboarding page at `http://{host}/ca` lets clients download the root CA certificate |
| 64 | + | - The root CA is stable across restarts (generated once, persisted to disk) | |||
| 74 | 65 | ||||
| 75 | - | For rootless user services, do not bind directly to `443`. Use an unprivileged TLS port (for example `8443`) and forward `443` to it at the firewall or edge proxy. | 66 | + | #### Disabling TLS |
| 67 | + | ||||
| 68 | + | For setups where TLS is handled externally (Tailscale, Cloudflare, etc.): | |||
| 76 | 69 | ||||
| 77 | ```toml | 70 | ```toml | ||
| 78 | [server] | 71 | [server] | ||
| 79 | - | tls_enabled = true | 72 | + | tls_port = 0 # No HTTPS listener, no internal CA generated |
| 80 | - | tls_port = 8443 | 73 | + | ``` |
| 74 | + | ||||
| 75 | + | #### Firewall port forwarding | |||
| 76 | + | ||||
| 77 | + | For rootless user services, forward 443 to the high port at the firewall: | |||
| 78 | + | ||||
| 79 | + | ```bash | |||
| 80 | + | # Forward 443 -> 8443 | |||
| 81 | + | sudo firewall-cmd --permanent --add-forward-port=port=443:proto=tcp:toport=8443 | |||
| 82 | + | sudo firewall-cmd --reload | |||
| 81 | ``` | 83 | ``` | ||
| 82 | 84 | ||||
| 83 | With firewalld and Tailscale: | 85 | With firewalld and Tailscale: | ||
| @@ -291,14 +293,9 @@ The `registry_listen_address` controls which interface the registry server binds | |||||
| 291 | registry_listen_address = "127.0.0.1" # Loopback only | 293 | registry_listen_address = "127.0.0.1" # Loopback only | ||
| 292 | ``` | 294 | ``` | ||
| 293 | 295 | ||||
| 294 | - | ## Force HSTS | 296 | + | ## HSTS |
| 295 | - | ||||
| 296 | - | When Gordon runs behind a TLS-terminating proxy (e.g. Cloudflare), `r.TLS` is nil so the HSTS header is not sent by default. Enable `force_hsts` to always include the `Strict-Transport-Security` header. | |||
| 297 | 297 | ||||
| 298 | - | ```toml | 298 | + | 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. |
| 299 | - | [server] | |||
| 300 | - | force_hsts = true | |||
| 301 | - | ``` | |||
| 302 | 299 | ||||
| 303 | ## Examples | 300 | ## Examples | ||
| 304 | 301 | ||||
M docs/getting-started.md +1 -1
| @@ -6,7 +6,7 @@ Deploy your first app with Gordon in under 5 minutes. | |||
| 6 | 6 | ||
| 7 | 7 | - A Linux VPS with Docker or Podman installed | |
| 8 | 8 | - A domain pointing to your VPS (DNS A record) | |
| 9 | - | - HTTPS setup: Cloudflare proxy **or** native TLS in Gordon (`server.tls_enabled = true`) | |
| 9 | + | - HTTPS setup: Cloudflare proxy, Tailscale, or Gordon's internal CA (`server.tls_port = 8443`) | |
| 10 | 10 | - [pass](https://www.passwordstore.org/) (password manager) with GPG key initialized | |
| 11 | 11 | ||
| 12 | 12 | ## 1. Install Gordon | |
| @@ -6,7 +6,7 @@ Deploy your first app with Gordon in under 5 minutes. | |||||
| 6 | 6 | ||||
| 7 | - A Linux VPS with Docker or Podman installed | 7 | - A Linux VPS with Docker or Podman installed | ||
| 8 | - A domain pointing to your VPS (DNS A record) | 8 | - A domain pointing to your VPS (DNS A record) | ||
| 9 | - | - HTTPS setup: Cloudflare proxy **or** native TLS in Gordon (`server.tls_enabled = true`) | 9 | + | - HTTPS setup: Cloudflare proxy, Tailscale, or Gordon's internal CA (`server.tls_port = 8443`) |
| 10 | - [pass](https://www.passwordstore.org/) (password manager) with GPG key initialized | 10 | - [pass](https://www.passwordstore.org/) (password manager) with GPG key initialized | ||
| 11 | 11 | ||||
| 12 | ## 1. Install Gordon | 12 | ## 1. Install Gordon | ||
M docs/index.md +1 -1
| @@ -80,7 +80,7 @@ Gordon runs on your VPS and provides: | |||
| 80 | 80 | - Domain pointing to your server | |
| 81 | 81 | - Cloudflare account for HTTPS (free tier works) | |
| 82 | 82 | ||
| 83 | - | > **Note:** Gordon can run behind Cloudflare/nginx, or terminate TLS directly when `server.tls_enabled = true`. | |
| 83 | + | > **Note:** Gordon can run behind Cloudflare/nginx, or terminate TLS directly via its internal CA (enabled by default on `server.tls_port`). Set `tls_port = 0` to disable. | |
| 84 | 84 | ||
| 85 | 85 | ## Related | |
| 86 | 86 | ||
| @@ -80,7 +80,7 @@ Gordon runs on your VPS and provides: | |||||
| 80 | - Domain pointing to your server | 80 | - Domain pointing to your server | ||
| 81 | - Cloudflare account for HTTPS (free tier works) | 81 | - Cloudflare account for HTTPS (free tier works) | ||
| 82 | 82 | ||||
| 83 | - | > **Note:** Gordon can run behind Cloudflare/nginx, or terminate TLS directly when `server.tls_enabled = true`. | 83 | + | > **Note:** Gordon can run behind Cloudflare/nginx, or terminate TLS directly via its internal CA (enabled by default on `server.tls_port`). Set `tls_port = 0` to disable. |
| 84 | 84 | ||||
| 85 | ## Related | 85 | ## Related | ||
| 86 | 86 | ||||
M internal/adapters/in/cli/local.go +1 -1
| @@ -46,7 +46,7 @@ func (l *LocalServices) GetDataDir() string { | |||
| 46 | 46 | func GetLocalServices(configPath string) (*LocalServices, error) { | |
| 47 | 47 | // Set up viper with defaults | |
| 48 | 48 | v := viper.New() | |
| 49 | - | v.SetDefault("server.port", 80) | |
| 49 | + | v.SetDefault("server.port", 8088) | |
| 50 | 50 | v.SetDefault("server.registry_port", 5000) | |
| 51 | 51 | v.SetDefault("server.data_dir", app.DefaultDataDir()) | |
| 52 | 52 | ||
| @@ -46,7 +46,7 @@ func (l *LocalServices) GetDataDir() string { | |||||
| 46 | func GetLocalServices(configPath string) (*LocalServices, error) { | 46 | func GetLocalServices(configPath string) (*LocalServices, error) { | ||
| 47 | // Set up viper with defaults | 47 | // Set up viper with defaults | ||
| 48 | v := viper.New() | 48 | v := viper.New() | ||
| 49 | - | v.SetDefault("server.port", 80) | 49 | + | v.SetDefault("server.port", 8088) |
| 50 | v.SetDefault("server.registry_port", 5000) | 50 | v.SetDefault("server.registry_port", 5000) | ||
| 51 | v.SetDefault("server.data_dir", app.DefaultDataDir()) | 51 | v.SetDefault("server.data_dir", app.DefaultDataDir()) | ||
| 52 | 52 | ||||
M internal/app/run.go +28 -16
| @@ -375,13 +375,17 @@ func createServices(ctx context.Context, v *viper.Viper, cfg Config, log zerowra | |||
| 375 | 375 | return nil, log.WrapErr(err, "failed to load configuration") | |
| 376 | 376 | } | |
| 377 | 377 | ||
| 378 | - | // Create PKI (internal CA) | |
| 379 | - | caAdapter, err := pkiadapter.NewCA(resolveDataDir(cfg.Server.DataDir), log) | |
| 380 | - | if err != nil { | |
| 381 | - | return nil, log.WrapErr(err, "failed to initialize internal CA") | |
| 378 | + | // Create PKI (internal CA) — disabled when tls_port is 0. | |
| 379 | + | if cfg.Server.TLSPort != 0 { | |
| 380 | + | caAdapter, err := pkiadapter.NewCA(resolveDataDir(cfg.Server.DataDir), log) | |
| 381 | + | if err != nil { | |
| 382 | + | return nil, log.WrapErr(err, "failed to initialize internal CA") | |
| 383 | + | } | |
| 384 | + | svc.caAdapter = caAdapter | |
| 385 | + | svc.pkiSvc = pkiusecase.NewService(ctx, caAdapter, svc.configSvc, log) | |
| 386 | + | } else { | |
| 387 | + | log.Info().Msg("internal CA disabled (server.tls_port=0)") | |
| 382 | 388 | } | |
| 383 | - | svc.caAdapter = caAdapter | |
| 384 | - | svc.pkiSvc = pkiusecase.NewService(ctx, caAdapter, svc.configSvc, log) | |
| 385 | 389 | ||
| 386 | 390 | var backend domain.SecretsBackend | |
| 387 | 391 | var passStore *domainsecrets.PassStore | |
| @@ -1895,15 +1899,19 @@ func runServers(ctx context.Context, v *viper.Viper, cfg Config, svc *services, | |||
| 1895 | 1899 | if err := waitForServerReady(proxyReady, errChan); err != nil { | |
| 1896 | 1900 | return err | |
| 1897 | 1901 | } | |
| 1898 | - | if err := waitForServerReady(tlsReady, errChan); err != nil { | |
| 1899 | - | return err | |
| 1902 | + | if tlsReady != nil { | |
| 1903 | + | if err := waitForServerReady(tlsReady, errChan); err != nil { | |
| 1904 | + | return err | |
| 1905 | + | } | |
| 1900 | 1906 | } | |
| 1901 | 1907 | ||
| 1902 | - | log.Info(). | |
| 1908 | + | logEvent := log.Info(). | |
| 1903 | 1909 | Int("proxy_port", cfg.Server.Port). | |
| 1904 | - | Int("tls_port", cfg.Server.TLSPort). | |
| 1905 | - | Int("registry_port", cfg.Server.RegistryPort). | |
| 1906 | - | Msg("Gordon is running") | |
| 1910 | + | Int("registry_port", cfg.Server.RegistryPort) | |
| 1911 | + | if cfg.Server.TLSPort != 0 { | |
| 1912 | + | logEvent = logEvent.Int("tls_port", cfg.Server.TLSPort) | |
| 1913 | + | } | |
| 1914 | + | logEvent.Msg("Gordon is running") | |
| 1907 | 1915 | ||
| 1908 | 1916 | schedulerCleanup, err := startOptionalSchedulers(ctx, cfg, svc, log, v) | |
| 1909 | 1917 | if err != nil { | |
| @@ -2166,8 +2174,8 @@ func gracefulShutdown(registrySrv, proxySrv, tlsSrv *http.Server, containerSvc * | |||
| 2166 | 2174 | log.Info().Msg("Gordon stopped") | |
| 2167 | 2175 | } | |
| 2168 | 2176 | ||
| 2169 | - | // startProxyServers sets up the HTTP proxy server and the HTTPS proxy server | |
| 2170 | - | // with on-demand TLS certificates from the internal CA. | |
| 2177 | + | // startProxyServers sets up the HTTP proxy server and, when tls_port != 0, | |
| 2178 | + | // an HTTPS proxy server with on-demand TLS certificates from the internal CA. | |
| 2171 | 2179 | func startProxyServers(cfg Config, httpHandler, httpsHandler http.Handler, pkiSvc *pkiusecase.Service, errChan chan<- error, log zerowrap.Logger) (*http.Server, <-chan struct{}, *http.Server, <-chan struct{}, error) { | |
| 2172 | 2180 | // HTTP listener (Cloudflare proxy + onboarding for direct clients) | |
| 2173 | 2181 | var httpProtos http.Protocols | |
| @@ -2182,6 +2190,10 @@ func startProxyServers(cfg Config, httpHandler, httpsHandler http.Handler, pkiSv | |||
| 2182 | 2190 | log, | |
| 2183 | 2191 | ) | |
| 2184 | 2192 | ||
| 2193 | + | if cfg.Server.TLSPort == 0 { | |
| 2194 | + | return httpSrv, httpReady, nil, nil, nil | |
| 2195 | + | } | |
| 2196 | + | ||
| 2185 | 2197 | // HTTPS listener (on-demand TLS via internal CA) | |
| 2186 | 2198 | tlsConfig := &tls.Config{ | |
| 2187 | 2199 | MinVersion: tls.VersionTLS12, | |
| @@ -2521,9 +2533,9 @@ func isProcessAlive(pid int) bool { | |||
| 2521 | 2533 | ||
| 2522 | 2534 | // loadConfig loads configuration from file and sets defaults. | |
| 2523 | 2535 | func loadConfig(v *viper.Viper, configPath string) error { | |
| 2524 | - | v.SetDefault("server.port", 80) | |
| 2536 | + | v.SetDefault("server.port", 8088) | |
| 2525 | 2537 | v.SetDefault("server.registry_port", 5000) | |
| 2526 | - | v.SetDefault("server.tls_port", 443) | |
| 2538 | + | v.SetDefault("server.tls_port", 8443) | |
| 2527 | 2539 | v.SetDefault("server.data_dir", DefaultDataDir()) | |
| 2528 | 2540 | v.SetDefault("server.runtime", "auto") | |
| 2529 | 2541 | v.SetDefault("logging.level", "info") | |
| @@ -375,13 +375,17 @@ func createServices(ctx context.Context, v *viper.Viper, cfg Config, log zerowra | |||||
| 375 | return nil, log.WrapErr(err, "failed to load configuration") | 375 | return nil, log.WrapErr(err, "failed to load configuration") | ||
| 376 | } | 376 | } | ||
| 377 | 377 | ||||
| 378 | - | // Create PKI (internal CA) | 378 | + | // Create PKI (internal CA) — disabled when tls_port is 0. |
| 379 | - | caAdapter, err := pkiadapter.NewCA(resolveDataDir(cfg.Server.DataDir), log) | 379 | + | if cfg.Server.TLSPort != 0 { |
| 380 | - | if err != nil { | 380 | + | caAdapter, err := pkiadapter.NewCA(resolveDataDir(cfg.Server.DataDir), log) |
| 381 | - | return nil, log.WrapErr(err, "failed to initialize internal CA") | 381 | + | if err != nil { |
| 382 | + | return nil, log.WrapErr(err, "failed to initialize internal CA") | |||
| 383 | + | } | |||
| 384 | + | svc.caAdapter = caAdapter | |||
| 385 | + | svc.pkiSvc = pkiusecase.NewService(ctx, caAdapter, svc.configSvc, log) | |||
| 386 | + | } else { | |||
| 387 | + | log.Info().Msg("internal CA disabled (server.tls_port=0)") | |||
| 382 | } | 388 | } | ||
| 383 | - | svc.caAdapter = caAdapter | |||
| 384 | - | svc.pkiSvc = pkiusecase.NewService(ctx, caAdapter, svc.configSvc, log) | |||
| 385 | 389 | ||||
| 386 | var backend domain.SecretsBackend | 390 | var backend domain.SecretsBackend | ||
| 387 | var passStore *domainsecrets.PassStore | 391 | var passStore *domainsecrets.PassStore | ||
| @@ -1895,15 +1899,19 @@ func runServers(ctx context.Context, v *viper.Viper, cfg Config, svc *services, | |||||
| 1895 | if err := waitForServerReady(proxyReady, errChan); err != nil { | 1899 | if err := waitForServerReady(proxyReady, errChan); err != nil { | ||
| 1896 | return err | 1900 | return err | ||
| 1897 | } | 1901 | } | ||
| 1898 | - | if err := waitForServerReady(tlsReady, errChan); err != nil { | 1902 | + | if tlsReady != nil { |
| 1899 | - | return err | 1903 | + | if err := waitForServerReady(tlsReady, errChan); err != nil { |
| 1904 | + | return err | |||
| 1905 | + | } | |||
| 1900 | } | 1906 | } | ||
| 1901 | 1907 | ||||
| 1902 | - | log.Info(). | 1908 | + | logEvent := log.Info(). |
| 1903 | Int("proxy_port", cfg.Server.Port). | 1909 | Int("proxy_port", cfg.Server.Port). | ||
| 1904 | - | Int("tls_port", cfg.Server.TLSPort). | 1910 | + | Int("registry_port", cfg.Server.RegistryPort) |
| 1905 | - | Int("registry_port", cfg.Server.RegistryPort). | 1911 | + | if cfg.Server.TLSPort != 0 { |
| 1906 | - | Msg("Gordon is running") | 1912 | + | logEvent = logEvent.Int("tls_port", cfg.Server.TLSPort) |
| 1913 | + | } | |||
| 1914 | + | logEvent.Msg("Gordon is running") | |||
| 1907 | 1915 | ||||
| 1908 | schedulerCleanup, err := startOptionalSchedulers(ctx, cfg, svc, log, v) | 1916 | schedulerCleanup, err := startOptionalSchedulers(ctx, cfg, svc, log, v) | ||
| 1909 | if err != nil { | 1917 | if err != nil { | ||
| @@ -2166,8 +2174,8 @@ func gracefulShutdown(registrySrv, proxySrv, tlsSrv *http.Server, containerSvc * | |||||
| 2166 | log.Info().Msg("Gordon stopped") | 2174 | log.Info().Msg("Gordon stopped") | ||
| 2167 | } | 2175 | } | ||
| 2168 | 2176 | ||||
| 2169 | - | // startProxyServers sets up the HTTP proxy server and the HTTPS proxy server | 2177 | + | // startProxyServers sets up the HTTP proxy server and, when tls_port != 0, |
| 2170 | - | // with on-demand TLS certificates from the internal CA. | 2178 | + | // an HTTPS proxy server with on-demand TLS certificates from the internal CA. |
| 2171 | func startProxyServers(cfg Config, httpHandler, httpsHandler http.Handler, pkiSvc *pkiusecase.Service, errChan chan<- error, log zerowrap.Logger) (*http.Server, <-chan struct{}, *http.Server, <-chan struct{}, error) { | 2179 | func startProxyServers(cfg Config, httpHandler, httpsHandler http.Handler, pkiSvc *pkiusecase.Service, errChan chan<- error, log zerowrap.Logger) (*http.Server, <-chan struct{}, *http.Server, <-chan struct{}, error) { | ||
| 2172 | // HTTP listener (Cloudflare proxy + onboarding for direct clients) | 2180 | // HTTP listener (Cloudflare proxy + onboarding for direct clients) | ||
| 2173 | var httpProtos http.Protocols | 2181 | var httpProtos http.Protocols | ||
| @@ -2182,6 +2190,10 @@ func startProxyServers(cfg Config, httpHandler, httpsHandler http.Handler, pkiSv | |||||
| 2182 | log, | 2190 | log, | ||
| 2183 | ) | 2191 | ) | ||
| 2184 | 2192 | ||||
| 2193 | + | if cfg.Server.TLSPort == 0 { | |||
| 2194 | + | return httpSrv, httpReady, nil, nil, nil | |||
| 2195 | + | } | |||
| 2196 | + | ||||
| 2185 | // HTTPS listener (on-demand TLS via internal CA) | 2197 | // HTTPS listener (on-demand TLS via internal CA) | ||
| 2186 | tlsConfig := &tls.Config{ | 2198 | tlsConfig := &tls.Config{ | ||
| 2187 | MinVersion: tls.VersionTLS12, | 2199 | MinVersion: tls.VersionTLS12, | ||
| @@ -2521,9 +2533,9 @@ func isProcessAlive(pid int) bool { | |||||
| 2521 | 2533 | ||||
| 2522 | // loadConfig loads configuration from file and sets defaults. | 2534 | // loadConfig loads configuration from file and sets defaults. | ||
| 2523 | func loadConfig(v *viper.Viper, configPath string) error { | 2535 | func loadConfig(v *viper.Viper, configPath string) error { | ||
| 2524 | - | v.SetDefault("server.port", 80) | 2536 | + | v.SetDefault("server.port", 8088) |
| 2525 | v.SetDefault("server.registry_port", 5000) | 2537 | v.SetDefault("server.registry_port", 5000) | ||
| 2526 | - | v.SetDefault("server.tls_port", 443) | 2538 | + | v.SetDefault("server.tls_port", 8443) |
| 2527 | v.SetDefault("server.data_dir", DefaultDataDir()) | 2539 | v.SetDefault("server.data_dir", DefaultDataDir()) | ||
| 2528 | v.SetDefault("server.runtime", "auto") | 2540 | v.SetDefault("server.runtime", "auto") | ||
| 2529 | v.SetDefault("logging.level", "info") | 2541 | v.SetDefault("logging.level", "info") | ||
M internal/usecase/config/service_test.go +2 -2
| @@ -1412,8 +1412,8 @@ backend = ["app.example.com"] | |||
| 1412 | 1412 | ||
| 1413 | 1413 | v := viper.New() | |
| 1414 | 1414 | v.SetConfigFile(configFile) | |
| 1415 | - | v.SetDefault("server.port", 80) | |
| 1416 | - | v.SetDefault("server.tls_port", 443) | |
| 1415 | + | v.SetDefault("server.port", 8088) | |
| 1416 | + | v.SetDefault("server.tls_port", 8443) | |
| 1417 | 1417 | v.SetDefault("auth.secrets_backend", "") | |
| 1418 | 1418 | v.SetDefault("auto_route.enabled", false) | |
| 1419 | 1419 | v.SetDefault("network_isolation.enabled", false) | |
| @@ -1412,8 +1412,8 @@ backend = ["app.example.com"] | |||||
| 1412 | 1412 | ||||
| 1413 | v := viper.New() | 1413 | v := viper.New() | ||
| 1414 | v.SetConfigFile(configFile) | 1414 | v.SetConfigFile(configFile) | ||
| 1415 | - | v.SetDefault("server.port", 80) | 1415 | + | v.SetDefault("server.port", 8088) |
| 1416 | - | v.SetDefault("server.tls_port", 443) | 1416 | + | v.SetDefault("server.tls_port", 8443) |
| 1417 | v.SetDefault("auth.secrets_backend", "") | 1417 | v.SetDefault("auth.secrets_backend", "") | ||
| 1418 | v.SetDefault("auto_route.enabled", false) | 1418 | v.SetDefault("auto_route.enabled", false) | ||
| 1419 | v.SetDefault("network_isolation.enabled", false) | 1419 | v.SetDefault("network_isolation.enabled", false) | ||