diff --git a/nix/host-modules/hive-gateway/error-pages.nix b/nix/host-modules/hive-gateway/error-pages.nix index 3285632c..f1ad62e9 100644 --- a/nix/host-modules/hive-gateway/error-pages.nix +++ b/nix/host-modules/hive-gateway/error-pages.nix @@ -56,6 +56,24 @@ in ''; }; + # Shown when the authelia vhost's upstream refuses the connection. + # Leads with the bootstrap because that is overwhelmingly the cause: + # authelia treats an empty user store as a FATAL startup error, so an + # enabled-but-unbootstrapped swarm crash-loops behind a vhost that is + # working perfectly, and the raw 502 points at the proxy instead. + ssoUnavailable = mkPage { + name = "sso-unavailable"; + title = "sso unavailable"; + accent = "#f9e2af"; + body = '' +

The swarm's identity provider isn't answering. The gateway is fine — nothing is listening behind it.

+

Most likely: no users exist yet. Authelia refuses to start with an empty user store, so it never finishes booting. Add the first account on the host running it:

+
swarmctl user add <username> \
+      --display-name <Name> --email <addr> --group admins
+

Otherwise check the container: journalctl -M swarm-authelia -u authelia-swarm. This page recovers on reload once the provider is up.

+ ''; + }; + unauthorized = mkPage { name = "unauthorized"; title = "unauthorized"; diff --git a/nix/host-modules/hive-gateway/vhosts.nix b/nix/host-modules/hive-gateway/vhosts.nix index 20d9c97d..297c724f 100644 --- a/nix/host-modules/hive-gateway/vhosts.nix +++ b/nix/host-modules/hive-gateway/vhosts.nix @@ -155,6 +155,17 @@ let proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Uri $request_uri; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # A dead upstream here means "not bootstrapped" far more often + # than "misconfigured proxy", and a bare 502 says the opposite. + proxy_intercept_errors on; + error_page 502 503 504 = /__hive_sso_unavailable; + ''; + }; + locations."= /__hive_sso_unavailable" = { + extraConfig = '' + internal; + alias ${errorPages.ssoUnavailable}; + default_type text/html; ''; }; };