# The matrix homeserver: implementation notes What the homeserver's NixOS module does that an operator never sees: the hive-side code it replaced, the evaluation assertions it makes, and the fluffychat-web build fixes. The operator's view of the homeserver is in [the swarm matrix page](../../2-handbook/swarm/matrix.md). ## Retired hive-side matrix code Earlier versions of hive-c0re created a private "hive" Matrix Space and a `hive-chat` room, invited every agent to both, kept the hive's sender token on disk and offered `hivectl matrix invite`. Matrix is swarm-level, so hive-c0re dropped all of it and no longer talks to the homeserver. The Space, the room and the files `/var/lib/hyperhive/matrix/{access-token,space-room-id,chat-room-id}` are harmless leftovers, so delete them by hand if you like. ## Assertion rationale `config.assertions` in this module fail eval early rather than ship surprising behaviour: - **`services.hyperhive.swarm.matrix.gatewayHost != ""`** — same footgun as `forge.domain`: empty string renders `.`-shaped garbage in both nginx `server_name` (treated as wildcard catch-all, surprising) and `/etc/hosts` (malformed entry). `null` is the right opt-out shape; a config assertion rejects empty string explicitly. SSO is unconditional, so the three below are requirements of running a homeserver at all rather than of a setting: - **Keep `deploy.matrix.sso.clientSecretFile` set** — it defaults to `/run/hive-matrix-oidc/.secret` wherever the homeserver runs, and `swarm-bao-matrix-oidc` writes the secret there from the swarm secret store under matrix-ctl's leaf. The path is on the host's tmpfs, so every reboot fetches the secret again and it never reaches persistent disk. After a reboot the homeserver doesn't start until the store answers; the store-retry timer then starts it with no manual step. A path outside `/run/hive-matrix-oidc/`, or a null, fails at eval, not at boot: tuwunel reads its identity providers from the config file, so a half-configured one can stop the homeserver from starting outright rather than merely hiding a login button. - **Set `swarm.authelia.url`** — without a provider URL there is nothing to discover against. - **Set `swarm.matrix.gatewayHost != null`** — the SSO callback URL is format-locked to `/_matrix/client/unstable/login/sso/callback/`, and the identity provider needs a public name to redirect the browser to. `server_name`'s own bogus-value guard lives in `hive-network.nix` (`services.hyperhive.domain != null`), not here — see [`docs/4-implementation/networking/network.md`](network.md). ## fluffychat-web build fixes `pkgs.fluffychat-web` ships from `flutter341.buildFlutterApplication`, which has two upstream gaps for fluffychat's web target: - The dart web-worker entry point (`web/native_executor.dart`) isn't compiled — `buildFlutterApplication` only runs `flutter build web` on the main entry. - `native_imaging`'s C source isn't built — emscripten isn't a flutter-builder native build input. Both fixed in `nix/host-modules/hive-matrix.nix` via two derivations: - **`fluffychat-web-imaging`** builds `Imaging.{js,wasm}` from the `native_imaging` C source via `pkgs.emscripten`. Source comes from `pkgs.fluffychat-web.passthru.pubspecLock.dependencySources.native_imaging` — already in the build closure of the flutter app, so no parallel hash pin and version autosyncs with nixpkgs bumps. Build closure is ~3.6 GiB (emscripten LLVM); runtime closure is just the two output files. `dontConfigure = true` because cmake runs inside `js/Makefile` via `emcmake cmake`, not at the package root. The build script needs `HOME` + `EM_CACHE` writable for emscripten's on-demand sysroot build (libc, libc++ → wasm). - **`fluffychat-web-fixed`** is `pkgs.fluffychat-web` plus a `postInstall` patch that (a) compiles `web/native_executor.dart` via `dart compile js` (dart from the flutter341 closure, no incremental cost) and (b) installs `fluffychat-web-imaging`'s outputs into `$out`. Two subtle details worth knowing before touching either derivation: - **`make -C js`** instead of `cd js; make` — keeps the build-phase pwd at the source root so `installPhase` doesn't have to know about the cd. Robust against future reorders / `dontBuild`. - **`web/native_executor.dart`** as a build-CWD-relative path, _not_ `$src/web/...` — `dart`'s `package_config.json` walk-up needs to hit `buildFlutterApplication`'s pub-get output (`.dart_tool/` in the build CWD). Walking up from a read-only `$src/` store path finds no `.dart_tool/` and errors with "Couldn't resolve the package 'matrix'." Drop both derivations when nixpkgs's flutter builder grows worker - emcc support upstream. Mount point is `chat./` (the `gatewayHost` vhost); upstream `--base-href "/"` is correct at sub-domain root, no override.