diff --git a/tv/3modules/ejabberd/config.nix b/tv/3modules/ejabberd/config.nix deleted file mode 100644 index e989fc8bd..000000000 --- a/tv/3modules/ejabberd/config.nix +++ /dev/null @@ -1,128 +0,0 @@ -with import ; -{ config, ... }: let - - # See https://github.com/processone/ejabberd/blob/master/ejabberd.yml.example - - ciphers = concatStringsSep ":" [ - "ECDHE-ECDSA-AES256-GCM-SHA384" - "ECDHE-RSA-AES256-GCM-SHA384" - "ECDHE-ECDSA-CHACHA20-POLY1305" - "ECDHE-RSA-CHACHA20-POLY1305" - "ECDHE-ECDSA-AES128-GCM-SHA256" - "ECDHE-RSA-AES128-GCM-SHA256" - "ECDHE-ECDSA-AES256-SHA384" - "ECDHE-RSA-AES256-SHA384" - "ECDHE-ECDSA-AES128-SHA256" - "ECDHE-RSA-AES128-SHA256" - ]; - - protocol_options = [ - "no_sslv2" - "no_sslv3" - "no_tlsv1" - "no_tlsv1_10" - ]; - -in /* yaml */ '' - - access_rules: - announce: - - allow: admin - local: - - allow: local - configure: - - allow: admin - register: - - allow - s2s: - - allow - trusted_network: - - allow: loopback - - acl: - local: - user_regexp: "" - loopback: - ip: - - "127.0.0.0/8" - - "::1/128" - - "::FFFF:127.0.0.1/128" - - certfiles: ${toJSON config.credentials.certfiles} - - hosts: ${toJSON config.hosts} - - language: "en" - - listen: - - - port: 5222 - ip: "::" - module: ejabberd_c2s - shaper: c2s_shaper - ciphers: ${toJSON ciphers} - dhfile: ${config.stateDir}/dhfile - protocol_options: ${toJSON protocol_options} - starttls: true - starttls_required: true - tls: false - tls_compression: false - max_stanza_size: 65536 - - - port: 5269 - ip: "::" - module: ejabberd_s2s_in - shaper: s2s_shaper - max_stanza_size: 131072 - - loglevel: 4 - - modules: - mod_adhoc: {} - mod_admin_extra: {} - mod_announce: - access: announce - mod_caps: {} - mod_carboncopy: {} - mod_client_state: {} - mod_configure: {} - mod_disco: {} - mod_echo: {} - mod_bosh: {} - mod_last: {} - mod_offline: - access_max_user_messages: max_user_offline_messages - mod_ping: {} - mod_privacy: {} - mod_private: {} - mod_register: - access_from: deny - access: register - ip_access: trusted_network - registration_watchers: ${toJSON config.registration_watchers} - mod_roster: {} - mod_shared_roster: {} - mod_stats: {} - mod_time: {} - mod_vcard: - search: false - mod_version: {} - mod_http_api: {} - - s2s_access: s2s - s2s_ciphers: ${toJSON ciphers} - s2s_dhfile: ${config.stateDir}/dhfile - s2s_protocol_options: ${toJSON protocol_options} - s2s_tls_compression: false - s2s_use_starttls: required - - shaper_rules: - max_user_offline_messages: - - 5000: admin - - 100 - max_user_sessions: 10 - c2s_shaper: - - none: admin - - normal - s2s_shaper: fast -'' diff --git a/tv/3modules/ejabberd/default.nix b/tv/3modules/ejabberd/default.nix index d6573ad01..2966a4f60 100644 --- a/tv/3modules/ejabberd/default.nix +++ b/tv/3modules/ejabberd/default.nix @@ -12,6 +12,8 @@ fi ''; + settingsFormat = pkgs.formats.yaml {}; + in { options.tv.ejabberd = { enable = mkEnableOption "tv.ejabberd"; @@ -21,6 +23,25 @@ in { (toString + "/ejabberd.pem") ]; }; + configFile = mkOption { + type = types.either types.package types.absolute-pathname; + default = settingsFormat.generate "ejabberd.yaml" cfg.settings; + }; + ciphers = mkOption { + type = types.listOf types.str; + default = [ + "ECDHE-ECDSA-AES256-GCM-SHA384" + "ECDHE-RSA-AES256-GCM-SHA384" + "ECDHE-ECDSA-CHACHA20-POLY1305" + "ECDHE-RSA-CHACHA20-POLY1305" + "ECDHE-ECDSA-AES128-GCM-SHA256" + "ECDHE-RSA-AES128-GCM-SHA256" + "ECDHE-ECDSA-AES256-SHA384" + "ECDHE-RSA-AES256-SHA384" + "ECDHE-ECDSA-AES128-SHA256" + "ECDHE-RSA-AES128-SHA256" + ]; + }; credentials.certfiles = mkOption { internal = true; readOnly = true; @@ -39,13 +60,8 @@ in { paths = [ (pkgs.writeDashBin "ejabberdctl" '' exec ${pkgs.ejabberd}/bin/ejabberdctl \ - --config ${toFile "ejabberd.yaml" (import ./config.nix { - inherit pkgs; - config = cfg; - })} \ - --ctl-config ${toFile "ejabberdctl.cfg" /* sh */ '' - ERL_OPTIONS='-setcookie ${cfg.stateDir}/.erlang.cookie' - ''} \ + --config /etc/ejabberd/ejabberd.yaml \ + --ctl-config /etc/ejabberd/ejabberdctl.cfg \ --logs ${cfg.stateDir} \ --spool ${cfg.stateDir} \ "$@" @@ -54,12 +70,25 @@ in { ]; }; }; + protocol_options = mkOption { + type = types.listOf types.str; + default = [ + "no_sslv2" + "no_sslv3" + "no_tlsv1" + "no_tlsv1_10" + ]; + }; registration_watchers = mkOption { type = types.listOf types.str; default = [ config.krebs.users.tv.mail ]; }; + settings = mkOption { + type = settingsFormat.type; + default = {}; + }; stateDir = mkOption { type = types.absolute-pathname; default = "/var/lib/ejabberd"; @@ -67,6 +96,13 @@ in { }; }; config = lib.mkIf cfg.enable { + + environment.etc."ejabberd/ejabberd.yaml".source = cfg.configFile; + environment.etc."ejabberd/ejabberdctl.cfg".source = + builtins.toFile "ejabberdctl.cfg" /* sh */ '' + ERL_OPTIONS='-setcookie ${cfg.stateDir}/.erlang.cookie' + ''; + environment.systemPackages = [ (pkgs.symlinkJoin { name = "ejabberd-sudo-wrapper"; @@ -91,6 +127,10 @@ in { systemd.services.ejabberd = { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; + reloadTriggers = [ + config.environment.etc."ejabberd/ejabberd.yaml".source + config.environment.etc."ejabberd/ejabberdctl.cfg".source + ]; serviceConfig = { ExecStartPre = [ "${pkgs.coreutils}/bin/ln -s \${CREDENTIALS_DIRECTORY} /tmp/credentials" @@ -122,5 +162,109 @@ in { WatchdogSec = 30; }; }; + + # preset config values + tv.ejabberd.settings = { + access_rules = { + announce = mkDefault [{ allow = "admin"; }]; + local = mkDefault [{ allow = "local"; }]; + configure = mkDefault [{ allow = "admin"; }]; + register = mkDefault ["allow"]; + s2s = mkDefault ["allow"]; + trusted_network = mkDefault [{ allow = "loopback"; }]; + }; + + acl = { + local.user_regexp = mkDefault ""; + loopback.ip = mkDefault [ + "127.0.0.0/8" + "::1/128" + "::FFFF:127.0.0.1/128" + ]; + }; + + certfiles = mkDefault cfg.credentials.certfiles; + + hosts = mkDefault cfg.hosts; + + language = mkDefault "en"; + + listen = mkDefault [ + { + port = 5222; + ip = "::"; + module = "ejabberd_c2s"; + shaper = "c2s_shaper"; + ciphers = concatStringsSep ":" cfg.ciphers; + protocol_options = cfg.protocol_options; + starttls = true; + starttls_required = true; + tls = false; + tls_compression = false; + max_stanza_size = 65536; + } + { + port = 5269; + ip = "::"; + module = "ejabberd_s2s_in"; + shaper = "s2s_shaper"; + dhfile = "${cfg.stateDir}/dhfile"; + max_stanza_size = 131072; + } + ]; + + loglevel = mkDefault "4"; + + modules = { + mod_adhoc = mkDefault {}; + mod_admin_extra = mkDefault {}; + mod_announce.access = mkDefault "announce"; + mod_caps = mkDefault {}; + mod_carboncopy = mkDefault {}; + mod_client_state = mkDefault {}; + mod_configure = mkDefault {}; + mod_disco = mkDefault {}; + mod_echo = mkDefault {}; + mod_bosh = mkDefault {}; + mod_last = mkDefault {}; + mod_offline.access_max_user_messages = mkDefault "max_user_offline_messages"; + mod_ping = mkDefault {}; + mod_privacy = mkDefault {}; + mod_private = mkDefault {}; + mod_register = { + access_from = mkDefault "deny"; + access = mkDefault "register"; + ip_access = mkDefault "trusted_network"; + registration_watchers = mkDefault cfg.registration_watchers; + }; + mod_roster = mkDefault {}; + mod_shared_roster = mkDefault {}; + mod_stats = mkDefault {}; + mod_time = mkDefault {}; + mod_vcard.search = mkDefault false; + mod_version = mkDefault {}; + mod_http_api = mkDefault {}; + }; + + s2s_access = mkDefault "s2s"; + s2s_ciphers = concatStringsSep ":" cfg.ciphers; + s2s_dhfile = mkDefault "${cfg.stateDir}/dhfile"; + s2s_protocol_options = mkDefault cfg.protocol_options; + s2s_tls_compression = mkDefault false; + s2s_use_starttls = mkDefault "required"; + + shaper_rules = { + max_user_offline_messages = mkDefault [ + { "5000" = "admin"; } + 100 + ]; + max_user_sessions = mkDefault 10; + c2s_shaper = mkDefault [ + { "none" = "admin"; } + "normal" + ]; + s2s_shaper = mkDefault "fast"; + }; + }; }; }