# Moved from hosts/pinix/localServices/xmpp-web.nix on 2026-09-06 # (docs/intent/xmpp-umzug-pinix-blunix.md), alongside setup-prosody.nix. # nginx no longer terminates TLS itself: Traefik already does that for # every other co-located blunix service (see traefik/prosody.nix), so # these vhosts are now plain HTTP behind it on loopback, and no longer # need their own certificate or public firewall opening. { config, lib, pkgs, ... }: let xmppWebVersion = "0.12.0"; launcherPalette = { red = "#ff0026"; strawberry = "#d91e4d"; pink = "#ff0094"; violet = "#e000ff"; orange = "#ff5a00"; }; xmppWebArchive = pkgs.fetchurl { url = "https://github.com/nioc/xmpp-web/releases/download/${xmppWebVersion}/xmpp-web-${xmppWebVersion}.tar.gz"; hash = "sha256-IL9MLf75yP7gqMaV6vzYVXlGqWwIlbdmEK5wH831Ybc="; }; xmppWebCustomCss = pkgs.writeText "xmpp-web-0ff-space.css" '' ${builtins.readFile ../../globalServices/branding/0ff-space-background.css} html { --palette-1: ${launcherPalette.red}; --palette-2: ${launcherPalette.strawberry}; --palette-3: ${launcherPalette.pink}; --palette-4: ${launcherPalette.violet}; --palette-5: ${launcherPalette.orange}; } body, #body, .hero.is-fullheight, .hero.is-fullheight-with-navbar { background-color: transparent !important; background-image: none !important; } /* Registered/Login.vue's
Öffentlicher Chat auf 0ff.space. Wähle einen Nicknamen und schreibe ohne Account mit.
', } ''; # Registered-only client for real 0ff.space accounts (same LDAP-backed # auth Monal uses on the main vhost) -- no guest access, no forced # redirect into the lobby, just a normal client landing on the user's # own roster/joined rooms. chatConfigJs = '' // eslint-disable-next-line no-unused-vars, no-var var config = { name: '0ff.space chat', transports: { websocket: 'wss://chat.${config.domain}/xmpp-websocket', }, hasGuestAccess: false, hasRegisteredAccess: true, isTransportsUserAllowed: false, hasHttpAutoDiscovery: false, resource: '0ff.space Web Chat', defaultDomain: '${config.domain}', defaultMuc: 'muc.${config.domain}', isStylingDisabled: false, hasSendingEnterKey: true, connectTimeout: 5000, logoUrl: "", sso: { endpoint: false, jidHeader: 'jid', passwordHeader: 'password', }, } ''; xmppWebPlaza = mkXmppWeb { name = "plaza"; configJs = plazaConfigJs; autoJoinLobby = true; }; xmppWebChat = mkXmppWeb { name = "chat"; configJs = chatConfigJs; }; websocketLocation = { proxyPass = "http://127.0.0.1:5280/xmpp-websocket"; proxyWebsockets = true; extraConfig = '' proxy_read_timeout 900s; ''; }; rootLocation = { tryFiles = "$uri $uri/ /index.html"; }; # Both vhosts share one plain-HTTP listen socket; nginx dispatches by # Host header the same way it dispatched by SNI before, just without a # TLS handshake of its own -- Traefik (traefik/prosody.nix) already # terminated TLS before the request reaches here. listenOn8080 = [ { addr = "127.0.0.1"; port = 8080; } ]; in { services.nginx = { enable = true; recommendedProxySettings = true; virtualHosts."plaza.${config.domain}" = { listen = listenOn8080; root = xmppWebPlaza; locations."/" = rootLocation; locations."/xmpp-websocket" = websocketLocation; }; virtualHosts."chat.${config.domain}" = { listen = listenOn8080; root = xmppWebChat; locations."/" = rootLocation; locations."/xmpp-websocket" = websocketLocation; }; }; services.prosody.virtualHosts."anon.${config.domain}" = { enabled = true; domain = "anon.${config.domain}"; extraConfig = '' authentication = "anonymous" allow_anonymous_s2s = false modules_enabled = { "websocket"; } modules_disabled = { "bookmarks"; "cloud_notify"; "mam"; "pep"; "private"; "proxy65"; "register"; "roster"; "vcard_legacy"; } http_host = "plaza.${config.domain}" http_external_url = "https://plaza.${config.domain}/" http_paths = { websocket = "/xmpp-websocket"; } cross_domain_websocket = { "https://plaza.${config.domain}"; } ''; ssl = { cert = "/var/lib/prosody/certs/${config.domain}.crt.pem"; key = "/var/lib/prosody/certs/${config.domain}.key.pem"; }; }; }