diff --git a/README.rst b/README.rst index 3b1759d..7bdeb2c 100644 --- a/README.rst +++ b/README.rst @@ -9,8 +9,8 @@ An installer which deploy a complete mail server based on Modoboa. This tool is still in beta stage, it has been tested on: - * Debian 10 and upper - * Ubuntu Bionic Beaver (18.04) and upper + * Debian 12 and upper + * Ubuntu Focal Fossa (20.04) and upper .. warning:: @@ -43,7 +43,7 @@ The following components are installed by the installer: * Nginx and uWSGI * Postfix * Dovecot -* Amavis (with SpamAssassin and ClamAV) +* Amavis (with SpamAssassin and ClamAV) or Rspamd * automx (autoconfiguration service) * OpenDKIM * Radicale (CalDAV and CardDAV server) @@ -229,6 +229,22 @@ If you want to use already generated certs, simply edit the tls_cert_file_path = *path to tls fullchain file* tls_key_file_path = *path to tls key file* +Antispam +======== + +You have 3 options regarding antispam : disabled, Amavis, Rspamd + +Amavis +------ + +Amavis + +Rspamd +------ + +Rspamd + + .. |workflow| image:: https://github.com/modoboa/modoboa-installer/workflows/Modoboa%20installer/badge.svg .. |codecov| image:: https://codecov.io/gh/modoboa/modoboa-installer/graph/badge.svg?token=Fo2o1GdHZq :target: https://codecov.io/gh/modoboa/modoboa-installer diff --git a/modoboa_installer/config_dict_template.py b/modoboa_installer/config_dict_template.py index d03dde1..4e3b918 100644 --- a/modoboa_installer/config_dict_template.py +++ b/modoboa_installer/config_dict_template.py @@ -39,7 +39,7 @@ ConfigDictTemplate = [ }, { "option": "type", - "default": "rspamd", + "default": "amavis", "customizable": True, "question": "Please select your antispam utility", "values": ["rspamd", "amavis"], diff --git a/modoboa_installer/scripts/files/rspamd/local.d/antivirus.conf.tpl b/modoboa_installer/scripts/files/rspamd/local.d/antivirus.conf.tpl index 5e50a4e..f1d98eb 100644 --- a/modoboa_installer/scripts/files/rspamd/local.d/antivirus.conf.tpl +++ b/modoboa_installer/scripts/files/rspamd/local.d/antivirus.conf.tpl @@ -7,7 +7,6 @@ clamav { symbol = "CLAM_VIRUS"; type = "clamav"; servers = "127.0.0.1:3310" - patterns { # symbol_name = "pattern"; JUST_EICAR = "Test.EICAR"; diff --git a/modoboa_installer/scripts/files/rspamd/local.d/arc.conf b/modoboa_installer/scripts/files/rspamd/local.d/arc.conf deleted file mode 100644 index 3dcf992..0000000 --- a/modoboa_installer/scripts/files/rspamd/local.d/arc.conf +++ /dev/null @@ -1,3 +0,0 @@ -try_fallback = false; -selector_map = "%selector_map_path"; -path_map = "%key_map_path"; diff --git a/modoboa_installer/scripts/files/rspamd/local.d/dmarc.conf.tpl b/modoboa_installer/scripts/files/rspamd/local.d/dmarc.conf.tpl new file mode 100644 index 0000000..bfe456a --- /dev/null +++ b/modoboa_installer/scripts/files/rspamd/local.d/dmarc.conf.tpl @@ -0,0 +1,21 @@ +reporting { + # Required attributes + enabled = true; # Enable reports in general + email = 'postmaster@%hostname'; # Source of DMARC reports + domain = '%hostname'; # Domain to serve + org_name = '%hostname'; # Organisation + # Optional parameters + #bcc_addrs = ["postmaster@example.com"]; # additional addresses to copy on reports + report_local_controller = false; # Store reports for local/controller scans (for testing only) + #helo = 'rspamd.localhost'; # Helo used in SMTP dialog + #smtp = '127.0.0.1'; # SMTP server IP + #smtp_port = 25; # SMTP server port + from_name = '%hostname DMARC REPORT'; # SMTP FROM + msgid_from = 'rspamd'; # Msgid format + #max_entries = 1k; # Maxiumum amount of entries per domain + #keys_expire = 2d; # Expire date for Redis keys + #only_domains = '/path/to/map'; # Only store reports from domains or eSLDs listed in this map + # Available from 3.3 + #exclude_domains = '/path/to/map'; # Exclude reports from domains or eSLDs listed in this map + #exclude_domains = ["example.com", "another.com"]; # Alternative, use array to exclude reports from domains or eSLDs +} diff --git a/modoboa_installer/scripts/files/rspamd/local.d/force_actions.conf.tpl b/modoboa_installer/scripts/files/rspamd/local.d/force_actions.conf.tpl new file mode 100644 index 0000000..6a1b331 --- /dev/null +++ b/modoboa_installer/scripts/files/rspamd/local.d/force_actions.conf.tpl @@ -0,0 +1,5 @@ +rules { + DMARC_POLICY_QUARANTINE { + action = "add header"; + } +} diff --git a/modoboa_installer/scripts/rspamd.py b/modoboa_installer/scripts/rspamd.py index 3890f28..dddd534 100644 --- a/modoboa_installer/scripts/rspamd.py +++ b/modoboa_installer/scripts/rspamd.py @@ -25,13 +25,19 @@ class Rspamd(base.Installer): "local.d/arc.conf", "local.d/mx_check.conf", "local.d/spf.conf", - "local.d/worker-controller.inc", "local.d/worker-normal.inc", "local.d/worker-proxy.inc", "local.d/greylist.conf", "local.d/milter_headers.conf", "local.d/metrics.conf"] + def __init__(self, *args, **kwargs): + super().__init__(self, *args, **kwargs) + self.generate_password_condition = (not self.upgrade or + utils.user_input( + "Do you want to (re)generate rspamd password ? (y/N)").lower().startswith("y") + ) + @property def config_dir(self): """Return appropriate config dir.""" @@ -83,23 +89,26 @@ class Rspamd(base.Installer): _config_files.append("local.d/rbl.conf") if self.app_config["whitelist_auth"].lower() == "true": _config_files.append("local.d/groups.conf") + if self.generate_password_condition: + _config_files.append("local.d/worker-controller.inc") return _config_files def get_template_context(self): _context = super().get_template_context() - code, controller_password = utils.exec_cmd( - r"rspamadm pw -p {}".format(self.app_config["password"])) - if code != 0: - utils.error("Error setting rspamd password. " - "Please make sure it is not 'q1' or 'q2'." - "Storing the password in plain. See" - "https://rspamd.com/doc/quickstart.html#setting-the-controller-password") - _context["controller_password"] = self.app_config["password"] - else: - controller_password = controller_password.decode().replace("\n", "") - _context["controller_password"] = controller_password _context["greylisting_disabled"] = "" if not self.app_config["greylisting"].lower() == "true" else "#" _context["whitelist_auth_enabled"] = "" if self.app_config["whitelist_auth"].lower() == "true" else "#" + if self.generate_password_condition: + code, controller_password = utils.exec_cmd( + r"rspamadm pw -p {}".format(self.app_config["password"])) + if code != 0: + utils.error("Error setting rspamd password. " + "Please make sure it is not 'q1' or 'q2'." + "Storing the password in plain. See" + "https://rspamd.com/doc/quickstart.html#setting-the-controller-password") + _context["controller_password"] = self.app_config["password"] + else: + controller_password = controller_password.decode().replace("\n", "") + _context["controller_password"] = controller_password return _context def post_run(self): diff --git a/run.py b/run.py index 4dab5a3..7bb2d70 100755 --- a/run.py +++ b/run.py @@ -85,12 +85,11 @@ def config_file_update_complete(backup_location): utils.BLUE) -def main(input_args): - """Install process.""" +def parser_setup(input_args): parser = argparse.ArgumentParser() versions = ( ["latest"] + list(compatibility_matrix.COMPATIBILITY_MATRIX.keys()) - ) + ) parser.add_argument("--debug", action="store_true", default=False, help="Enable debug output") parser.add_argument("--force", action="store_true", default=False, @@ -118,7 +117,7 @@ def main(input_args): parser.add_argument( "--backup", action="store_true", default=False, help="Backing up interactively previously installed instance" - ) + ) parser.add_argument( "--silent-backup", action="store_true", default=False, help="For script usage, do not require user interaction " @@ -131,13 +130,18 @@ def main(input_args): "--restore", type=str, metavar="path", help="Restore a previously backup up modoboa instance on a NEW machine. " "You MUST provide backup directory" - ) + ) parser.add_argument( "--skip-checks", action="store_true", default=False, help="Skip the checks the installer performs initially") parser.add_argument("domain", type=str, help="The main domain of your future mail server") - args = parser.parse_args(input_args) + return parser.parse_args(input_args) + + +def main(input_args): + """Install process.""" + args = parser_setup(input_args) if args.debug: utils.ENV["debug"] = True @@ -241,20 +245,29 @@ def main(input_args): scripts.install(appname, config, args.upgrade, args.restore) system.restart_service("cron") package.backend.restore_system() + hostname = config.get("general", "hostname") if not args.restore: utils.success( - "Congratulations! You can enjoy Modoboa at https://{} (admin:password)" - .format(config.get("general", "hostname")) + f"Congratulations! You can enjoy Modoboa at https://{hostname} " + "(admin:password)" ) if config.get("rspamd", "enabled"): + rspamd_password = config.get("rspamd", "password") utils.success( - f"You can also enjoy rspamd at https://{config.get("general", "hostname")}/rspamd ({config.get("rspamd", "password")})" + f"You can also enjoy rspamd at https://{hostname}/rspamd " + f"(password: {rspamd_password})" ) else: utils.success( - "Restore complete! You can enjoy Modoboa at https://{} (same credentials as before)" - .format(config.get("general", "hostname")) + f"Restore complete! You can enjoy Modoboa at https://{hostname} " + "(same credentials as before)" ) + if config.get("rspamd", "enabled"): + rspamd_password = config.get("rspamd", "password") + utils.success( + f"You can also enjoy rspamd at https://{hostname}/rspamd " + "(password: {rspamd_password})" + ) utils.success( "\n" "Modoboa is a free software maintained by volunteers.\n"