1 { pkgs, lib, config, inputs, hosts, ipv4, ... }:
3 inherit (config) networking;
4 inherit (config.services) prosody;
5 inherit (hosts.mermet.config.services) coturn;
11 networking.nftables.ruleset = ''
12 add rule inet filter net2fw tcp dport {5222,5269} counter accept comment "XMPP"
13 add rule inet filter net2fw tcp dport 5000 counter accept comment "XMPP XEP-0065 File Transfer Proxy"
14 add rule inet filter net2fw tcp dport {${lib.concatMapStringsSep "," toString prosody.httpsPorts}} counter accept comment "XMPP HTTPS"
15 add rule inet filter fw2net meta skuid ${prosody.user} counter accept comment "Prosody"
18 services.upnpc.redirections =
20 { description = "XMPP";
21 externalPort = 5222; protocol = "TCP";
23 service.wantedBy = ["prosody.service"];
24 service.partOf = ["prosody.service"];
26 { description = "XMPP";
27 externalPort = 5269; protocol = "TCP";
29 service.wantedBy = ["prosody.service"];
30 service.partOf = ["prosody.service"];
32 { description = "XMPP-FTP";
33 externalPort = 5000; protocol = "TCP";
35 service.wantedBy = ["prosody.service"];
36 service.partOf = ["prosody.service"];
38 ] ++ map (externalPort: {
39 description = "XMPP-HTTPS";
40 inherit externalPort; protocol="TCP";
42 service.wantedBy = ["prosody.service"];
43 service.partOf = ["prosody.service"];
44 }) prosody.httpsPorts;
47 services.tor.relay.hiddenServices."${networking.domain}/xmpp".map = [ 5222 5269 5000 ] ++ prosody.httpsPorts;
49 users.groups.acme.members = [ prosody.user ];
50 security.acme.certs."${networking.domain}" = {
51 postRun = "systemctl reload prosody";
53 fileSystems."/var/lib/prosody" = {
54 device = "rpool/var/prosody";
57 services.sanoid.datasets = {
58 "rpool/var/prosody" = {
59 use_template = [ "snap" ];
63 systemd.services.prosody = {
64 wants = [ "acme-selfsigned-${networking.domain}.service" "acme-${networking.domain}.service"];
65 after = [ "acme-selfsigned-${networking.domain}.service" ];
67 # sudo -u prosody prosodyctl check
70 xmppComplianceSuite = true;
78 server_contact_info = true;
79 watchregistrations = true;
90 -- Listen only in IPv4 until hosting provider's IPv6 works well.
91 interfaces = { "0.0.0.0" }
92 c2s_interfaces = { "0.0.0.0" }
94 --abuse = { "mailto:abuse@${networking.domain}", "xmpp:abuse@${networking.domain}" };
95 --admin = { "mailto:admin@${networking.domain}", "xmpp:admin@${networking.domain}" };
96 --feedback = { "http://${networking.domain}/feedback.php", "mailto:feedback@${networking.domain}", "xmpp:feedback@${networking.domain}" };
97 --sales = { "xmpp:bard@${networking.domain}" };
98 --security = { "xmpp:security@${networking.domain}" };
99 --support = { "http://${networking.domain}/support.php", "xmpp:support@${networking.domain}" };
101 legacy_ssl_ports = { 5222 }
103 turncredentials_host = "turn.${networking.domain}"
104 turncredentials_port = 3478
105 turncredentials_secret = "${lib.removeSuffix "\n" (builtins.readFile (inputs.secrets + "/coturn/static-auth-secret"))}";
106 smacks_enabled_s2s = true;
107 smacks_s2s_resend = true;
109 --http_files_dir = "/var/lib/prosody/files"
110 --http_external_url = "https://tmp.${networking.domain}:5281"
111 --https_certificate = "/var/lib/acme/${networking.domain}/fullchain.pem"
112 --https_key = "/var/lib/acme/${networking.domain}/key.pem"
113 --certificates = "/var/lib/acme"
116 Component "proxy65.${networking.domain}" "proxy65"
117 proxy65_address = "proxy65.${networking.domain}"
118 proxy65_acl = { "${networking.domain}" }
120 Component "biboumi.${networking.domain}"
121 component_secret = "useless-secret-on-loopback"
125 c2sRequireEncryption = true;
126 s2sRequireEncryption = true;
127 s2sSecureAuth = true;
129 domain = "tmp.${networking.domain}";
130 # Prosody's HTTP parser limit on body size
131 uploadFileSizeLimit = "10485760";
132 userQuota = 100 * 1024 * 1024;
133 uploadExpireAfter = "60 * 60 * 24 * 7";
134 httpUploadPath = "/var/lib/prosody/upload";
137 { domain = "salons.${networking.domain}";
139 restrict_room_creation = "local"
140 max_history_messages = 42
141 muc_room_locking = true
142 muc_room_lock_timeout = 600
143 muc_tombstones = true
144 muc_tombstone_expiry = 31 * 24 * 60 * 60
145 muc_room_default_public = true
146 muc_room_default_members_only = false
147 muc_room_default_moderated = true
148 muc_room_default_public_jids = false
149 muc_room_default_change_subject = true
150 muc_room_default_history_length = 42
151 muc_room_default_language = "fr"
155 ssl.key = "/var/lib/acme/${networking.domain}/key.pem";
156 ssl.cert = "/var/lib/acme/${networking.domain}/fullchain.pem";
158 "julm@${networking.domain}"
160 virtualHosts."${networking.domain}" = {
162 domain = "${networking.domain}";
163 ssl.key = "/var/lib/acme/${networking.domain}/key.pem";
164 ssl.cert = "/var/lib/acme/${networking.domain}/fullchain.pem";
166 allowRegistration = false;
167 authentication = "internal_hashed";
171 { url = "biboumi.${networking.domain}";
172 description = "Passerelle vers des serveurs IRC (Internet Relay Chat)"; }
174 package = pkgs.prosody.override {
175 withCommunityModules = [