From 2f12fd8ae7240c91ae8337399af591d3c6055608 Mon Sep 17 00:00:00 2001 From: Colin Date: Fri, 22 Sep 2023 22:50:51 +0000 Subject: [PATCH] ejabberd: port config to structured nix attrs --- hosts/by-name/servo/services/ejabberd.nix | 529 +++++++++++----------- 1 file changed, 265 insertions(+), 264 deletions(-) diff --git a/hosts/by-name/servo/services/ejabberd.nix b/hosts/by-name/servo/services/ejabberd.nix index 4258aef9..91e59696 100644 --- a/hosts/by-name/servo/services/ejabberd.nix +++ b/hosts/by-name/servo/services/ejabberd.nix @@ -179,284 +179,285 @@ in services.ejabberd.enable = true; services.ejabberd.configFile = "/var/lib/ejabberd/ejabberd.yaml"; systemd.services.ejabberd.preStart = let - config-in = pkgs.writeTextFile { - name = "ejabberd.yaml.in"; - text = '' - hosts: - - uninsane.org + config-in = pkgs.writeText "ejabberd.yaml.in" (lib.generators.toYAML {} { + hosts = [ "uninsane.org" ]; + # none | emergency | alert | critical | error | warning | notice | info | debug + loglevel = "debug"; + acme.auto = false; + certfiles = [ "/var/lib/acme/uninsane.org/full.pem" ]; + # ca_file = "${pkgs.cacert.unbundled}/etc/ssl/certs/"; + # ca_file = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; - # none | emergency | alert | critical | error | warning | notice | info | debug - loglevel: debug - # loglevel: info - # loglevel: notice + pam_userinfotype = "jid"; + acl = { + admin.user = [ "colin@uninsane.org" ]; + local.user_regexp = ""; + loopback.ip = [ "127.0.0.0/8" "::1/128" ]; + }; - acme: - auto: false - certfiles: - - /var/lib/acme/uninsane.org/full.pem - # ca_file: ${pkgs.cacert.unbundled}/etc/ssl/certs/ - # ca_file: ${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt + access_rules = { + local.allow = "local"; + c2s_access.allow = "all"; + announce.allow = "admin"; + configure.allow = "admin"; + muc_create.allow = "local"; + pubsub_createnode_access.allow = "all"; + trusted_network.allow = "loopback"; + }; - pam_userinfotype: jid + # docs: + shaper_rules = { + # setting this to above 1 may break outgoing messages + # - maybe some servers rate limit? or just don't understand simultaneous connections? + max_s2s_connections = 1; + max_user_sessions = 10; + max_user_offline_messages = 5000; + c2s_shaper.fast = "all"; + s2s_shaper.med = "all"; + }; - acl: - admin: - user: - - "colin@uninsane.org" - local: - user_regexp: "" - loopback: - ip: - - 127.0.0.0/8 - - ::1/128 + # docs: + # this limits the bytes/sec. + # for example, burst: 3_000_000 and rate: 100_000 means: + # - each client has a BW budget that accumulates 100kB/sec and is capped at 3 MB + shaper.fast = 1000000; + shaper.med = 500000; + # shaper.fast.rate = 1000000; + # shaper.fast.burst_size = 10000000; + # shaper.med.rate = 500000; + # shaper.med.burst_size = 5000000; - access_rules: - local: - allow: local - c2s_access: - allow: all - announce: - allow: admin - configure: - allow: admin - muc_create: - allow: local - pubsub_createnode_access: - allow: all - trusted_network: - allow: loopback + # see: + # s2s_use_starttls = true; + s2s_use_starttls = "optional"; + # lessens 504: remote-server-timeout errors + # see: + negotiation_timeout = 60; - # docs: - shaper_rules: - # setting this to above 1 may break outgoing messages - # - maybe some servers rate limit? or just don't understand simultaneous connections? - max_s2s_connections: 1 - max_user_sessions: 10 - max_user_offline_messages: 5000 - c2s_shaper: - fast: all - s2s_shaper: - med: all + listen = [ + { + port = 5222; + module = "ejabberd_c2s"; + shaper = "c2s_shaper"; + starttls = true; + access = "c2s_access"; + } + { + port = 5223; + module = "ejabberd_c2s"; + shaper = "c2s_shaper"; + tls = true; + access = "c2s_access"; + } + { + port = 5269; + module = "ejabberd_s2s_in"; + shaper = "s2s_shaper"; + } + { + port = 5270; + module = "ejabberd_s2s_in"; + shaper = "s2s_shaper"; + tls = true; + } + { + port = 5443; + module = "ejabberd_http"; + tls = true; + request_handlers = { + "/admin" = "ejabberd_web_admin"; # TODO: ensure this actually works + "/api" = "mod_http_api"; # ejabberd API endpoint (to control server) + "/bosh" = "mod_bosh"; + "/upload" = "mod_http_upload"; + "/ws" = "ejabberd_http_ws"; + # "/.well-known/host-meta" = "mod_host_meta"; + # "/.well-known/host-meta.json" = "mod_host_meta"; + }; + } + { + # STUN+TURN TCP + # note that the full port range should be forwarded ("not NAT'd") + # `use_turn=true` enables both TURN *and* STUN + port = 3478; + module = "ejabberd_stun"; + transport = "tcp"; + use_turn = true; + turn_min_port = turnPortLow; + turn_max_port = turnPortHigh; + turn_ipv4_address = "%ANATIVE%"; + } + { + # STUN+TURN UDP + port = 3478; + module = "ejabberd_stun"; + transport = "udp"; + use_turn = true; + turn_min_port = turnPortLow; + turn_max_port = turnPortHigh; + turn_ipv4_address = "%ANATIVE%"; + } + { + # STUN+TURN TLS over TCP + port = 5349; + module = "ejabberd_stun"; + transport = "tcp"; + tls = true; + certfile = "/var/lib/acme/uninsane.org/full.pem"; + use_turn = true; + turn_min_port = turnPortLow; + turn_max_port = turnPortHigh; + turn_ipv4_address = "%ANATIVE%"; + } + ]; - # docs: - # this limits the bytes/sec. - # for example, burst: 3_000_000 and rate: 100_000 means: - # - each client has a BW budget that accumulates 100kB/sec and is capped at 3 MB - shaper: - fast: 1000000 - med: 500000 - # fast: - # - rate: 1000000 - # - burst_size: 10000000 - # med: - # - rate: 500000 - # - burst_size: 5000000 + # TODO: enable mod_fail2ban + # TODO(low): look into mod_http_fileserver for serving macros? + modules = { + # mod_adhoc = {}; + # mod_announce = { + # access = "admin"; + # }; + # allows users to set avatars in vCard + # - + mod_avatar = {}; + mod_caps = {}; # for mod_pubsub + mod_carboncopy = {}; # allows multiple clients to receive a user's message + # queues messages when recipient is offline, including PEP and presence messages. + # compliance test suggests this be enabled + mod_client_state = {}; - # see: - # s2s_use_starttls: true - s2s_use_starttls: optional - # lessens 504: remote-server-timeout errors - # see: - negotiation_timeout: 60 - - listen: - - - port: 5222 - module: ejabberd_c2s - shaper: c2s_shaper - starttls: true - access: c2s_access - - - port: 5223 - module: ejabberd_c2s - shaper: c2s_shaper - tls: true - access: c2s_access - - - port: 5269 - module: ejabberd_s2s_in - shaper: s2s_shaper - - - port: 5270 - module: ejabberd_s2s_in - shaper: s2s_shaper - tls: true - - - port: 5443 - module: ejabberd_http - tls: true - request_handlers: - /admin: ejabberd_web_admin # TODO: ensure this actually works - /api: mod_http_api # ejabberd API endpoint (to control server) - /bosh: mod_bosh - /upload: mod_http_upload - /ws: ejabberd_http_ws - # /.well-known/host-meta: mod_host_meta - # /.well-known/host-meta.json: mod_host_meta - - - # STUN+TURN TCP - # note that the full port range should be forwarded ("not NAT'd") - # `use_turn=true` enables both TURN *and* STUN - port: 3478 - module: ejabberd_stun - transport: tcp - use_turn: true - turn_min_port: ${builtins.toString turnPortLow} - turn_max_port: ${builtins.toString turnPortHigh} - turn_ipv4_address: %ANATIVE% - - - # STUN+TURN UDP - port: 3478 - module: ejabberd_stun - transport: udp - use_turn: true - turn_min_port: ${builtins.toString turnPortLow} - turn_max_port: ${builtins.toString turnPortHigh} - turn_ipv4_address: %ANATIVE% - - - # STUN+TURN TLS over TCP - port: 5349 - module: ejabberd_stun - transport: tcp - tls: true - certfile: /var/lib/acme/uninsane.org/full.pem - use_turn: true - turn_min_port: ${builtins.toString turnPortLow} - turn_max_port: ${builtins.toString turnPortHigh} - turn_ipv4_address: %ANATIVE% - - # TODO: enable mod_fail2ban - # TODO(low): look into mod_http_fileserver for serving macros? - modules: - # mod_adhoc: {} - # mod_announce: - # access: admin - # allows users to set avatars in vCard - # - - mod_avatar: {} - mod_caps: {} # for mod_pubsub - mod_carboncopy: {} # allows multiple clients to receive a user's message - # queues messages when recipient is offline, including PEP and presence messages. - # compliance test suggests this be enabled - mod_client_state: {} - # mod_conversejs: TODO: enable once on 21.12 - # allows clients like Dino to discover where to upload files - mod_disco: - server_info: - - - modules: all - name: abuse-addresses - urls: - - "mailto:admin.xmpp@uninsane.org" - - "xmpp:colin@uninsane.org" - - - modules: all - name: admin-addresses - urls: - - "mailto:admin.xmpp@uninsane.org" - - "xmpp:colin@uninsane.org" - mod_http_upload: - host: upload.xmpp.uninsane.org - hosts: - - upload.xmpp.uninsane.org - put_url: "https://@HOST@:5443/upload" - dir_mode: "0750" - file_mode: "0750" - rm_on_unregister: false - # allow discoverability of BOSH and websocket endpoints - # TODO: enable once on ejabberd 22.05 (presently 21.04) - # mod_host_meta: {} - mod_jidprep: {} # probably not needed: lets clients normalize jids - mod_last: {} # allow other users to know when i was last online - mod_mam: - # Mnesia is limited to 2GB, better to use an SQL backend - # For small servers SQLite is a good fit and is very easy - # to configure. Uncomment this when you have SQL configured: - # db_type: sql - assume_mam_usage: true - default: always - mod_muc: - access: - - allow - access_admin: - - allow: admin - access_create: muc_create - access_persistent: muc_create - access_mam: - - allow - history_size: 100 # messages to show new participants - host: muc.xmpp.uninsane.org - hosts: - - muc.xmpp.uninsane.org - default_room_options: - anonymous: false - lang: en - persistent: true - mam: true - mod_muc_admin: {} - mod_offline: # store messages for a user when they're offline (TODO: understand multi-client workflow?) - access_max_user_messages: max_user_offline_messages - store_groupchat: true - mod_ping: {} - mod_privacy: {} # deprecated, but required for `ejabberctl export_piefxis` - mod_private: {} # allow local clients to persist arbitrary data on my server - # push notifications to services integrated with e.g. Apple/Android. - # default is for a maximum amount of PII to be withheld, since these push notifs - # generally traverse 3rd party services. can opt to include message body, etc, though. - mod_push: {} - # i don't fully understand what this does, but it seems aimed at making push notifs more reliable. - mod_push_keepalive: {} - mod_roster: - versioning: true - # docs: - # s2s dialback to verify inbound messages - # unclear to what degree the XMPP network requires this - mod_s2s_dialback: {} - mod_shared_roster: {} # creates groups for @all, @online, and anything manually administered? - mod_stream_mgmt: - resend_on_timeout: if_offline # resend undelivered messages if the origin client is offline - # fallback for when DNS-based STUN discovery is unsupported. - # - see: - # docs: - # people say to just keep this defaulted (i guess ejabberd knows to return its `host` option of uninsane.org?) - mod_stun_disco: {} - # docs: - mod_vcard: - allow_return_all: true # all users are discoverable (?) - host: vjid.xmpp.uninsane.org - hosts: - - vjid.xmpp.uninsane.org - search: true - mod_vcard_xupdate: {} # needed for avatars - # docs: - mod_pubsub: # needed for avatars - access_createnode: pubsub_createnode_access - host: pubsub.xmpp.uninsane.org - hosts: - - pubsub.xmpp.uninsane.org - ignore_pep_from_offline: false - last_item_cache: true - plugins: - - pep - - flat - force_node_config: - # ensure client bookmarks are private - storage:bookmarks: - access_model: whitelist - urn:xmpp:avatar:data: - access_model: open - urn:xmpp:avatar:metadata: - access_model: open - mod_version: {} - ''; - }; + # mod_conversejs: TODO: enable once on 21.12 + # allows clients like Dino to discover where to upload files + mod_disco.server_info = [ + { + modules = "all"; + name = "abuse-addresses"; + urls = [ + "mailto:admin.xmpp@uninsane.org" + "xmpp:colin@uninsane.org" + ]; + } + { + modules = "all"; + name = "admin-addresses"; + urls = [ + "mailto:admin.xmpp@uninsane.org" + "xmpp:colin@uninsane.org" + ]; + } + ]; + mod_http_upload = { + host = "upload.xmpp.uninsane.org"; + hosts = [ "upload.xmpp.uninsane.org" ]; + put_url = "https://@HOST@:5443/upload"; + dir_mode = "0750"; + file_mode = "0750"; + rm_on_unregister = false; + }; + # allow discoverability of BOSH and websocket endpoints + # TODO: enable once on ejabberd 22.05 (presently 21.04) + # mod_host_meta = {}; + mod_jidprep = {}; # probably not needed: lets clients normalize jids + mod_last = {}; # allow other users to know when i was last online + mod_mam = { + # Mnesia is limited to 2GB, better to use an SQL backend + # For small servers SQLite is a good fit and is very easy + # to configure. Uncomment this when you have SQL configured: + # db_type: sql + assume_mam_usage = true; + default = "always"; + }; + mod_muc = { + access = [ "allow" ]; + access_admin = { allow = "admin"; }; + access_create = "muc_create"; + access_persistent = "muc_create"; + access_mam = [ "allow" ]; + history_size = 100; # messages to show new participants + host = "muc.xmpp.uninsane.org"; + hosts = [ "muc.xmpp.uninsane.org" ]; + default_room_options = { + anonymous = false; + lang = "en"; + persistent = true; + mam = true; + }; + }; + mod_muc_admin = {}; + mod_offline = { + # store messages for a user when they're offline (TODO: understand multi-client workflow?) + access_max_user_messages = "max_user_offline_messages"; + store_groupchat = true; + }; + mod_ping = {}; + mod_privacy = {}; # deprecated, but required for `ejabberctl export_piefxis` + mod_private = {}; # allow local clients to persist arbitrary data on my server + # push notifications to services integrated with e.g. Apple/Android. + # default is for a maximum amount of PII to be withheld, since these push notifs + # generally traverse 3rd party services. can opt to include message body, etc, though. + mod_push = {}; + # i don't fully understand what this does, but it seems aimed at making push notifs more reliable. + mod_push_keepalive = {}; + mod_roster = { + versioning = true; + }; + # docs: + # s2s dialback to verify inbound messages + # unclear to what degree the XMPP network requires this + mod_s2s_dialback = {}; + mod_shared_roster = {}; # creates groups for @all, @online, and anything manually administered? + mod_stream_mgmt = { + # resend undelivered messages if the origin client is offline + resend_on_timeout = "if_offline"; + }; + # fallback for when DNS-based STUN discovery is unsupported. + # - see: + # docs: + # people say to just keep this defaulted (i guess ejabberd knows to return its `host` option of uninsane.org?) + mod_stun_disco = {}; + # docs: + mod_vcard = { + allow_return_all = true; # all users are discoverable (?) + host = "vjid.xmpp.uninsane.org"; + hosts = [ "vjid.xmpp.uninsane.org" ]; + search = true; + }; + mod_vcard_xupdate = {}; # needed for avatars + # docs: + mod_pubsub = { + #^ needed for avatars + access_createnode = "pubsub_createnode_access"; + host = "pubsub.xmpp.uninsane.org"; + hosts = [ "pubsub.xmpp.uninsane.org" ]; + ignore_pep_from_offline = false; + last_item_cache = true; + plugins = [ + "pep" + "flat" + ]; + force_node_config = { + # ensure client bookmarks are private + "storage:bookmarks:" = { + "access_model" = "whitelist"; + }; + "urn:xmpp:avatar:data" = { + "access_model" = "open"; + }; + "urn:xmpp:avatar:metadata" = { + "access_model" = "open"; + }; + }; + }; + mod_version = {}; + }; + }); sed = "${pkgs.gnused}/bin/sed"; in '' ip=$(cat '${config.sane.services.dyn-dns.ipPath}') # config is 444 (not 644), so we want to write out-of-place and then atomically move # TODO: factor this out into `sane-woop` helper? rm -f /var/lib/ejabberd/ejabberd.yaml.new - ${sed} "s/%ANATIVE%/$ip/" ${config-in} > /var/lib/ejabberd/ejabberd.yaml.new + ${sed} "s/%ANATIVE%/$ip/g" ${config-in} > /var/lib/ejabberd/ejabberd.yaml.new mv /var/lib/ejabberd/ejabberd.yaml{.new,} '';