forge: always behind the gateway; drop behindGateway
The forge always sits behind the gateway, so `deploy.forgejo.behindGateway` (and its `swarm.forge.behindGateway` rename alias) is removed and its true-branch behaviour is now unconditional within `deploy.forgejo.enable`: https ROOT_URL on the gateway's httpsPort, the forge vhost and local DNS name, the swarm-ui quick link, the published metrics scrape target, forgejo metrics, the authelia `/metrics` rule, and `publicUrl` defaulting to `https://<forge.domain>`. Removed with it: the direct-port `http://<domain>:<httpPort>/` ROOT_URL branch, the hive-ci assertion that the option is true, the core-toggle cases that only exercised the false branch (the services-leaf case reads `bare`, which never enabled the forge either). `hivectl open forge` now points at `swarm.forge.publicUrl`, which can still be set to null. Refs #4885
This commit is contained in:
parent
a40c0026cf
commit
ac592a5d23
13 changed files with 89 additions and 213 deletions
|
|
@ -58,26 +58,20 @@ let
|
|||
|
||||
caTrust = import ../lib/hive-ca-trust.nix { inherit lib tlsCfg gatewayCfg; };
|
||||
|
||||
# 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. The gateway always terminates TLS
|
||||
# (self-signed is the implicit floor when neither `tls.certDir` nor
|
||||
# ACME is configured), so behind the gateway the forge is always
|
||||
# advertised over `https` on `httpsPort` — the canonical 443 elides
|
||||
# the port suffix. When direct (`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. Both bindings are duplicated in ./service.nix, which builds
|
||||
# `sso.redirectUri` from them; keep the two equal.
|
||||
# ROOT_URL forgejo advertises in clone links + outbound URLs.
|
||||
# `cfg.domain` doubles as both the forgejo `DOMAIN` setting AND the
|
||||
# gateway vhost server-name, so ROOT_URL just uses it directly. The
|
||||
# gateway always terminates TLS (self-signed is the implicit floor when
|
||||
# neither `tls.certDir` nor ACME is configured), so the forge is always
|
||||
# advertised over `https` on `httpsPort` — the canonical 443 elides the
|
||||
# port suffix. Operators can still override via `cfg.rootUrl` for
|
||||
# bespoke shapes. Both bindings are duplicated in ./service.nix, which
|
||||
# builds `sso.redirectUri` from them; keep the two equal.
|
||||
defaultRootUrl =
|
||||
if deployCfg.forgejo.behindGateway then
|
||||
let
|
||||
portSuffix = if gatewayCfg.httpsPort == 443 then "" else ":${toString gatewayCfg.httpsPort}";
|
||||
in
|
||||
"https://${cfg.domain}${portSuffix}/"
|
||||
else
|
||||
"http://${cfg.domain}:${toString cfg.httpPort}/";
|
||||
let
|
||||
portSuffix = if gatewayCfg.httpsPort == 443 then "" else ":${toString gatewayCfg.httpsPort}";
|
||||
in
|
||||
"https://${cfg.domain}${portSuffix}/";
|
||||
effectiveRootUrl = if cfg.rootUrl != null then cfg.rootUrl else defaultRootUrl;
|
||||
|
||||
# When CI is enabled, the runner needs `actions/checkout` resolvable
|
||||
|
|
@ -136,35 +130,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
behindGateway = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Serve forgejo through the hive-gateway nginx as a sub-domain
|
||||
vhost (`server_name = cfg.domain`) instead of directly on
|
||||
`httpPort` (sub-domain routing — see `docs/networking/gateway.md`).
|
||||
|
||||
When `true`:
|
||||
- The gateway adds a `server { server_name = ''${cfg.domain}; }`
|
||||
block that proxies all `/` → `http://127.0.0.1:''${httpPort}/`.
|
||||
- Forgejo's `ROOT_URL` flips to `http(s)://''${cfg.domain}/`
|
||||
(sub-domain root, no port suffix when gateway is on 80).
|
||||
- `gateway.localHostsEntry = true` extends `/etc/hosts` to
|
||||
include `cfg.domain → 127.0.0.1` for local dev.
|
||||
|
||||
Defaults to `true` (the gateway always runs alongside
|
||||
hyperhive, so forge auto-routes through it). Set `false`
|
||||
explicitly to keep forge on the direct port even though the
|
||||
gateway is running (e.g. an external git client that doesn't
|
||||
traverse the gateway).
|
||||
|
||||
Sub-domain routing is the preferred shape for forge + matrix
|
||||
(both are external standard apps with sub-domain-native config
|
||||
defaults). Per-agent UIs stay on sub-path (`/agent/<name>/`)
|
||||
because they're hyperhive-internal + already base-path-aware.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
|
|
@ -281,49 +246,38 @@ in
|
|||
# the gateway supplies the primitives (`lib.listen`, `lib.tlsFor`,
|
||||
# `lib.securityHeaders`) and never needs to know this service by
|
||||
# name.
|
||||
#
|
||||
# Both halves are gated on `behindGateway`: with it off the operator
|
||||
# fronts forgejo themselves, so this hive must neither claim the
|
||||
# vhost nor answer DNS for it.
|
||||
services.hyperhive.gateway.localNames = lib.optional deployCfg.forgejo.behindGateway cfg.domain;
|
||||
services.hyperhive.gateway.enable = lib.mkIf deployCfg.forgejo.behindGateway (lib.mkDefault true);
|
||||
services.hyperhive.gateway.localNames = [ cfg.domain ];
|
||||
services.hyperhive.gateway.enable = lib.mkDefault true;
|
||||
|
||||
# Not conditional on `behindGateway`: the forge container resolves the
|
||||
# rest of the hive through dnsmasq whoever fronts it.
|
||||
# The forge container resolves the rest of the hive through dnsmasq.
|
||||
services.hyperhive.gateway.dns.enable = lib.mkDefault true;
|
||||
|
||||
# This swarm-ui quick-links entry, same `behindGateway` guard as the
|
||||
# vhost/DNS name above — with it off, this host doesn't actually
|
||||
# serve `cfg.domain`, so linking to it would be dead. See
|
||||
# This swarm-ui quick-links entry. See
|
||||
# `services.hyperhive.swarm.controller.links`'s description.
|
||||
services.hyperhive.swarm.controller.links = lib.optional deployCfg.forgejo.behindGateway {
|
||||
label = "Forge";
|
||||
icon = "⚒";
|
||||
url = "https://${cfg.domain}/";
|
||||
};
|
||||
services.hyperhive.swarm.controller.links = [
|
||||
{
|
||||
label = "Forge";
|
||||
icon = "⚒";
|
||||
url = "https://${cfg.domain}/";
|
||||
}
|
||||
];
|
||||
|
||||
# The metrics endpoint, declared once: the collector both scrapes this
|
||||
# URL and derives from it the audience its token is minted for. Same
|
||||
# `behindGateway` guard, and for a stronger reason than the two above:
|
||||
# with it off there is no `= /metrics` location and no `auth_request`
|
||||
# in front of it, so the URL this names does not exist to be scraped
|
||||
# or authorised.
|
||||
# URL and derives from it the audience its token is minted for.
|
||||
#
|
||||
# ⚠️ Written as the exact URL a collector requests, because that is
|
||||
# what authelia compares against — this string agreeing with the
|
||||
# `location` block above it is the whole mechanism. A near miss is a
|
||||
# correctly minted token refused at the target.
|
||||
services.hyperhive.swarm.otel.publishedScrapeTargets =
|
||||
lib.optionalAttrs deployCfg.forgejo.behindGateway
|
||||
{
|
||||
forgejo = "https://${cfg.domain}/metrics";
|
||||
};
|
||||
services.hyperhive.swarm.otel.publishedScrapeTargets = {
|
||||
forgejo = "https://${cfg.domain}/metrics";
|
||||
};
|
||||
|
||||
# `server_name = forge.domain`, proxies all `/` → forgejo. Tuned for
|
||||
# git: `client_max_body_size 1G`, `proxy_read_timeout 1h` (multi-GB
|
||||
# clones). SSH stays direct on `forge.sshPort`. See
|
||||
# `docs/networking/gateway.md`.
|
||||
services.nginx.virtualHosts = lib.optionalAttrs deployCfg.forgejo.behindGateway {
|
||||
services.nginx.virtualHosts = {
|
||||
"${cfg.domain}" = (gatewayCfg.lib.tlsFor cfg.domain) // {
|
||||
listen = gatewayCfg.lib.listen;
|
||||
extraConfig = gatewayCfg.lib.securityHeaders;
|
||||
|
|
@ -600,21 +554,17 @@ in
|
|||
DEFAULT_PRIVATE = "private";
|
||||
};
|
||||
# Not an option: a swarm-integrated, auto-deployed forge
|
||||
# always has metrics. Tied to `behindGateway` because that
|
||||
# IS the swarm-integrated shape — it is the condition under
|
||||
# which the protected `= /metrics` location below exists.
|
||||
# Serving the endpoint without that location would put it on
|
||||
# a listener `openFirewall` can expose, with nothing in
|
||||
# front of it.
|
||||
# always has metrics, behind the protected `= /metrics`
|
||||
# location on its gateway vhost.
|
||||
#
|
||||
# No `TOKEN` here on purpose. Forgejo can guard this itself
|
||||
# with a static bearer, but the swarm authenticates the
|
||||
# scraper at the gateway, so a second credential system per
|
||||
# service would buy nothing and would be the one that stops
|
||||
# getting rotated.
|
||||
metrics.ENABLED = deployCfg.forgejo.behindGateway;
|
||||
# The two per-dimension breakdowns, on the same condition as
|
||||
# the endpoint itself: `gitea_issues_by_label{label=…}` and
|
||||
metrics.ENABLED = true;
|
||||
# The two per-dimension breakdowns, alongside the endpoint
|
||||
# itself: `gitea_issues_by_label{label=…}` and
|
||||
# `gitea_issues_by_repository{repository=…}`. Off by default
|
||||
# upstream because they are the only metrics here whose series
|
||||
# count grows with the CONTENT of the forge rather than with
|
||||
|
|
@ -631,8 +581,8 @@ in
|
|||
# forge that grew to thousands of repos would want this
|
||||
# revisited — that is a real trigger, unlike a time-based one:
|
||||
# `count(gitea_issues_by_repository)` answers it directly.
|
||||
metrics.ENABLED_ISSUE_BY_LABEL = deployCfg.forgejo.behindGateway;
|
||||
metrics.ENABLED_ISSUE_BY_REPOSITORY = deployCfg.forgejo.behindGateway;
|
||||
metrics.ENABLED_ISSUE_BY_LABEL = true;
|
||||
metrics.ENABLED_ISSUE_BY_REPOSITORY = true;
|
||||
# Repo migrations / pull-mirrors fetch from the source
|
||||
# URL *inside* Forgejo. hyperhive code is synced from
|
||||
# `localhost` (and the host LAN), which Forgejo's
|
||||
|
|
|
|||
Loading…
Reference in a new issue