290 lines
10 KiB
Nix
290 lines
10 KiB
Nix
# example configs:
|
|
# - official: <https://prosody.im/doc/example_config>
|
|
# - nixos: <https://github.com/kittywitch/nixfiles/blob/main/services/prosody.nix>
|
|
# config options:
|
|
# - <https://prosody.im/doc/configure>
|
|
#
|
|
# modules:
|
|
# - main: <https://prosody.im/doc/modules>
|
|
# - community: <https://modules.prosody.im/index.html>
|
|
#
|
|
# debugging:
|
|
# - logging:
|
|
# - enable `stanza_debug` module
|
|
# - enable `log.debug = "*syslog"` in extraConfig
|
|
# - interactive:
|
|
# - `telnet localhost 5582` (this is equal to `prosodyctl shell` -- but doesn't hang)
|
|
# - `watch:stanzas(target_spec, filter)` -> to log stanzas, for version > 0.12
|
|
# - console docs: <https://prosody.im/doc/console>
|
|
# - can modify/inspect arbitrary internals (lua) by prefixing line with `> `
|
|
# - e.g. `> _G` to print all globals
|
|
#
|
|
# sanity checks:
|
|
# - `sudo -u prosody -g prosody prosodyctl check connectivity`
|
|
# - `sudo -u prosody -g prosody prosodyctl check turn`
|
|
# - `sudo -u prosody -g prosody prosodyctl check turn -v --ping=stun.conversations.im`
|
|
# - checks that my stun/turn server is usable by clients of conversations.im (?)
|
|
# - `sudo -u prosody -g prosody prosodyctl check` (dns, config, certs)
|
|
#
|
|
#
|
|
# create users with:
|
|
# - `sudo -u prosody prosodyctl adduser colin@uninsane.org`
|
|
#
|
|
#
|
|
# federation/support matrix:
|
|
# - nixnet.services (runs ejabberd):
|
|
# - WORKS: sending and receiving PMs and calls (2023/10/15)
|
|
# - N.B.: it didn't originally work; was solved by disabling the lua-unbound DNS option & forcing the system/local resolver
|
|
# - cheogram (XMPP <-> SMS gateway):
|
|
# - WORKS: sending and receiving PMs, images (2023/10/15)
|
|
# - PARTIAL: calls (xmpp -> tel works; tel -> xmpp fails)
|
|
# - maybe i need to setup stun/turn
|
|
#
|
|
# TODO:
|
|
# - enable push notifications (mod_cloud_notify)
|
|
# - optimize coturn (e.g. move off of the VPN!)
|
|
# - ensure muc is working
|
|
# - enable file uploads
|
|
# - "upload.xmpp.uninsane.org:http_upload: URL: <https://upload.xmpp.uninsane.org:5281/upload> - Ensure this can be reached by users"
|
|
# - disable or fix bosh (jabber over http):
|
|
# - "certmanager: No certificate/key found for client_https port 0"
|
|
|
|
{ lib, pkgs, ... }:
|
|
|
|
let
|
|
# enables very verbose logging
|
|
enableDebug = false;
|
|
in
|
|
{
|
|
sane.persist.sys.byStore.plaintext = [
|
|
{ user = "prosody"; group = "prosody"; path = "/var/lib/prosody"; method = "bind"; }
|
|
];
|
|
sane.ports.ports."5000" = {
|
|
protocol = [ "tcp" ];
|
|
visibleTo.lan = true;
|
|
visibleTo.wan = true;
|
|
description = "colin-xmpp-prosody-fileshare-proxy65";
|
|
};
|
|
sane.ports.ports."5222" = {
|
|
protocol = [ "tcp" ];
|
|
visibleTo.lan = true;
|
|
visibleTo.wan = true;
|
|
description = "colin-xmpp-client-to-server";
|
|
};
|
|
sane.ports.ports."5223" = {
|
|
protocol = [ "tcp" ];
|
|
visibleTo.lan = true;
|
|
visibleTo.wan = true;
|
|
description = "colin-xmpps-client-to-server"; # XMPP over TLS
|
|
};
|
|
sane.ports.ports."5269" = {
|
|
protocol = [ "tcp" ];
|
|
visibleTo.wan = true;
|
|
description = "colin-xmpp-server-to-server";
|
|
};
|
|
sane.ports.ports."5270" = {
|
|
protocol = [ "tcp" ];
|
|
visibleTo.wan = true;
|
|
description = "colin-xmpps-server-to-server"; # XMPP over TLS
|
|
};
|
|
sane.ports.ports."5280" = {
|
|
protocol = [ "tcp" ];
|
|
visibleTo.lan = true;
|
|
visibleTo.wan = true;
|
|
description = "colin-xmpp-bosh";
|
|
};
|
|
sane.ports.ports."5281" = {
|
|
protocol = [ "tcp" ];
|
|
visibleTo.lan = true;
|
|
visibleTo.wan = true;
|
|
description = "colin-xmpp-prosody-https"; # necessary?
|
|
};
|
|
|
|
users.users.prosody.extraGroups = [
|
|
"nginx" # provide access to certs
|
|
"ntfy-sh" # access to secret ntfy topic
|
|
];
|
|
|
|
security.acme.certs."uninsane.org".extraDomainNames = [
|
|
"xmpp.uninsane.org"
|
|
"conference.xmpp.uninsane.org"
|
|
"upload.xmpp.uninsane.org"
|
|
];
|
|
|
|
# exists so the XMPP server's cert can obtain altNames for all its resources
|
|
services.nginx.virtualHosts."xmpp.uninsane.org" = {
|
|
useACMEHost = "uninsane.org";
|
|
};
|
|
services.nginx.virtualHosts."conference.xmpp.uninsane.org" = {
|
|
useACMEHost = "uninsane.org";
|
|
};
|
|
services.nginx.virtualHosts."upload.xmpp.uninsane.org" = {
|
|
useACMEHost = "uninsane.org";
|
|
};
|
|
|
|
sane.dns.zones."uninsane.org".inet = {
|
|
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
|
|
A."xmpp" = "%ANATIVE%";
|
|
CNAME."conference.xmpp" = "xmpp";
|
|
CNAME."upload.xmpp" = "xmpp";
|
|
|
|
# _Service._Proto.Name TTL Class SRV Priority Weight Port Target
|
|
# - <https://xmpp.org/extensions/xep-0368.html>
|
|
# something's requesting the SRV records for conference.xmpp, so let's include it
|
|
# nothing seems to request XMPP SRVs for the other records (except @)
|
|
# lower numerical priority field tells clients to prefer this method
|
|
SRV."_xmpps-client._tcp.conference.xmpp" = "3 50 5223 xmpp";
|
|
SRV."_xmpps-server._tcp.conference.xmpp" = "3 50 5270 xmpp";
|
|
SRV."_xmpp-client._tcp.conference.xmpp" = "5 50 5222 xmpp";
|
|
SRV."_xmpp-server._tcp.conference.xmpp" = "5 50 5269 xmpp";
|
|
|
|
SRV."_xmpps-client._tcp" = "3 50 5223 xmpp";
|
|
SRV."_xmpps-server._tcp" = "3 50 5270 xmpp";
|
|
SRV."_xmpp-client._tcp" = "5 50 5222 xmpp";
|
|
SRV."_xmpp-server._tcp" = "5 50 5269 xmpp";
|
|
};
|
|
|
|
# help Prosody find its certificates.
|
|
# pointing it to /var/lib/acme doesn't quite work because it expects the private key
|
|
# to be named `privkey.pem` instead of acme's `key.pem`
|
|
# <https://prosody.im/doc/certificates#automatic_location>
|
|
sane.fs."/etc/prosody/certs/uninsane.org/fullchain.pem" = {
|
|
symlink.target = "/var/lib/acme/uninsane.org/fullchain.pem";
|
|
wantedBeforeBy = [ "prosody.service" ];
|
|
};
|
|
sane.fs."/etc/prosody/certs/uninsane.org/privkey.pem" = {
|
|
symlink.target = "/var/lib/acme/uninsane.org/key.pem";
|
|
wantedBeforeBy = [ "prosody.service" ];
|
|
};
|
|
|
|
services.prosody = {
|
|
enable = true;
|
|
package = pkgs.prosody.override {
|
|
# XXX(2023/10/15): build without lua-unbound support.
|
|
# this forces Prosody to fall back to the default Lua DNS resolver, which seems more reliable.
|
|
# fixes errors like "unbound.queryXYZUV: Resolver error: out of memory"
|
|
# related: <https://issues.prosody.im/1737#comment-11>
|
|
lua.withPackages = selector: pkgs.lua.withPackages (p:
|
|
selector (p // { luaunbound = null; })
|
|
);
|
|
# withCommunityModules = [ "turncredentials" ];
|
|
};
|
|
admins = [ "colin@uninsane.org" ];
|
|
# allowRegistration = false; # defaults to false
|
|
|
|
muc = [
|
|
{
|
|
domain = "conference.xmpp.uninsane.org";
|
|
}
|
|
];
|
|
uploadHttp.domain = "upload.xmpp.uninsane.org";
|
|
|
|
virtualHosts = {
|
|
# "Prosody requires at least one enabled VirtualHost to function. You can
|
|
# safely remove or disable 'localhost' once you have added another."
|
|
# localhost = {
|
|
# domain = "localhost";
|
|
# enabled = true;
|
|
# };
|
|
"xmpp.uninsane.org" = {
|
|
domain = "uninsane.org";
|
|
enabled = true;
|
|
};
|
|
};
|
|
|
|
## modules:
|
|
# these are enabled by default, via <repo:nixos/nixpkgs:/pkgs/servers/xmpp/prosody/default.nix>
|
|
# - cloud_notify
|
|
# - http_upload
|
|
# - vcard_muc
|
|
# these are enabled by the module defaults (services.prosody.modules.<foo>)
|
|
# - admin_adhoc
|
|
# - blocklist
|
|
# - bookmarks
|
|
# - carbons
|
|
# - cloud_notify
|
|
# - csi
|
|
# - dialback
|
|
# - disco
|
|
# - http_files
|
|
# - mam
|
|
# - pep
|
|
# - ping
|
|
# - private
|
|
# - XEP-0049: let clients store arbitrary (private) data on the server
|
|
# - proxy65
|
|
# - XEP-0065: allow server to proxy file transfers between two clients who are behind NAT
|
|
# - register
|
|
# - roster
|
|
# - saslauth
|
|
# - smacks
|
|
# - time
|
|
# - tls
|
|
# - uptime
|
|
# - vcard_legacy
|
|
# - version
|
|
|
|
extraPluginPaths = [ ./modules ];
|
|
|
|
extraModules = [
|
|
# admin_shell: allows `prosodyctl shell` to work
|
|
# see: <https://prosody.im/doc/modules/mod_admin_shell>
|
|
# see: <https://prosody.im/doc/console>
|
|
"admin_shell"
|
|
"admin_telnet" #< needed by admin_shell
|
|
# lastactivity: XEP-0012: allow users to query how long another user has been idle for
|
|
# - not sure why i enabled this; think it was in someone's config i referenced
|
|
"lastactivity"
|
|
# allows prosody to share TURN/STUN secrets with XMPP clients to provide them access to the coturn server.
|
|
# see: <https://prosody.im/doc/coturn>
|
|
"turn_external"
|
|
# legacy coturn integration
|
|
# see: <https://modules.prosody.im/mod_turncredentials.html>
|
|
# "turncredentials"
|
|
"sane_ntfy"
|
|
] ++ lib.optionals enableDebug [
|
|
"stanza_debug" #< logs EVERY stanza as debug: <https://prosody.im/doc/modules/mod_stanza_debug>
|
|
];
|
|
|
|
extraConfig = ''
|
|
local function readAll(file)
|
|
local f = assert(io.open(file, "rb"))
|
|
local content = f:read("*all")
|
|
f:close()
|
|
-- remove trailing newline
|
|
return string.gsub(content, "%s+", "")
|
|
end
|
|
|
|
-- logging docs:
|
|
-- - <https://prosody.im/doc/logging>
|
|
-- - <https://prosody.im/doc/advanced_logging>
|
|
-- levels: debug, info, warn, error
|
|
log = {
|
|
${if enableDebug then "debug" else "info"} = "*syslog";
|
|
}
|
|
|
|
-- see: <https://prosody.im/doc/certificates#automatic_location>
|
|
-- try to solve: "certmanager: Error indexing certificate directory /etc/prosody/certs: cannot open /etc/prosody/certs: No such file or directory"
|
|
-- only, this doesn't work because prosody doesn't like acme's naming scheme
|
|
-- certificates = "/var/lib/acme"
|
|
|
|
c2s_direct_tls_ports = { 5223 }
|
|
s2s_direct_tls_ports = { 5270 }
|
|
|
|
turn_external_host = "turn.uninsane.org"
|
|
turn_external_secret = readAll("/var/lib/coturn/shared_secret.bin")
|
|
-- turn_external_user = "prosody"
|
|
|
|
-- legacy mod_turncredentials integration
|
|
-- turncredentials_host = "turn.uninsane.org"
|
|
-- turncredentials_secret = readAll("/var/lib/coturn/shared_secret.bin")
|
|
|
|
ntfy_binary = "${pkgs.ntfy-sh}/bin/ntfy"
|
|
ntfy_topic = readAll("/run/secrets/ntfy-sh-topic")
|
|
|
|
-- s2s_require_encryption = true
|
|
-- c2s_require_encryption = true
|
|
'';
|
|
};
|
|
}
|