{ pkgs, lib, config, inputs, hosts, ipv4, ... }: let inherit (config.services) prosody; inherit (hosts.mermet.config.services) coturn; domain = config.networking.domain; in { imports = [ prosody/biboumi.nix ]; networking.nftables.ruleset = '' table inet filter { chain input-net { tcp dport { xmpp-client, xmpp-server } counter accept comment "prosody: XMPP" tcp dport 5000 counter accept comment "prosody: XMPP XEP-0065 File Transfer Proxy" tcp dport {${lib.concatMapStringsSep "," toString prosody.httpsPorts}} counter accept comment "prosody: HTTPS" } chain output-net { skuid ${prosody.user} counter accept comment "prosody" } } ''; /* services.upnpc.redirections = [ { description = "XMPP"; externalPort = 5222; protocol = "TCP"; duration = 30 * 60; service.wantedBy = ["prosody.service"]; service.partOf = ["prosody.service"]; } { description = "XMPP"; externalPort = 5269; protocol = "TCP"; duration = 30 * 60; service.wantedBy = ["prosody.service"]; service.partOf = ["prosody.service"]; } { description = "XMPP-FTP"; externalPort = 5000; protocol = "TCP"; duration = 30 * 60; service.wantedBy = ["prosody.service"]; service.partOf = ["prosody.service"]; } ] ++ map (externalPort: { description = "XMPP-HTTPS"; inherit externalPort; protocol="TCP"; duration = 30 * 60; service.wantedBy = ["prosody.service"]; service.partOf = ["prosody.service"]; }) prosody.httpsPorts; */ /* services.tor.relay.hiddenServices."${domain}/xmpp".map = [ 5222 5269 5000 ] ++ prosody.httpsPorts; */ users.groups.acme.members = [ prosody.user ]; security.acme.certs."${domain}" = { postRun = "systemctl restart prosody"; }; fileSystems."/var/lib/prosody" = { device = "rpool/var/prosody"; fsType = "zfs"; }; services.sanoid.datasets = { "rpool/var/prosody" = { use_template = [ "snap" ]; daily = 7; }; }; systemd.services.prosody = { wants = [ "acme-selfsigned-${domain}.service" "acme-${domain}.service"]; after = [ "acme-selfsigned-${domain}.service" ]; }; # sudo -u prosody prosodyctl check services.prosody = { enable = true; xmppComplianceSuite = true; modules = { announce = true; blocklist = true; cloud_notify = false; # not encrypted even with OMEMO #cloud_notify_encrypted = true; groups = true; limits = false; motd = true; server_contact_info = true; watchregistrations = true; websocket = false; welcome = true; proxy65 = false; }; extraModules = [ "turn_external" #"turncredentials" #"net_multiplex" #"extdisco" ]; extraConfig = '' log = { -- debug = "*syslog"; info = "*syslog"; warn = "*syslog"; error = "*syslog"; } -- Listen only in IPv4 until hosting provider's IPv6 works well. interfaces = { "0.0.0.0" } c2s_interfaces = { "0.0.0.0" } contact_info = { --abuse = { "mailto:abuse@${domain}", "xmpp:abuse@${domain}" }; --admin = { "mailto:admin@${domain}", "xmpp:admin@${domain}" }; --feedback = { "http://${domain}/feedback.php", "mailto:feedback@${domain}", "xmpp:feedback@${domain}" }; --sales = { "xmpp:bard@${domain}" }; --security = { "xmpp:security@${domain}" }; --support = { "http://${domain}/support.php", "xmpp:support@${domain}" }; } legacy_ssl_ports = { 5222 } -- turncredentials_host = "turn.${domain}" -- turncredentials_port = 3478 -- turncredentials_secret = "${lib.removeSuffix "\n" (builtins.readFile (inputs.secrets + "/coturn/static-auth-secret"))}"; turn_external_secret = "${lib.removeSuffix "\n" (builtins.readFile (inputs.secrets + "/coturn/static-auth-secret"))}" turn_external_host = "turn.${domain}" turn_external_port = 3478 turn_external_ttl = 86400 smacks_enabled_s2s = true; smacks_s2s_resend = true; --http_files_dir = "/var/lib/prosody/files" --http_external_url = "https://tmp.${domain}:5281" --https_certificate = "/var/lib/acme/${domain}/fullchain.pem" --https_key = "/var/lib/acme/${domain}/key.pem" --certificates = "/var/lib/acme" proxy65_ports = 5000 Component "proxy65.${domain}" "proxy65" proxy65_address = "proxy65.${domain}" proxy65_acl = { "${domain}" } Component "biboumi.${domain}" component_secret = "useless-secret-on-loopback" ''; httpFileShare = { domain = "tmp.${domain}"; size_limit = 16*1024*1024; # 16 MiB daily_quota = 100*1024*1024; # 100 MiB per day per user global_quota = 1024*1024*1024; # 1 GiB total }; #ports = {80}; #ssl_ports = {443}; c2sRequireEncryption = true; s2sRequireEncryption = true; s2sSecureAuth = true; muc = [ { domain = "salons.${domain}"; extraConfig = '' restrict_room_creation = "local" max_history_messages = 42 muc_room_locking = true muc_room_lock_timeout = 600 muc_tombstones = true muc_tombstone_expiry = 31 * 24 * 60 * 60 muc_room_default_public = true muc_room_default_members_only = false muc_room_default_moderated = true muc_room_default_public_jids = false muc_room_default_change_subject = true muc_room_default_history_length = 42 muc_room_default_language = "fr" ''; } ]; ssl.key = "/var/lib/acme/${domain}/key.pem"; ssl.cert = "/var/lib/acme/${domain}/fullchain.pem"; admins = [ "julm@${domain}" ]; virtualHosts."${domain}" = { enabled = true; domain = "${domain}"; ssl.key = "/var/lib/acme/${domain}/key.pem"; ssl.cert = "/var/lib/acme/${domain}/fullchain.pem"; }; allowRegistration = false; authentication = "internal_hashed"; httpPorts = []; httpsPorts = [5281]; disco_items = [ { url = "biboumi.${domain}"; description = "Passerelle vers des serveurs IRC (Internet Relay Chat)"; } ]; package = pkgs.prosody.override { withCommunityModules = [ "turncredentials" #"extdisco" ]; }; }; }