diff --git a/nix/modules/hive-forge.nix b/nix/modules/hive-forge.nix index d81921a8..022dda29 100644 --- a/nix/modules/hive-forge.nix +++ b/nix/modules/hive-forge.nix @@ -12,18 +12,26 @@ let # ROOT_URL forgejo advertises in clone links + outbound URLs. When # served behind the gateway, `cfg.domain` doubles as both the # forgejo `DOMAIN` setting AND the gateway vhost server-name, so - # ROOT_URL just uses it directly (drops the port suffix when the - # gateway is on the canonical port 80). When direct (gateway off - # or `behindGateway = false`), keep the host:port shape so direct - # browser access on `:httpPort` still produces correct links. - # Operators can override via `cfg.rootUrl` for TLS / non-default - # gateway ports / bespoke shapes. + # ROOT_URL just uses it directly (dropping the port suffix on the + # canonical port for the scheme — 80 for http, 443 for https). The + # scheme + port follow what the gateway actually serves: `https` when + # the gateway terminates TLS (a self-signed cert or an external + # `tls.certDir`), `http` otherwise (#1724) — advertising `http://` for + # a TLS gateway produces broken clone links + mixed-content redirects. + # When direct (gateway off or `behindGateway = false`), keep the + # host:httpPort shape so direct browser access still produces correct + # links. Operators can still override via `cfg.rootUrl` for bespoke + # shapes. + gatewayTls = gatewayCfg.selfSignedTls || gatewayCfg.tls.certDir != null; defaultRootUrl = if cfg.behindGateway then let - portSuffix = if gatewayCfg.port == 80 then "" else ":${toString gatewayCfg.port}"; + scheme = if gatewayTls then "https" else "http"; + port = if gatewayTls then gatewayCfg.httpsPort else gatewayCfg.port; + canonicalPort = if gatewayTls then 443 else 80; + portSuffix = if port == canonicalPort then "" else ":${toString port}"; in - "http://${cfg.domain}${portSuffix}/" + "${scheme}://${cfg.domain}${portSuffix}/" else "http://${cfg.domain}:${toString cfg.httpPort}/"; effectiveRootUrl = if cfg.rootUrl != null then cfg.rootUrl else defaultRootUrl; @@ -147,16 +155,19 @@ in description = '' Override the auto-derived forgejo `ROOT_URL`. When `null` (default), `ROOT_URL` is derived from `cfg.domain` + gateway - state: + state, including the scheme: - - `behindGateway = true` → `http://''${cfg.domain}/` (uses - `services.hyperhive.gateway.port` when non-80) + - `behindGateway = true` → `https://''${cfg.domain}/` when the + gateway terminates TLS (`gateway.selfSignedTls = true` or + `gateway.tls.certDir` set), otherwise `http://''${cfg.domain}/`. + A non-canonical gateway port (`gateway.port` for http, + `gateway.httpsPort` for https) is appended as `:`. - `behindGateway = false` → `http://''${cfg.domain}:''${cfg.httpPort}/` - Set this to a fully-qualified URL when running behind TLS - termination (`https://...`), a non-default gateway port, or - a bespoke shape. Must end with `/` per forgejo's `ROOT_URL` - contract. + The TLS scheme is derived automatically now, so you only need to + set this for a genuinely bespoke shape (e.g. an external reverse + proxy on a different host/path). Must end with `/` per forgejo's + `ROOT_URL` contract. ''; };