Moves the Prosody server, xmpp-web frontends (chat/plaza), and Forgejo's wiki-update webhook notifier from pinix to blunix, co-located with Traefik/ACME so TLS comes straight from Traefik's cert store instead of the old manual copy process. pinix's prosody/xmpp-web/webhook modules stay in place but deactivated as a fallback, matching the earlier Forgejo migration's pattern. Implements docs/intent/xmpp-umzug-pinix-blunix.md. Deployed and verified live on blunix (nixos-rebuild switch, chat/plaza returning 200, prosody healthy, agent XMPP listeners reconnected). Two first-bootstrap bugs found and fixed during that verification, both specific to bringing Prosody up on a host it never ran on before: - prosody-certs-sync.service used to call a blocking `systemctl reload-or-restart prosody.service` whenever the cert file differed from what's installed -- including on first activation, where prosody.service's own start job is still queued behind this unit (Requires+After), deadlocking forever. Now only reloads an already-running Prosody; ordering alone brings up a fresh one with the cert just installed. - hosts/blunix/localServices/secrets.nix force-owned the global `bindPW` secret to root with the (previously correct) rationale that it belongs to a pinix-only service. Prosody now runs on blunix too and needs to read it directly as its own LDAP bind config include, so that override no longer applies to it. pinix's own deploy (data migration, DNS/webhook cutover) is separate follow-up work, not part of this commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ANg2L2xUmNJ45t9mcv6HVT
145 lines
6.9 KiB
Markdown
145 lines
6.9 KiB
Markdown
# Prosody
|
|
|
|
Prosody runs on `blunix`, co-located with Traefik/ACME (moved here from
|
|
`pinix` on 2026-09-06, docs/intent/xmpp-umzug-pinix-blunix.md — same
|
|
pinix-outage resilience motivation as the earlier Forgejo move). c2s
|
|
(5222) and s2s (5269) are bound directly on this host's public interface;
|
|
Traefik no longer needs a TCP passthrough for either one, unlike the old
|
|
pinix setup.
|
|
|
|
The service uses the upstream NixOS Prosody module. LDAP authentication is
|
|
enabled by adding `lualdap` to the Prosody package's Lua environment in
|
|
`setup-prosody.nix`; no store paths or copied NixOS module are required.
|
|
LDAP is reached over loopback (`127.0.0.1:3890`) now that LLDAP is on the
|
|
same host, rather than over the Tailnet.
|
|
|
|
The LDAP password and MOTD are included from agenix files at runtime.
|
|
Consequently, the module's build-time configuration check is disabled and
|
|
the live configuration must be checked after activation.
|
|
|
|
## TLS
|
|
|
|
`prosody-certs-sync.service` (in `setup-prosody.nix`) reads the same
|
|
certificate Traefik already obtained for `${domain}` straight out of its
|
|
own ACME store (`/var/lib/traefik/acme.json`) and installs it where
|
|
Prosody expects it (`/var/lib/prosody/certs/`), reloading Prosody only
|
|
when the certificate content actually changed. A systemd timer re-checks
|
|
daily. This replaces the old manual SSH-based copy process the pinix
|
|
setup needed (documented there in a prior revision of this file) — that
|
|
process existed only because Prosody and Traefik/ACME ran on different
|
|
hosts; co-location makes it unnecessary.
|
|
|
|
## Web clients
|
|
|
|
`xmpp-web.nix` builds two frontends from the same pinned xmpp-web release:
|
|
|
|
- `chat.0ff.space` is the registered-account client;
|
|
- `plaza.0ff.space` is the anonymous guest lobby and redirects directly into
|
|
`lobby@muc.0ff.space`.
|
|
|
|
Both builds receive the same generated `0ff-space.css`. Its background comes
|
|
from the shared `hosts/globalServices/branding/0ff-space-background.css`,
|
|
also used by LLDAP and Phanpy. It reproduces the launcher's 15-pixel dotted
|
|
pattern and follows `prefers-color-scheme` for its light and dark variants.
|
|
The stylesheet is copied into each immutable build output and injected into
|
|
its `index.html`; there is no separately managed file below `/var/www`.
|
|
|
|
The module also keeps the launcher's five-color palette in one
|
|
`launcherPalette` attribute set and maps xmpp-web/Bulma's semantic colors to
|
|
it: primary uses strawberry red, danger neon red, success pink, info violet,
|
|
and warning orange. Base, hover, active, and focus colors are replaced during
|
|
both frontend builds, so the upstream teal, blue, and green accents do not
|
|
reappear during interaction.
|
|
|
|
nginx serves the two static frontends and proxies `/xmpp-websocket` to
|
|
Prosody on `127.0.0.1:5280`, all in plain HTTP on loopback
|
|
(`127.0.0.1:8080`, dispatched by Host header). Traefik
|
|
(`traefik/prosody.nix`) terminates TLS publicly and forwards to that
|
|
loopback address — nginx no longer holds a certificate of its own, unlike
|
|
the old pinix setup where it had to (Traefik there could only reach
|
|
Prosody's host over a TCP-TLS passthrough, so TLS had to terminate on
|
|
pinix).
|
|
|
|
Guests authenticate anonymously against `anon.0ff.space` and join
|
|
`lobby@muc.0ff.space`. The room is persistent and
|
|
`lukas@0ff.space` is its owner, so the normal LDAP-backed account can join
|
|
and administer it from Monal without a second account.
|
|
|
|
The MUC archive is retained for 30 days and cleaned every four hours.
|
|
`mod_muc_moderation` is installed from the Prosody community-modules revision
|
|
pinned by nixpkgs and enabled only on `muc.0ff.space`. Clients supporting
|
|
XEP-0425 can therefore retract abusive messages from the room and its archive;
|
|
the moderator must join with an owner or administrator account.
|
|
|
|
## Update notifications
|
|
|
|
Forgejo sends push and pull-request events to the local webhook receiver on
|
|
blunix. The receiver posts short notifications as `forgeBot` to
|
|
`update@muc.0ff.space` using the `vikunja` account.
|
|
The hook target is `http://127.0.0.1:9000/hooks/wiki-update`
|
|
(`hosts/blunix/localServices/webhook.nix`). Forgejo's own repo-side webhook
|
|
URLs (Forgejo's DB, not Nix) for `nixos-config`, `website`, `dashboard`,
|
|
`launcher` need to be repointed here manually — that part of the cutover
|
|
isn't visible to `nix flake check`.
|
|
|
|
The update room is members-only. The bot therefore needs a `member`
|
|
affiliation in the room; its password remains in `go-sendxmpp.age`.
|
|
Room creation and affiliation are one-time `prosodyctl shell` operations —
|
|
see the root `CLAUDE.md`'s MUC section for the exact commands; unaffected
|
|
by this move since the room and its affiliations live in the migrated
|
|
`/var/lib/prosody` data, not in Nix.
|
|
|
|
### Second channel: `agent@bot.0ff.space`
|
|
|
|
Vikunja updates additionally go out as a direct (1:1) message from `vikunja`
|
|
to `agent@bot.0ff.space`, alongside the existing `vikunja@muc.0ff.space` post.
|
|
Vikunja itself stays on pinix and is out of scope for this move (see
|
|
`docs/intent/xmpp-umzug-pinix-blunix.md`, "Explizit ausgeschlossen").
|
|
|
|
`agent@bot.0ff.space` is intentionally never added to a human XMPP client:
|
|
`go-sendxmpp` sends plaintext (no OMEMO), so a client like Monal shows this
|
|
conversation unencrypted next to otherwise-encrypted chats.
|
|
|
|
The `agent-xmpp-listener` (`hosts/blunix/localServices/agent-codex.nix`)
|
|
already ran on this host before Prosody moved here; it connects to
|
|
`bot.${domain}` by hostname, which now resolves to Prosody running on the
|
|
very same host instead of over the Tailnet. No configuration change was
|
|
needed for it as part of this move — verify after activation with:
|
|
|
|
```bash
|
|
journalctl -u agent-xmpp-listener
|
|
```
|
|
|
|
See `hosts/blunix/localServices/agent-codex/README.md` for the rest of that
|
|
agent's design (queueing, session mapping, sandboxing).
|
|
|
|
## Enable and deploy
|
|
|
|
Already wired into `../default.nix`:
|
|
|
|
```nix
|
|
./prosody/setup-prosody.nix
|
|
./xmpp-web.nix
|
|
```
|
|
|
|
Build and deploy like any other blunix change — `sudo nixos-rebuild switch
|
|
--flake .#blunix` when run from blunix itself (see the root `CLAUDE.md`).
|
|
|
|
Before the very first activation, the actual data cutover still needs to
|
|
happen as a separate step (not part of this module's declarative config):
|
|
stop pinix's Prosody, `rsync /var/lib/prosody` (accounts, roster, MUC
|
|
archive, uploads, the TLS certs directory before the sync service replaces
|
|
them) from pinix to blunix, then activate this module. This mirrors the
|
|
Forgejo migration's own two-step cutover.
|
|
|
|
## pinix fallback
|
|
|
|
`hosts/pinix/localServices/prosody/setup-prosody.nix` and
|
|
`hosts/pinix/localServices/xmpp-web.nix` stay in place, deliberately not
|
|
deleted. `systemd.services.prosody.enable = false;` is what actually stops
|
|
the XMPP backend there — the same fallback pattern the Forgejo move
|
|
established. nginx has no equivalent per-vhost disable option, so its two
|
|
now-superseded `chat`/`plaza` vhosts stay declared as before; they simply
|
|
receive no traffic any more since blunix's TCP passthrough to them was
|
|
removed. That module's own README still describes the old manual TLS copy
|
|
process; it applied only to that now-inactive setup.
|