diff --git a/nix/modules/hive-gateway.nix b/nix/modules/hive-gateway.nix index 61b4cd18..5c5194c1 100644 --- a/nix/modules/hive-gateway.nix +++ b/nix/modules/hive-gateway.nix @@ -404,20 +404,23 @@ in system.stateVersion = "26.05"; # Generate a self-signed cert on first boot if missing. nginx - # waits on this (Before=) so we never start with a broken - # ssl_certificate path. Cert covers the bare hive domain plus - # `*.${hyperhiveDomain}` so the matrix + forge sub-domains - # are valid under the same cert. See `docs/gateway.md` - # ("Self-signed TLS"). + # `Requires=` this via `requiredBy`, so systemd refuses to + # start nginx until the cert exists — `before=` alone wasn't + # enough (it only orders within a single transaction, but + # nginx was being pulled into a different transaction by + # multi-user.target and started without waiting, #856). Cert + # covers the bare hive domain plus `*.${hyperhiveDomain}` so + # the matrix + forge sub-domains are valid under the same + # cert. See `docs/gateway.md` ("Self-signed TLS"). systemd.services.hive-gateway-self-signed-cert = lib.mkIf cfg.selfSignedTls { description = "Generate self-signed TLS cert for hive-gateway"; wantedBy = [ "multi-user.target" ]; before = [ "nginx.service" ]; + requiredBy = [ "nginx.service" ]; unitConfig.ConditionPathExists = "!${tlsCert}"; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; - UMask = "0077"; }; path = [ pkgs.openssl @@ -436,6 +439,10 @@ in in '' mkdir -p ${tlsDir} + # 0755 dir so nginx (master starts as root but workers + # drop to the nginx user) can read the cert path + # without traversal failures. Key stays 0600 below. + chmod 0755 ${tlsDir} openssl req -x509 -newkey rsa:4096 -nodes -sha256 -days 3650 \ -keyout ${tlsKey} \ -out ${tlsCert} \