Moves the authelia vhost out of the gateway's vhosts.nix and its `address=` rule out of dnsmasq.nix, into swarm-authelia.nix. Both land inside that module's existing `cfg.enable` guard, which is the load-bearing part: every hive in a swarm knows `authelia.url`, but only the host that RUNS the container may claim the name. A client hive declaring the vhost would answer for a service it does not run, and publishing the DNS record would point every agent on its bridge at that wrong answer. The kit grows a fourth member, `errorPages`, because the vhost aims its 502/503/504 at the gateway's styled sso-unavailable page. Republished rather than imported per module: a service rendering its own would drift from the rest of the gateway the first time the theme changed.
105 lines
5.1 KiB
Nix
105 lines
5.1 KiB
Nix
# Hive-internal DNS resolver + DHCP, running on the host alongside the
|
|
# gateway's nginx — single front-door for both DNS and HTTP, and no
|
|
# container of its own. Listens on the bridge interface from
|
|
# `services.hyperhive.network`; authoritative for the hive domain +
|
|
# sub-domains, forwards everything else upstream. Returns the
|
|
# `services.dnsmasq` value (see ./default.nix); the DHCP pool bounds
|
|
# are computed by hive-network.
|
|
{
|
|
lib,
|
|
cfg, # services.hyperhive.gateway
|
|
networkCfg,
|
|
matrixCfg,
|
|
uiCfg,
|
|
hyperhiveDomain,
|
|
}:
|
|
{
|
|
enable = true;
|
|
# ON for its *plumbing*, not for the address it publishes.
|
|
#
|
|
# This flag does two separable things upstream. The one that matters
|
|
# here: it points dnsmasq's own upstream servers at a SEPARATE file
|
|
# (`resolv-file = /etc/dnsmasq-resolv.conf`, kept current by
|
|
# resolvconf). Without that, dnsmasq reads `/etc/resolv.conf` for its
|
|
# upstreams — so the moment the host's resolver is pointed at dnsmasq,
|
|
# every non-hive query goes in a circle.
|
|
#
|
|
# The other thing it does is publish `127.0.0.1` as the host's
|
|
# nameserver, which is the wrong address for this hive: see the
|
|
# `nameservers` override in ./default.nix, where the reason lives.
|
|
resolveLocalQueries = true;
|
|
settings = {
|
|
# Bind only on the bridge interface (and lo for health-checks).
|
|
# Outside hosts can't even see the listener.
|
|
interface = [
|
|
networkCfg.bridgeName
|
|
"lo"
|
|
];
|
|
bind-interfaces = true;
|
|
port = 53;
|
|
# Authoritative for the hive domain via the `address` rules below —
|
|
# must not fall back to the host's /etc/hosts. dnsmasq reads
|
|
# /etc/hosts by default, and `gateway.localHostsEntry` populates it
|
|
# with 127.0.0.1 for every hive name (host-side dev convenience,
|
|
# see default.nix). Since moving dnsmasq onto the host, that
|
|
# file is now the *same* /etc/hosts dnsmasq reads for agent queries
|
|
# — its entries win over `address=`, so every agent resolves the
|
|
# hive's own domains back to itself (127.0.0.1 in its own netns)
|
|
# instead of the bridge IP, and can't reach the forge, matrix, or
|
|
# dashboard at all. `no-hosts = true` keeps the authoritative
|
|
# `address=` rules in charge for containers while leaving
|
|
# `networking.hosts` (the actual /etc/hosts entries) untouched for
|
|
# host-side browsing.
|
|
no-hosts = true;
|
|
# Hive authoritative records — answer queries for the hive domain
|
|
# + its sub-domains with the bridge IP, where nginx is reachable
|
|
# from every container netns.
|
|
#
|
|
# The matrix entry is redundant in the common case where
|
|
# `matrix.gatewayHost` is a sub-domain of `hyperhive.domain` —
|
|
# dnsmasq's `/<domain>/` rule already matches sub-domains. Kept
|
|
# explicit because an operator can override it to a cross-domain
|
|
# hostname (e.g. `git.example.com` for the forge); listing such a
|
|
# name explicitly keeps that case routed without an extra config
|
|
# block.
|
|
address = [
|
|
"/${hyperhiveDomain}/${networkCfg.bridgeIp}"
|
|
]
|
|
++ lib.optional (
|
|
matrixCfg.enable && matrixCfg.gatewayHost != null
|
|
) "/${matrixCfg.gatewayHost}/${networkCfg.bridgeIp}"
|
|
# The swarm UI's name is the swarm APEX by default — a sibling of
|
|
# the three above, not a child of anything this resolver already
|
|
# answers for, so the `/<hive domain>/` rule does not cover it.
|
|
#
|
|
# Published to agents deliberately (mara: publishing it is fine).
|
|
# Reachability is not the access control here: the vhost's
|
|
# `auth_request` + authelia's `group:operators` rule are, and an
|
|
# agent that resolves the name still cannot open the page.
|
|
++ lib.optional uiCfg.enable "/${uiCfg.domain}/${networkCfg.bridgeIp}"
|
|
# Names contributed by the modules that own them
|
|
# (`gateway.localNames`). Same address as everything above — the
|
|
# bridge IP is the gateway's answer for anything it fronts, and a
|
|
# contributing module neither knows nor should know it.
|
|
#
|
|
# `unique` is not tidiness: two modules claiming one name would
|
|
# otherwise emit two `address=` rules for it, and dnsmasq resolves
|
|
# that by precedence rather than by complaining. An assertion in
|
|
# ./default.nix makes the collision loud instead.
|
|
++ map (name: "/${name}/${networkCfg.bridgeIp}") (lib.unique cfg.localNames);
|
|
# DHCP pool covering all usable host addresses on the bridge
|
|
# subnet — bounds computed by hive-network.nix from
|
|
# bridgeIp/bridgePrefixLength. All containers (agents and service
|
|
# containers such as hive-ci) receive their IPs dynamically.
|
|
dhcp-range = "${networkCfg.dhcpRangeStart},${networkCfg.dhcpRangeEnd},1h";
|
|
dhcp-leasefile = "/var/lib/dnsmasq/dnsmasq.leases";
|
|
# No explicit upstream: non-hive queries follow dnsmasq's
|
|
# resolv.conf default — the host's own `/etc/resolv.conf`, so the
|
|
# hive always uses the host's resolvers and follows them live with
|
|
# no copy to go stale. Deliberately no fallback
|
|
# `server=`: dnsmasq queries
|
|
# all known upstreams in parallel, so a hardcoded public resolver
|
|
# would take a share of *normal* traffic, not just fill in when the
|
|
# host file is empty.
|
|
};
|
|
}
|