Compare commits
6 changed files with 2 additions and 83 deletions
|
|
@ -14,9 +14,6 @@ Single nginx in front of every hyperhive web surface. Runs on the **host**, next
|
||||||
| `matrix.<hive>/_matrix/*` | `matrix.<hive>` | tuwunel (`8008`) | `matrix.gatewayHost != null` |
|
| `matrix.<hive>/_matrix/*` | `matrix.<hive>` | tuwunel (`8008`) | `matrix.gatewayHost != null` |
|
||||||
| `matrix.<hive>/` | `matrix.<hive>` | fluffychat-web static | `matrix.gui.enable` |
|
| `matrix.<hive>/` | `matrix.<hive>` | fluffychat-web static | `matrix.gui.enable` |
|
||||||
| `matrix.<hive>/config.json` | `matrix.<hive>` | inline JSON (FluffyChat boot config) | `matrix.gui.enable && domain != null` |
|
| `matrix.<hive>/config.json` | `matrix.<hive>` | inline JSON (FluffyChat boot config) | `matrix.gui.enable && domain != null` |
|
||||||
| `auth.<swarm>/` | `auth.<swarm>` | authelia (`9091`) | `swarm.authelia.enable` |
|
|
||||||
|
|
||||||
The authelia vhost is declared only by the host that **runs** authelia, not by every hive that uses it — a client hive knows the swarm's `authelia.url` but must not answer for a name it doesn't serve. Its server name is exactly `swarm.authelia.domain`: authelia validates `authelia_url ⊂ session cookie domain` at startup, so a near-miss is a container that refuses to boot. It carries no `auth_basic` — the login page must not sit behind the login mechanism it replaces — and sets the four `X-Forwarded-{Proto,Host,Uri,For}` headers, since authelia decides by the *original* request rather than the hop it sees.
|
|
||||||
|
|
||||||
Per-agent UIs stay sub-path because they're hyperhive-internal and base-path-aware. External standard apps (forge / matrix) get sub-domains because their defaults work cleanly at sub-domain root + per-origin cookies / storage isolation matters.
|
Per-agent UIs stay sub-path because they're hyperhive-internal and base-path-aware. External standard apps (forge / matrix) get sub-domains because their defaults work cleanly at sub-domain root + per-origin cookies / storage isolation matters.
|
||||||
|
|
||||||
|
|
@ -60,7 +57,6 @@ Each location carries a duplicated `auth_basic` block (separate locations don't
|
||||||
- `<hive-domain>` → `127.0.0.1`
|
- `<hive-domain>` → `127.0.0.1`
|
||||||
- `forge.<hive>` → `127.0.0.1` (when forge.behindGateway)
|
- `forge.<hive>` → `127.0.0.1` (when forge.behindGateway)
|
||||||
- `matrix.<hive>` → `127.0.0.1` (when matrix.gatewayHost set)
|
- `matrix.<hive>` → `127.0.0.1` (when matrix.gatewayHost set)
|
||||||
- `auth.<swarm>` → `127.0.0.1` (when swarm.authelia.enable)
|
|
||||||
|
|
||||||
`lib.unique` de-dupes if any sub-domain happens to equal another entry. Operators with real DNS leave it off.
|
`lib.unique` de-dupes if any sub-domain happens to equal another entry. Operators with real DNS leave it off.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,7 @@ schemes pick their own.
|
||||||
## Resolver behaviour
|
## Resolver behaviour
|
||||||
|
|
||||||
dnsmasq is **authoritative** for the hive's own zones — answers
|
dnsmasq is **authoritative** for the hive's own zones — answers
|
||||||
`<hive-domain>`, `forge.<hive-domain>`, `matrix.<hive-domain>` and —
|
`<hive-domain>`, `forge.<hive-domain>`, `matrix.<hive-domain>`
|
||||||
on the host running it — the swarm's `auth.<swarm-domain>`
|
|
||||||
queries with the bridge IP (where nginx is reachable). Everything
|
queries with the bridge IP (where nginx is reachable). Everything
|
||||||
else is forwarded to the host's own resolvers: dnsmasq runs on the host
|
else is forwarded to the host's own resolvers: dnsmasq runs on the host
|
||||||
and reads the host's `/etc/resolv.conf` directly. Containers don't need
|
and reads the host's `/etc/resolv.conf` directly. Containers don't need
|
||||||
|
|
|
||||||
|
|
@ -10,38 +10,6 @@ The second role is derived rather than switched:
|
||||||
on. authelia refuses to start with a provider that has no clients, so a
|
on. authelia refuses to start with a provider that has no clients, so a
|
||||||
separate `enable` would be a second fact free to disagree with the first.
|
separate `enable` would be a second fact free to disagree with the first.
|
||||||
|
|
||||||
## Getting in the first time
|
|
||||||
|
|
||||||
authelia binds loopback only. The **gateway** on the host running it
|
|
||||||
publishes it as `auth.<swarm.domain>` — vhost, dnsmasq record and TLS
|
|
||||||
name all follow `swarm.authelia.enable`, so there is nothing to turn on
|
|
||||||
separately. (Details, including why a client hive must not declare that
|
|
||||||
vhost: [`../gateway.md`](../gateway.md).)
|
|
||||||
|
|
||||||
Reachable is not the same as usable: the provider is generated with an
|
|
||||||
empty user set, deliberately. A provider with nobody in it yet is the
|
|
||||||
correct state for a fresh swarm — it is not a half-finished install, and
|
|
||||||
seeding a default account would be a credential in a config file.
|
|
||||||
|
|
||||||
Add the first subject on the host running authelia:
|
|
||||||
|
|
||||||
```console
|
|
||||||
# swarmctl user add mara --display-name Mara --email mara@example.com --group admins
|
|
||||||
added mara to /var/lib/authelia-swarm/users.yml
|
|
||||||
password: <generated>
|
|
||||||
this password is stored nowhere — record it now
|
|
||||||
```
|
|
||||||
|
|
||||||
The password is generated, hashed, and printed once; only the hash is
|
|
||||||
kept. `swarmctl` writes its canonical `users.json`, re-renders authelia's
|
|
||||||
`users.yml` from it, and restarts authelia. Full reference:
|
|
||||||
[`../tools/swarmctl-cli.md`](../tools/swarmctl-cli.md).
|
|
||||||
|
|
||||||
This step stays manual on purpose. Bootstrapping an identity provider
|
|
||||||
non-interactively means a secret arriving from somewhere — a file, an
|
|
||||||
env var, a nix expression — and every one of those is worse than an
|
|
||||||
operator typing one command once.
|
|
||||||
|
|
||||||
## What secrets exist, and where each one lives
|
## What secrets exist, and where each one lives
|
||||||
|
|
||||||
| secret | generated by | rests in | read by |
|
| secret | generated by | rests in | read by |
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ let
|
||||||
# same list rather than each deciding what "a swarm service" means.
|
# same list rather than each deciding what "a swarm service" means.
|
||||||
swarmServiceDomains = config.services.hyperhive.swarm.serviceDomains;
|
swarmServiceDomains = config.services.hyperhive.swarm.serviceDomains;
|
||||||
matrixCfg = config.services.hyperhive.swarm.matrix;
|
matrixCfg = config.services.hyperhive.swarm.matrix;
|
||||||
autheliaCfg = config.services.hyperhive.swarm.authelia;
|
|
||||||
forgeCfg = config.services.hyperhive.swarm.forge;
|
forgeCfg = config.services.hyperhive.swarm.forge;
|
||||||
networkCfg = config.services.hyperhive.network;
|
networkCfg = config.services.hyperhive.network;
|
||||||
|
|
||||||
|
|
@ -71,7 +70,6 @@ let
|
||||||
cfg
|
cfg
|
||||||
forgeCfg
|
forgeCfg
|
||||||
matrixCfg
|
matrixCfg
|
||||||
autheliaCfg
|
|
||||||
hyperhiveDomain
|
hyperhiveDomain
|
||||||
dashboardDist
|
dashboardDist
|
||||||
swaggerUiTheme
|
swaggerUiTheme
|
||||||
|
|
@ -311,7 +309,6 @@ in
|
||||||
networkCfg
|
networkCfg
|
||||||
forgeCfg
|
forgeCfg
|
||||||
matrixCfg
|
matrixCfg
|
||||||
autheliaCfg
|
|
||||||
hyperhiveDomain
|
hyperhiveDomain
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
|
@ -335,7 +332,6 @@ in
|
||||||
++ lib.optional (config.services.hyperhive.swarm.forge.behindGateway or false
|
++ lib.optional (config.services.hyperhive.swarm.forge.behindGateway or false
|
||||||
) config.services.hyperhive.swarm.forge.domain
|
) config.services.hyperhive.swarm.forge.domain
|
||||||
++ lib.optional (matrixCfg.enable && matrixCfg.gatewayHost != null) matrixCfg.gatewayHost
|
++ lib.optional (matrixCfg.enable && matrixCfg.gatewayHost != null) matrixCfg.gatewayHost
|
||||||
++ lib.optional autheliaCfg.enable autheliaCfg.domain
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
networkCfg,
|
networkCfg,
|
||||||
forgeCfg,
|
forgeCfg,
|
||||||
matrixCfg,
|
matrixCfg,
|
||||||
autheliaCfg,
|
|
||||||
hyperhiveDomain,
|
hyperhiveDomain,
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
|
|
@ -59,8 +58,7 @@
|
||||||
++ lib.optional ((forgeCfg.behindGateway or false)) "/${forgeCfg.domain}/${networkCfg.bridgeIp}"
|
++ lib.optional ((forgeCfg.behindGateway or false)) "/${forgeCfg.domain}/${networkCfg.bridgeIp}"
|
||||||
++ lib.optional (
|
++ lib.optional (
|
||||||
matrixCfg.enable && matrixCfg.gatewayHost != null
|
matrixCfg.enable && matrixCfg.gatewayHost != null
|
||||||
) "/${matrixCfg.gatewayHost}/${networkCfg.bridgeIp}"
|
) "/${matrixCfg.gatewayHost}/${networkCfg.bridgeIp}";
|
||||||
++ lib.optional autheliaCfg.enable "/${autheliaCfg.domain}/${networkCfg.bridgeIp}";
|
|
||||||
# DHCP pool covering all usable host addresses on the bridge
|
# DHCP pool covering all usable host addresses on the bridge
|
||||||
# subnet — bounds computed by hive-network.nix from
|
# subnet — bounds computed by hive-network.nix from
|
||||||
# bridgeIp/bridgePrefixLength. All containers (agents and service
|
# bridgeIp/bridgePrefixLength. All containers (agents and service
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
cfg, # services.hyperhive.gateway
|
cfg, # services.hyperhive.gateway
|
||||||
forgeCfg,
|
forgeCfg,
|
||||||
matrixCfg,
|
matrixCfg,
|
||||||
autheliaCfg, # services.hyperhive.swarm.authelia
|
|
||||||
hyperhiveDomain,
|
hyperhiveDomain,
|
||||||
dashboardDist,
|
dashboardDist,
|
||||||
swaggerUiTheme, # nix/packages/swagger-ui-theme.nix: has index.html + hyperhive-theme.css
|
swaggerUiTheme, # nix/packages/swagger-ui-theme.nix: has index.html + hyperhive-theme.css
|
||||||
|
|
@ -124,42 +123,6 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Authelia sub-domain vhost. `server_name = authelia.domain`, all of
|
|
||||||
# `/` → authelia. Empty attrset unless THIS host runs the container:
|
|
||||||
# every hive knows the swarm's `authelia.url`, but only the one
|
|
||||||
# serving it may claim the name — a client hive declaring this vhost
|
|
||||||
# would answer for a service it does not run.
|
|
||||||
#
|
|
||||||
# ⚠️ The server name must be exactly `autheliaCfg.domain`, not a
|
|
||||||
# near-miss: authelia validates `authelia_url ⊂ session cookie domain`
|
|
||||||
# at STARTUP, so a mismatch is a container that refuses to boot rather
|
|
||||||
# than a login that misbehaves.
|
|
||||||
#
|
|
||||||
# ⚠️ And deliberately NO `dashboardAuth` here. That block is the
|
|
||||||
# gateway's `auth_basic`; applying it to the SSO provider would put
|
|
||||||
# the login page behind the login mechanism it exists to replace.
|
|
||||||
autheliaVhost = lib.optionalAttrs autheliaCfg.enable {
|
|
||||||
"${autheliaCfg.domain}" = (vhostTlsFor autheliaCfg.domain) // {
|
|
||||||
listen = vhostListen;
|
|
||||||
extraConfig = securityHeaders;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://127.0.0.1:${toString autheliaCfg.port}/";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_buffering off;
|
|
||||||
# authelia decides by the ORIGINAL request, not by the hop it
|
|
||||||
# sees — the login redirect and the session cookie's domain
|
|
||||||
# both derive from these. Without them every request looks
|
|
||||||
# like it arrived at 127.0.0.1 over plain http.
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
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;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Matrix sub-domain vhost. `server_name = matrixCfg.gatewayHost`.
|
# Matrix sub-domain vhost. `server_name = matrixCfg.gatewayHost`.
|
||||||
# `/_matrix/*` → tuwunel (CORS *, 50M body cap, 1h long-poll
|
# `/_matrix/*` → tuwunel (CORS *, 50M body cap, 1h long-poll
|
||||||
# timeout). `/` serves fluffychat or 404 if GUI off. nginx
|
# timeout). `/` serves fluffychat or 404 if GUI off. nginx
|
||||||
|
|
@ -446,6 +409,5 @@ in
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// forgeVhost
|
// forgeVhost
|
||||||
// autheliaVhost
|
|
||||||
// matrixVhost;
|
// matrixVhost;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue