1 { pkgs, lib, config, inputs, hosts, ipv4, ... }:
 
   3   inherit (config.services) prosody;
 
   4   inherit (hosts.mermet.config.services) coturn;
 
   5   domain = config.networking.domain;
 
  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."${domain}/xmpp".map = [ 5222 5269 5000 ] ++ prosody.httpsPorts;
 
  49 users.groups.acme.members = [ prosody.user ];
 
  50 security.acme.certs."${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-${domain}.service" "acme-${domain}.service"];
 
  65   after = [ "acme-selfsigned-${domain}.service" ];
 
  67 # sudo -u prosody prosodyctl check
 
  70   xmppComplianceSuite = true;
 
  78     server_contact_info = true;
 
  79     watchregistrations = true;
 
  96     -- Listen only in IPv4 until hosting provider's IPv6 works well.
 
  97     interfaces = { "0.0.0.0" }
 
  98     c2s_interfaces = { "0.0.0.0" }
 
 100       --abuse = { "mailto:abuse@${domain}", "xmpp:abuse@${domain}" };
 
 101       --admin = { "mailto:admin@${domain}", "xmpp:admin@${domain}" };
 
 102       --feedback = { "http://${domain}/feedback.php", "mailto:feedback@${domain}", "xmpp:feedback@${domain}" };
 
 103       --sales = { "xmpp:bard@${domain}" };
 
 104       --security = { "xmpp:security@${domain}" };
 
 105       --support = { "http://${domain}/support.php", "xmpp:support@${domain}" };
 
 107     legacy_ssl_ports = { 5222 }
 
 109     turncredentials_host = "turn.${domain}"
 
 110     turncredentials_port = 3478
 
 111     turncredentials_secret = "${lib.removeSuffix "\n" (builtins.readFile (inputs.secrets + "/coturn/static-auth-secret"))}";
 
 112     smacks_enabled_s2s = true;
 
 113     smacks_s2s_resend = true;
 
 115     --http_files_dir = "/var/lib/prosody/files"
 
 116     --http_external_url = "https://tmp.${domain}:5281"
 
 117     --https_certificate = "/var/lib/acme/${domain}/fullchain.pem"
 
 118     --https_key = "/var/lib/acme/${domain}/key.pem"
 
 119     --certificates = "/var/lib/acme"
 
 122     Component "proxy65.${domain}" "proxy65"
 
 123       proxy65_address = "proxy65.${domain}"
 
 124       proxy65_acl = { "${domain}" }
 
 126     Component "biboumi.${domain}"
 
 127       component_secret = "useless-secret-on-loopback"
 
 131   c2sRequireEncryption = true;
 
 132   s2sRequireEncryption = true;
 
 133   s2sSecureAuth = true;
 
 135     domain = "tmp.${domain}";
 
 136     # Prosody's HTTP parser limit on body size
 
 137     uploadFileSizeLimit = "10485760";
 
 138     userQuota = 100 * 1024 * 1024;
 
 139     uploadExpireAfter = "60 * 60 * 24 * 7";
 
 140     httpUploadPath = "/var/lib/prosody/upload";
 
 144       domain = "salons.${domain}";
 
 146         restrict_room_creation = "local"
 
 147         max_history_messages = 42
 
 148         muc_room_locking = true
 
 149         muc_room_lock_timeout = 600
 
 150         muc_tombstones = true
 
 151         muc_tombstone_expiry = 31 * 24 * 60 * 60
 
 152         muc_room_default_public = true
 
 153         muc_room_default_members_only = false
 
 154         muc_room_default_moderated = true
 
 155         muc_room_default_public_jids = false
 
 156         muc_room_default_change_subject = true
 
 157         muc_room_default_history_length = 42
 
 158         muc_room_default_language = "fr"
 
 162   ssl.key = "/var/lib/acme/${domain}/key.pem";
 
 163   ssl.cert = "/var/lib/acme/${domain}/fullchain.pem";
 
 167   virtualHosts."${domain}" = {
 
 169     domain = "${domain}";
 
 170     ssl.key = "/var/lib/acme/${domain}/key.pem";
 
 171     ssl.cert = "/var/lib/acme/${domain}/fullchain.pem";
 
 173   allowRegistration = false;
 
 174   authentication = "internal_hashed";
 
 178     { url = "biboumi.${domain}";
 
 179       description = "Passerelle vers des serveurs IRC (Internet Relay Chat)"; }
 
 181   package = pkgs.prosody.override {
 
 182     withCommunityModules = [