From 71fdea75be3e3d7f52392045b51d5beed76f7862 Mon Sep 17 00:00:00 2001 From: Rouven Seifert Date: Tue, 12 Mar 2024 11:34:16 +0100 Subject: [PATCH 1/7] refactor: split mail into modules --- flake.nix | 3 +- modules/mail/default.nix | 427 +-------------------------------- modules/mail/dovecot2.nix | 175 ++++++++++++++ modules/{ => mail}/mailman.nix | 0 modules/mail/postfix.nix | 106 ++++++++ modules/mail/rspamd.nix | 143 +++++++++++ modules/{ => mail}/sogo.nix | 0 7 files changed, 438 insertions(+), 416 deletions(-) create mode 100644 modules/mail/dovecot2.nix rename modules/{ => mail}/mailman.nix (100%) create mode 100644 modules/mail/postfix.nix create mode 100644 modules/mail/rspamd.nix rename modules/{ => mail}/sogo.nix (100%) diff --git a/flake.nix b/flake.nix index f84b6c8..55c7942 100755 --- a/flake.nix +++ b/flake.nix @@ -44,7 +44,7 @@ quitte = self.nixosConfigurations.quitte.config.system.build.toplevel; tomate = self.nixosConfigurations.tomate.config.system.build.toplevel; }); - formatters = forAllSystems (system: rec { + formatters = forAllSystems (system: { default = pkgs.${system}.nixpkgs-fmt; }); hydraJobs = forAllSystems (system: { @@ -96,7 +96,6 @@ ./modules/nextcloud.nix ./modules/matrix.nix ./modules/mautrix-telegram.nix - ./modules/sogo.nix ./modules/vaultwarden.nix ./modules/website.nix ./modules/zsh.nix diff --git a/modules/mail/default.nix b/modules/mail/default.nix index 02413c9..bc80e1d 100644 --- a/modules/mail/default.nix +++ b/modules/mail/default.nix @@ -1,426 +1,25 @@ -{ config, pkgs, ... }: +{ config, ... }: let hostname = "mail.${config.networking.domain}"; - domain = config.networking.domain; - rspamd-domain = "rspamd.${config.networking.domain}"; - dovecot-ldap-args = pkgs.writeText "ldap-args" '' - uris = ldap://localhost - dn = uid=search, ou=users, dc=ifsr, dc=de - auth_bind = yes - !include ${config.sops.secrets."dovecot_ldap_search".path} - - ldap_version = 3 - scope = subtree - base = dc=ifsr, dc=de - user_filter = (&(objectClass=posixAccount)(uid=%n)) - pass_filter = (&(objectClass=posixAccount)(uid=%n)) - ''; - # see https://www.kuketz-blog.de/e-mail-anbieter-ip-stripping-aus-datenschutzgruenden/ - header_cleanup = pkgs.writeText "header_cleanup_outgoing" '' - /^\s*(Received: from)[^\n]*(.*)/ REPLACE $1 127.0.0.1 (localhost [127.0.0.1])$2 - /^\s*User-Agent/ IGNORE - /^\s*X-Enigmail/ IGNORE - /^\s*X-Mailer/ IGNORE - /^\s*X-Originating-IP/ IGNORE - /^\s*Mime-Version/ IGNORE - ''; - # https://unix.stackexchange.com/questions/294300/postfix-prevent-users-from-changing-the-real-e-mail-address - login_maps = pkgs.writeText "login_maps.pcre" '' - # basic username => username@ifsr.de - /^([^@+]*)(\+[^@]*)?@ifsr\.de$/ ''${1} - ''; in { - sops.secrets."rspamd-password".owner = config.users.users.rspamd.name; - sops.secrets."dovecot_ldap_search".owner = config.services.dovecot2.user; - sops.secrets."postfix_ldap_aliases".owner = config.services.postfix.user; - - networking.firewall.allowedTCPPorts = [ - 25 # insecure SMTP - 143 - 465 - 587 # SMTP - 993 # IMAP - 4190 # sieve + imports = [ + ./postfix.nix + ./dovecot2.nix + ./rspamd.nix + ./sogo.nix + ./mailman.nix ]; - users.users.rspamd.extraGroups = [ "redis-rspamd" ]; - environment.etc = { - "dovecot/sieve-pipe/sa-learn-spam.sh" = { - text = '' - #!/bin/sh - ${pkgs.rspamd}/bin/rspamc learn_spam - ''; - mode = "0555"; - }; - "dovecot/sieve-pipe/sa-learn-ham.sh" = { - text = '' - #!/bin/sh - ${pkgs.rspamd}/bin/rspamc learn_ham - ''; - mode = "0555"; - }; - "dovecot/sieve/report-spam.sieve" = { - source = ./report-spam.sieve; - user = "dovecot2"; - group = "dovecot2"; - mode = "0544"; - }; - "dovecot/sieve/report-ham.sieve" = { - source = ./report-ham.sieve; - user = "dovecot2"; - group = "dovecot2"; - mode = "0544"; - }; + + # Get SSL certs for dovecot and postfix via ngnix + services.nginx.virtualHosts."${hostname}" = { + forceSSL = true; + enableACME = true; }; - - services = { - postfix = { - enable = true; - enableSubmission = true; - enableSubmissions = true; - hostname = "${hostname}"; - domain = "${domain}"; - origin = "${domain}"; - destination = [ "${hostname}" "${domain}" "localhost" ]; - networksStyle = "host"; # localhost and own public IP - sslCert = "/var/lib/acme/${hostname}/fullchain.pem"; - sslKey = "/var/lib/acme/${hostname}/key.pem"; - relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ]; - config = { - home_mailbox = "Maildir/"; - # 25 MiB - message_size_limit = "26214400"; - # hostname used in helo command. It is recommended to have this match the reverse dns entry - smtp_helo_name = config.networking.rDNS; - smtpd_banner = "${config.networking.rDNS} ESMTP $mail_name"; - smtp_use_tls = true; - # smtp_tls_security_level = "encrypt"; - smtpd_use_tls = true; - # smtpd_tls_security_level = lib.mkForce "encrypt"; - # smtpd_tls_auth_only = true; - smtpd_tls_protocols = [ - "!SSLv2" - "!SSLv3" - "!TLSv1" - "!TLSv1.1" - ]; - # "reject_non_fqdn_hostname" - smtpd_recipient_restrictions = [ - "permit_sasl_authenticated" - "permit_mynetworks" - "reject_unauth_destination" - "reject_non_fqdn_sender" - "reject_non_fqdn_recipient" - "reject_unknown_sender_domain" - "reject_unknown_recipient_domain" - "reject_unauth_destination" - "reject_unauth_pipelining" - "reject_invalid_hostname" - "check_policy_service inet:localhost:12340" - ]; - smtpd_relay_restrictions = [ - "permit_sasl_authenticated" - "permit_mynetworks" - "reject_unauth_destination" - ]; - # https://www.postfix.org/smtp-smuggling.html - smtpd_data_restrictions = [ - "reject_unauth_pipelining" - ]; - smtpd_sender_restrictions = [ - "reject_authenticated_sender_login_mismatch" - ]; - smtpd_sender_login_maps = [ - "pcre:/etc/special-aliases.pcre" - "pcre:${login_maps}" - ]; - smtp_header_checks = "pcre:${header_cleanup}"; - # smtpd_sender_login_maps = [ "ldap:${ldap-senders}" ]; - alias_maps = [ "hash:/etc/aliases" ]; - alias_database = [ "hash:/etc/aliases" ]; - # alias_maps = [ "hash:/etc/aliases" "ldap:${ldap-aliases}" ]; - smtpd_sasl_auth_enable = true; - smtpd_sasl_path = "/var/lib/postfix/auth"; - smtpd_sasl_type = "dovecot"; - #mailman stuff - mailbox_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp"; - - transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ]; - virtual_alias_maps = [ "hash:/var/lib/mailman/data/postfix_vmap" ]; - local_recipient_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" "ldap:${config.sops.secrets."postfix_ldap_aliases".path}" "$alias_maps" ]; - }; - }; - dovecot2 = { - enable = true; - enableImap = true; - enableQuota = true; - quotaGlobalPerUser = "10G"; - enableLmtp = true; - enablePAM = false; - mailLocation = "maildir:~/Maildir"; - sslServerCert = "/var/lib/acme/${hostname}/fullchain.pem"; - sslServerKey = "/var/lib/acme/${hostname}/key.pem"; - protocols = [ "imap" "sieve" ]; - mailPlugins = { - globally.enable = [ "listescape" ]; - perProtocol = { - imap = { - enable = [ "imap_sieve" "imap_filter_sieve" ]; - }; - lmtp = { - enable = [ "sieve" ]; - }; - }; - }; - mailboxes = { - Spam = { - auto = "subscribe"; - specialUse = "Junk"; - autoexpunge = "60d"; - }; - Sent = { - auto = "subscribe"; - specialUse = "Sent"; - }; - Drafts = { - auto = "subscribe"; - specialUse = "Drafts"; - }; - Trash = { - auto = "subscribe"; - specialUse = "Trash"; - }; - Archive = { - auto = "no"; - specialUse = "Archive"; - }; - }; - modules = [ - pkgs.dovecot_pigeonhole - ]; - # set to satisfy the sieveScripts check, will be overridden by userdb lookups anyways - mailUser = "vmail"; - mailGroup = "vmail"; - sieveScripts = { - before = pkgs.writeText "spam.sieve" '' - require "fileinto"; - - if anyof( - header :contains "x-spam-flag" "yes", - header :contains "X-Spam-Status" "Yes"){ - fileinto "Spam"; - } - ''; - }; - extraConfig = '' - auth_username_format = %Ln - passdb { - driver = ldap - args = ${dovecot-ldap-args} - } - userdb { - driver = ldap - args = ${dovecot-ldap-args} - } - service auth { - unix_listener /var/lib/postfix/auth { - group = postfix - mode = 0660 - user = postfix - } - } - service managesieve-login { - inet_listener sieve { - port = 4190 - } - service_count = 1 - } - - namespace inbox { - separator = / - inbox = yes - } - - service lmtp { - unix_listener dovecot-lmtp { - group = postfix - mode = 0600 - user = postfix - } - client_limit = 1 - } - - - plugin { - sieve_plugins = sieve_imapsieve sieve_extprograms - sieve_global_extensions = +vnd.dovecot.pipe - sieve_pipe_bin_dir = /etc/dovecot/sieve-pipe - - # Spam: From elsewhere to Spam folder or flag changed in Spam folder - imapsieve_mailbox1_name = Spam - imapsieve_mailbox1_causes = COPY APPEND FLAG - imapsieve_mailbox1_before = file:/etc/dovecot/sieve/report-spam.sieve - - # Ham: From Spam folder to elsewhere - imapsieve_mailbox2_name = * - imapsieve_mailbox2_from = Spam - imapsieve_mailbox2_causes = COPY - imapsieve_mailbox2_before = file:/etc/dovecot/sieve/report-ham.sieve - - # https://doc.dovecot.org/configuration_manual/plugins/listescape_plugin/ - listescape_char = "\\" - } - ''; - }; - rspamd = { - enable = true; - postfix.enable = true; - locals = { - "worker-controller.inc".source = config.sops.secrets."rspamd-password".path; - "redis.conf".text = '' - read_servers = "/run/redis-rspamd/redis.sock"; - write_servers = "/run/redis-rspamd/redis.sock"; - ''; - # headers in spamassasin style to not break old sieve scripts - "worker-proxy.inc".text = '' - spam_header = "X-Spam-Flag"; - ''; - "milter_headers.conf".text = '' - use = ["x-spam-level", "x-spam-status", "x-spamd-result", "authentication-results" ]; - ''; - "neural.conf".text = '' - servers = "/run/redis-rspamd/redis.sock"; - enabled = true; - ''; - "neural_group.conf".text = '' - symbols = { - "NEURAL_SPAM" { - weight = 0.5; # fairly low weight since we don't know how this will behave - description = "Neural network spam"; - } - "NEURAL_HAM" { - weight = -0.5; - description = "Neural network ham"; - } - } - ''; - "dmarc.conf".text = '' - reporting { - enabled = true; - email = 'reports@${config.networking.domain}'; - domain = '${config.networking.domain}'; - org_name = '${config.networking.domain}'; - from_name = 'DMARC Aggregate Report'; - } - ''; - "dkim_signing.conf".text = '' - selector = "quitte2024"; - allow_username_mismatch = true; - allow_hdrfrom_mismatch = true; - use_domain_sign_local = "ifsr.de"; - path = /var/lib/rspamd/dkim/$domain.$selector.key; - - ''; - - "multimap.conf".text = - let - local_ips = pkgs.writeText "localhost.map" '' - ::1 - 127.0.0.1 - ''; - tud_ips = pkgs.writeText "tud.map" '' - 141.30.0.0/16 - 141.76.0.0/16 - ''; - in - '' - WHITELIST_SENDER_DOMAIN { - type = "from"; - filter = "email:domain"; - map = "/var/lib/rspamd/whitelist.sender.domain.map"; - action = "accept"; - } - WHITELIST_SENDER_EMAIL { - type = "from"; - map = "/var/lib/rspamd/whitelist.sender.email.map"; - action = "accept"; - } - BLACKLIST_SENDER_DOMAIN { - type = "from"; - filter = "email:domain"; - map = "/var/lib/rspamd/blacklist.sender.domain.map"; - action = "reject"; - } - BLACKLIST_SENDER_EMAIL { - type = "from"; - map = "/var/lib/rspamd/blacklist.sender.email.map"; - action = "reject"; - } - BLACKLIST_SUBJECT_KEYWORDS { - type = "header"; - header = "Subject" - map = "/var/lib/rspamd/blacklist.keyword.subject.map"; - action = "reject"; - regexp = true; - } - RECEIVED_LOCALHOST { - type = "ip"; - action = "accept"; - map = ${local_ips}; - } - RECEIVED_TU_NETWORKS { - type = "ip"; - map = ${tud_ips}; - } - - ''; - }; - }; - redis = { - vmOverCommit = true; - servers.rspamd = { - enable = true; - }; - }; - nginx = { - enable = true; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - - virtualHosts."${hostname}" = { - forceSSL = true; - enableACME = true; - }; - virtualHosts."${rspamd-domain}" = { - forceSSL = true; - enableACME = true; - locations = { - "/" = { - proxyPass = "http://127.0.0.1:11334"; - proxyWebsockets = true; - }; - }; - }; - }; - }; - security.acme.certs."${domain}" = { + security.acme.certs."${hostname}" = { reloadServices = [ "postfix.service" "dovecot2.service" ]; }; - systemd = { - services.rspamd-dmarc-report = { - description = "rspamd dmarc reporter"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.rspamd}/bin/rspamadm dmarc_report -v"; - User = "rspamd"; - Group = "rspamd"; - }; - startAt = "daily"; - }; - }; } diff --git a/modules/mail/dovecot2.nix b/modules/mail/dovecot2.nix new file mode 100644 index 0000000..ffc6614 --- /dev/null +++ b/modules/mail/dovecot2.nix @@ -0,0 +1,175 @@ +{ config, pkgs, ... }: +let + hostname = "mail.${config.networking.domain}"; + dovecot-ldap-args = pkgs.writeText "ldap-args" '' + uris = ldap://localhost + dn = uid=search, ou=users, dc=ifsr, dc=de + auth_bind = yes + !include ${config.sops.secrets."dovecot_ldap_search".path} + + ldap_version = 3 + scope = subtree + base = dc=ifsr, dc=de + user_filter = (&(objectClass=posixAccount)(uid=%n)) + pass_filter = (&(objectClass=posixAccount)(uid=%n)) + ''; +in +{ + networking.firewall.allowedTCPPorts = [ + 143 # IMAP + 993 # IMAPS + 4190 # Managesieve + ]; + sops.secrets."dovecot_ldap_search".owner = config.services.dovecot2.user; + environment.etc = { + "dovecot/sieve-pipe/sa-learn-spam.sh" = { + text = '' + #!/bin/sh + ${pkgs.rspamd}/bin/rspamc learn_spam + ''; + mode = "0555"; + }; + "dovecot/sieve-pipe/sa-learn-ham.sh" = { + text = '' + #!/bin/sh + ${pkgs.rspamd}/bin/rspamc learn_ham + ''; + mode = "0555"; + }; + "dovecot/sieve/report-spam.sieve" = { + source = ./report-spam.sieve; + user = "dovecot2"; + group = "dovecot2"; + mode = "0544"; + }; + "dovecot/sieve/report-ham.sieve" = { + source = ./report-ham.sieve; + user = "dovecot2"; + group = "dovecot2"; + mode = "0544"; + }; + }; + + services.dovecot2 = { + enable = true; + enableImap = true; + enableQuota = true; + quotaGlobalPerUser = "10G"; + enableLmtp = true; + enablePAM = false; + mailLocation = "maildir:~/Maildir"; + sslServerCert = "/var/lib/acme/${hostname}/fullchain.pem"; + sslServerKey = "/var/lib/acme/${hostname}/key.pem"; + protocols = [ "imap" "sieve" ]; + mailPlugins = { + globally.enable = [ "listescape" ]; + perProtocol = { + imap = { + enable = [ "imap_sieve" "imap_filter_sieve" ]; + }; + lmtp = { + enable = [ "sieve" ]; + }; + }; + }; + mailboxes = { + Spam = { + auto = "subscribe"; + specialUse = "Junk"; + autoexpunge = "60d"; + }; + Sent = { + auto = "subscribe"; + specialUse = "Sent"; + }; + Drafts = { + auto = "subscribe"; + specialUse = "Drafts"; + }; + Trash = { + auto = "subscribe"; + specialUse = "Trash"; + }; + Archive = { + auto = "no"; + specialUse = "Archive"; + }; + }; + modules = [ + pkgs.dovecot_pigeonhole + ]; + # set to satisfy the sieveScripts check, will be overridden by userdb lookups anyways + mailUser = "vmail"; + mailGroup = "vmail"; + sieveScripts = { + before = pkgs.writeText "spam.sieve" '' + require "fileinto"; + + if anyof( + header :contains "x-spam-flag" "yes", + header :contains "X-Spam-Status" "Yes"){ + fileinto "Spam"; + } + ''; + }; + extraConfig = '' + auth_username_format = %Ln + passdb { + driver = ldap + args = ${dovecot-ldap-args} + } + userdb { + driver = ldap + args = ${dovecot-ldap-args} + } + service auth { + unix_listener /var/lib/postfix/auth { + group = postfix + mode = 0660 + user = postfix + } + } + service managesieve-login { + inet_listener sieve { + port = 4190 + } + service_count = 1 + } + + namespace inbox { + separator = / + inbox = yes + } + + service lmtp { + unix_listener dovecot-lmtp { + group = postfix + mode = 0600 + user = postfix + } + client_limit = 1 + } + + + plugin { + sieve_plugins = sieve_imapsieve sieve_extprograms + sieve_global_extensions = +vnd.dovecot.pipe + sieve_pipe_bin_dir = /etc/dovecot/sieve-pipe + + # Spam: From elsewhere to Spam folder or flag changed in Spam folder + imapsieve_mailbox1_name = Spam + imapsieve_mailbox1_causes = COPY APPEND FLAG + imapsieve_mailbox1_before = file:/etc/dovecot/sieve/report-spam.sieve + + # Ham: From Spam folder to elsewhere + imapsieve_mailbox2_name = * + imapsieve_mailbox2_from = Spam + imapsieve_mailbox2_causes = COPY + imapsieve_mailbox2_before = file:/etc/dovecot/sieve/report-ham.sieve + + # https://doc.dovecot.org/configuration_manual/plugins/listescape_plugin/ + listescape_char = "\\" + } + ''; + }; +} diff --git a/modules/mailman.nix b/modules/mail/mailman.nix similarity index 100% rename from modules/mailman.nix rename to modules/mail/mailman.nix diff --git a/modules/mail/postfix.nix b/modules/mail/postfix.nix new file mode 100644 index 0000000..4a79e04 --- /dev/null +++ b/modules/mail/postfix.nix @@ -0,0 +1,106 @@ +{ config, pkgs, ... }: +let + domain = config.networking.domain; + hostname = "mail.${config.networking.domain}"; + # see https://www.kuketz-blog.de/e-mail-anbieter-ip-stripping-aus-datenschutzgruenden/ + header_cleanup = pkgs.writeText "header_cleanup_outgoing" '' + /^\s*(Received: from)[^\n]*(.*)/ REPLACE $1 127.0.0.1 (localhost [127.0.0.1])$2 + /^\s*User-Agent/ IGNORE + /^\s*X-Enigmail/ IGNORE + /^\s*X-Mailer/ IGNORE + /^\s*X-Originating-IP/ IGNORE + /^\s*Mime-Version/ IGNORE + ''; + # https://unix.stackexchange.com/questions/294300/postfix-prevent-users-from-changing-the-real-e-mail-address + login_maps = pkgs.writeText "login_maps.pcre" '' + # basic username => username@ifsr.de + /^([^@+]*)(\+[^@]*)?@ifsr\.de$/ ''${1} + ''; +in +{ + sops.secrets."postfix_ldap_aliases".owner = config.services.postfix.user; + + networking.firewall.allowedTCPPorts = [ + 25 # SMTP + 465 # Submissions + 587 # Submission + ]; + services = { + postfix = { + enable = true; + enableSubmission = true; + enableSubmissions = true; + hostname = "${hostname}"; + domain = "${domain}"; + origin = "${domain}"; + destination = [ "${hostname}" "${domain}" "localhost" ]; + networksStyle = "host"; # localhost and own public IP + sslCert = "/var/lib/acme/${hostname}/fullchain.pem"; + sslKey = "/var/lib/acme/${hostname}/key.pem"; + relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ]; + config = { + home_mailbox = "Maildir/"; + # 25 MiB + message_size_limit = "26214400"; + # hostname used in helo command. It is recommended to have this match the reverse dns entry + smtp_helo_name = config.networking.rDNS; + smtpd_banner = "${config.networking.rDNS} ESMTP $mail_name"; + smtp_use_tls = true; + # smtp_tls_security_level = "encrypt"; + smtpd_use_tls = true; + # smtpd_tls_security_level = lib.mkForce "encrypt"; + # smtpd_tls_auth_only = true; + smtpd_tls_protocols = [ + "!SSLv2" + "!SSLv3" + "!TLSv1" + "!TLSv1.1" + ]; + # "reject_non_fqdn_hostname" + smtpd_recipient_restrictions = [ + "permit_sasl_authenticated" + "permit_mynetworks" + "reject_unauth_destination" + "reject_non_fqdn_sender" + "reject_non_fqdn_recipient" + "reject_unknown_sender_domain" + "reject_unknown_recipient_domain" + "reject_unauth_destination" + "reject_unauth_pipelining" + "reject_invalid_hostname" + "check_policy_service inet:localhost:12340" + ]; + smtpd_relay_restrictions = [ + "permit_sasl_authenticated" + "permit_mynetworks" + "reject_unauth_destination" + ]; + # https://www.postfix.org/smtp-smuggling.html + smtpd_data_restrictions = [ + "reject_unauth_pipelining" + ]; + smtpd_sender_restrictions = [ + "reject_authenticated_sender_login_mismatch" + ]; + smtpd_sender_login_maps = [ + "pcre:/etc/special-aliases.pcre" + "pcre:${login_maps}" + ]; + smtp_header_checks = "pcre:${header_cleanup}"; + # smtpd_sender_login_maps = [ "ldap:${ldap-senders}" ]; + alias_maps = [ "hash:/etc/aliases" ]; + alias_database = [ "hash:/etc/aliases" ]; + # alias_maps = [ "hash:/etc/aliases" "ldap:${ldap-aliases}" ]; + smtpd_sasl_auth_enable = true; + smtpd_sasl_path = "/var/lib/postfix/auth"; + smtpd_sasl_type = "dovecot"; + #mailman stuff + mailbox_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp"; + + transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ]; + virtual_alias_maps = [ "hash:/var/lib/mailman/data/postfix_vmap" ]; + local_recipient_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" "ldap:${config.sops.secrets."postfix_ldap_aliases".path}" "$alias_maps" ]; + }; + }; + }; +} diff --git a/modules/mail/rspamd.nix b/modules/mail/rspamd.nix new file mode 100644 index 0000000..6eebf63 --- /dev/null +++ b/modules/mail/rspamd.nix @@ -0,0 +1,143 @@ +{ config, pkgs, ... }: +let + domain = "rspamd.${config.networking.domain}"; +in +{ + sops.secrets."rspamd-password".owner = config.users.users.rspamd.name; + users.users.rspamd.extraGroups = [ "redis-rspamd" ]; + services = { + rspamd = { + enable = true; + postfix.enable = true; + locals = { + "worker-controller.inc".source = config.sops.secrets."rspamd-password".path; + "redis.conf".text = '' + read_servers = "/run/redis-rspamd/redis.sock"; + write_servers = "/run/redis-rspamd/redis.sock"; + ''; + # headers in spamassasin style to not break old sieve scripts + "worker-proxy.inc".text = '' + spam_header = "X-Spam-Flag"; + ''; + "milter_headers.conf".text = '' + use = ["x-spam-level", "x-spam-status", "x-spamd-result", "authentication-results" ]; + ''; + "neural.conf".text = '' + servers = "/run/redis-rspamd/redis.sock"; + enabled = true; + ''; + "neural_group.conf".text = '' + symbols = { + "NEURAL_SPAM" { + weight = 0.5; # fairly low weight since we don't know how this will behave + description = "Neural network spam"; + } + "NEURAL_HAM" { + weight = -0.5; + description = "Neural network ham"; + } + } + ''; + "dmarc.conf".text = '' + reporting { + enabled = true; + email = 'reports@${config.networking.domain}'; + domain = '${config.networking.domain}'; + org_name = '${config.networking.domain}'; + from_name = 'DMARC Aggregate Report'; + } + ''; + "dkim_signing.conf".text = '' + selector = "quitte2024"; + allow_username_mismatch = true; + allow_hdrfrom_mismatch = true; + use_domain_sign_local = "ifsr.de"; + path = /var/lib/rspamd/dkim/$domain.$selector.key; + + ''; + + "multimap.conf".text = + let + local_ips = pkgs.writeText "localhost.map" '' + ::1 + 127.0.0.1 + ''; + tud_ips = pkgs.writeText "tud.map" '' + 141.30.0.0/16 + 141.76.0.0/16 + ''; + in + '' + WHITELIST_SENDER_DOMAIN { + type = "from"; + filter = "email:domain"; + map = "/var/lib/rspamd/whitelist.sender.domain.map"; + action = "accept"; + } + WHITELIST_SENDER_EMAIL { + type = "from"; + map = "/var/lib/rspamd/whitelist.sender.email.map"; + action = "accept"; + } + BLACKLIST_SENDER_DOMAIN { + type = "from"; + filter = "email:domain"; + map = "/var/lib/rspamd/blacklist.sender.domain.map"; + action = "reject"; + } + BLACKLIST_SENDER_EMAIL { + type = "from"; + map = "/var/lib/rspamd/blacklist.sender.email.map"; + action = "reject"; + } + BLACKLIST_SUBJECT_KEYWORDS { + type = "header"; + header = "Subject" + map = "/var/lib/rspamd/blacklist.keyword.subject.map"; + action = "reject"; + regexp = true; + } + RECEIVED_LOCALHOST { + type = "ip"; + action = "accept"; + map = ${local_ips}; + } + RECEIVED_TU_NETWORKS { + type = "ip"; + map = ${tud_ips}; + } + ''; + }; + }; + redis = { + vmOverCommit = true; + servers.rspamd = { + enable = true; + }; + }; + nginx = { + virtualHosts."${domain}" = { + forceSSL = true; + enableACME = true; + locations = { + "/" = { + proxyPass = "http://127.0.0.1:11334"; + proxyWebsockets = true; + }; + }; + }; + }; + }; + systemd = { + services.rspamd-dmarc-report = { + description = "rspamd dmarc reporter"; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.rspamd}/bin/rspamadm dmarc_report -v"; + User = "rspamd"; + Group = "rspamd"; + }; + startAt = "daily"; + }; + }; +} diff --git a/modules/sogo.nix b/modules/mail/sogo.nix similarity index 100% rename from modules/sogo.nix rename to modules/mail/sogo.nix -- 2.44.2 From b429e6468f404dde549fddfdf68bc28c0ae82d9f Mon Sep 17 00:00:00 2001 From: Rouven Seifert Date: Tue, 12 Mar 2024 11:49:01 +0100 Subject: [PATCH 2/7] refactor: streamline all websites into one folder --- flake.nix | 13 ++----------- modules/web/default.nix | 15 +++++++++++++++ modules/{ese-website.nix => web/ese.nix} | 0 modules/{ => web}/fsrewsp.nix | 0 modules/{ => web}/ftp.nix | 0 modules/{website.nix => web/ifsrde.nix} | 0 modules/{ => web}/infoscreen.nix | 0 modules/{ => web}/kpp.nix | 0 modules/{ => web}/manual.nix | 0 modules/{ => web}/nightline.nix | 0 modules/{ => web}/sharepic.nix | 0 modules/{ => web}/userdir.nix | 0 12 files changed, 17 insertions(+), 11 deletions(-) create mode 100644 modules/web/default.nix rename modules/{ese-website.nix => web/ese.nix} (100%) rename modules/{ => web}/fsrewsp.nix (100%) rename modules/{ => web}/ftp.nix (100%) rename modules/{website.nix => web/ifsrde.nix} (100%) rename modules/{ => web}/infoscreen.nix (100%) rename modules/{ => web}/kpp.nix (100%) rename modules/{ => web}/manual.nix (100%) rename modules/{ => web}/nightline.nix (100%) rename modules/{ => web}/sharepic.nix (100%) rename modules/{ => web}/userdir.nix (100%) diff --git a/flake.nix b/flake.nix index 55c7942..b000074 100755 --- a/flake.nix +++ b/flake.nix @@ -75,18 +75,15 @@ ./modules/options.nix ./modules/base.nix ./modules/sops.nix - ./modules/kpp.nix - ./modules/ese-website.nix ./modules/ldap ./modules/sssd.nix ./modules/mail - ./modules/mailman.nix + ./modules/web + ./modules/mysql.nix ./modules/nix-serve.nix ./modules/nginx.nix - # ./modules/hydra.nix - ./modules/userdir.nix ./modules/hedgedoc.nix ./modules/padlist.nix ./modules/postgres.nix @@ -97,20 +94,14 @@ ./modules/matrix.nix ./modules/mautrix-telegram.nix ./modules/vaultwarden.nix - ./modules/website.nix ./modules/zsh.nix ./modules/course-management.nix ./modules/courses-phil.nix ./modules/gitea.nix ./modules/fail2ban.nix ./modules/kanboard.nix - ./modules/infoscreen.nix - ./modules/manual.nix - ./modules/sharepic.nix ./modules/zammad.nix ./modules/initrd-ssh.nix - ./modules/fsrewsp.nix - ./modules/nightline.nix ./modules/decisions.nix ./modules/struktur-bot.nix { diff --git a/modules/web/default.nix b/modules/web/default.nix new file mode 100644 index 0000000..262ea0b --- /dev/null +++ b/modules/web/default.nix @@ -0,0 +1,15 @@ +{ ... }: +{ + imports = [ + ./ifsrde.nix + ./ese.nix + ./infoscreen.nix + ./kpp.nix + ./nightline.nix + ./fsrewsp.nix + ./manual.nix + ./sharepic.nix + ./userdir.nix + ./ftp.nix + ]; +} diff --git a/modules/ese-website.nix b/modules/web/ese.nix similarity index 100% rename from modules/ese-website.nix rename to modules/web/ese.nix diff --git a/modules/fsrewsp.nix b/modules/web/fsrewsp.nix similarity index 100% rename from modules/fsrewsp.nix rename to modules/web/fsrewsp.nix diff --git a/modules/ftp.nix b/modules/web/ftp.nix similarity index 100% rename from modules/ftp.nix rename to modules/web/ftp.nix diff --git a/modules/website.nix b/modules/web/ifsrde.nix similarity index 100% rename from modules/website.nix rename to modules/web/ifsrde.nix diff --git a/modules/infoscreen.nix b/modules/web/infoscreen.nix similarity index 100% rename from modules/infoscreen.nix rename to modules/web/infoscreen.nix diff --git a/modules/kpp.nix b/modules/web/kpp.nix similarity index 100% rename from modules/kpp.nix rename to modules/web/kpp.nix diff --git a/modules/manual.nix b/modules/web/manual.nix similarity index 100% rename from modules/manual.nix rename to modules/web/manual.nix diff --git a/modules/nightline.nix b/modules/web/nightline.nix similarity index 100% rename from modules/nightline.nix rename to modules/web/nightline.nix diff --git a/modules/sharepic.nix b/modules/web/sharepic.nix similarity index 100% rename from modules/sharepic.nix rename to modules/web/sharepic.nix diff --git a/modules/userdir.nix b/modules/web/userdir.nix similarity index 100% rename from modules/userdir.nix rename to modules/web/userdir.nix -- 2.44.2 From 01bcc9ecaddec64740e6b21c9008aeaf09fe6756 Mon Sep 17 00:00:00 2001 From: Rouven Seifert Date: Tue, 12 Mar 2024 12:03:29 +0100 Subject: [PATCH 3/7] refactor: streamline core modules into dedicated folder --- flake.nix | 20 +++++--------------- modules/{ => core}/bacula.nix | 0 modules/{ => core}/base.nix | 16 ++++++++-------- modules/core/default.nix | 14 ++++++++++++++ modules/{ => core}/fail2ban.nix | 0 modules/{ => core}/initrd-ssh.nix | 0 modules/{ => core}/mysql.nix | 0 modules/{ => core}/nginx.nix | 0 modules/{ => core}/postgres.nix | 0 modules/{ => core}/sssd.nix | 0 modules/{ => core}/zsh.nix | 0 modules/sops.nix | 5 ----- 12 files changed, 27 insertions(+), 28 deletions(-) rename modules/{ => core}/bacula.nix (100%) rename modules/{ => core}/base.nix (93%) create mode 100644 modules/core/default.nix rename modules/{ => core}/fail2ban.nix (100%) rename modules/{ => core}/initrd-ssh.nix (100%) rename modules/{ => core}/mysql.nix (100%) rename modules/{ => core}/nginx.nix (100%) rename modules/{ => core}/postgres.nix (100%) rename modules/{ => core}/sssd.nix (100%) rename modules/{ => core}/zsh.nix (100%) delete mode 100644 modules/sops.nix diff --git a/flake.nix b/flake.nix index b000074..24c42bd 100755 --- a/flake.nix +++ b/flake.nix @@ -71,37 +71,27 @@ course-management.nixosModules.default vscode-server.nixosModules.default ./hosts/quitte/configuration.nix - ./modules/bacula.nix ./modules/options.nix - ./modules/base.nix - ./modules/sops.nix + ./modules/core ./modules/ldap - ./modules/sssd.nix ./modules/mail ./modules/web - ./modules/mysql.nix ./modules/nix-serve.nix - ./modules/nginx.nix ./modules/hedgedoc.nix ./modules/padlist.nix - ./modules/postgres.nix ./modules/wiki - ./modules/ftp.nix #./modules/stream.nix ./modules/nextcloud.nix ./modules/matrix.nix ./modules/mautrix-telegram.nix ./modules/vaultwarden.nix - ./modules/zsh.nix ./modules/course-management.nix ./modules/courses-phil.nix ./modules/gitea.nix - ./modules/fail2ban.nix ./modules/kanboard.nix ./modules/zammad.nix - ./modules/initrd-ssh.nix ./modules/decisions.nix ./modules/struktur-bot.nix { @@ -119,10 +109,10 @@ vscode-server.nixosModules.default print-interface.nixosModules.default ./hosts/tomate/configuration.nix - ./modules/base.nix - ./modules/zsh.nix - ./modules/fail2ban.nix - ./modules/sssd.nix + ./modules/core/base.nix + ./modules/core/zsh.nix + ./modules/core/fail2ban.nix + ./modules/core/sssd.nix { sops.defaultSopsFile = ./secrets/tomate.yaml; } diff --git a/modules/bacula.nix b/modules/core/bacula.nix similarity index 100% rename from modules/bacula.nix rename to modules/core/bacula.nix diff --git a/modules/base.nix b/modules/core/base.nix similarity index 93% rename from modules/base.nix rename to modules/core/base.nix index a514e81..f74cd9e 100755 --- a/modules/base.nix +++ b/modules/core/base.nix @@ -54,14 +54,14 @@ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINJgYI2rXmw4uPXAMmOgqgJEwYfwj/IBExTCzs9Dgo+R w0lff" ]; keyFiles = [ - ../keys/ssh/marcus-sapphire - ../keys/ssh/schrader - ../keys/ssh/jannusch - ../keys/ssh/jannusch-arch - ../keys/ssh/tassilo - ../keys/ssh/jonasga - ../keys/ssh/rouven - ../keys/ssh/joachim + ../../keys/ssh/marcus-sapphire + ../../keys/ssh/schrader + ../../keys/ssh/jannusch + ../../keys/ssh/jannusch-arch + ../../keys/ssh/tassilo + ../../keys/ssh/jonasga + ../../keys/ssh/rouven + ../../keys/ssh/joachim ]; }; diff --git a/modules/core/default.nix b/modules/core/default.nix new file mode 100644 index 0000000..c4badf4 --- /dev/null +++ b/modules/core/default.nix @@ -0,0 +1,14 @@ +{ ... }: +{ + imports = [ + ./base.nix + ./bacula.nix + ./fail2ban.nix + ./initrd-ssh.nix + ./mysql.nix + ./nginx.nix + ./postgres.nix + ./sssd.nix + ./zsh.nix + ]; +} diff --git a/modules/fail2ban.nix b/modules/core/fail2ban.nix similarity index 100% rename from modules/fail2ban.nix rename to modules/core/fail2ban.nix diff --git a/modules/initrd-ssh.nix b/modules/core/initrd-ssh.nix similarity index 100% rename from modules/initrd-ssh.nix rename to modules/core/initrd-ssh.nix diff --git a/modules/mysql.nix b/modules/core/mysql.nix similarity index 100% rename from modules/mysql.nix rename to modules/core/mysql.nix diff --git a/modules/nginx.nix b/modules/core/nginx.nix similarity index 100% rename from modules/nginx.nix rename to modules/core/nginx.nix diff --git a/modules/postgres.nix b/modules/core/postgres.nix similarity index 100% rename from modules/postgres.nix rename to modules/core/postgres.nix diff --git a/modules/sssd.nix b/modules/core/sssd.nix similarity index 100% rename from modules/sssd.nix rename to modules/core/sssd.nix diff --git a/modules/zsh.nix b/modules/core/zsh.nix similarity index 100% rename from modules/zsh.nix rename to modules/core/zsh.nix diff --git a/modules/sops.nix b/modules/sops.nix deleted file mode 100644 index d34979f..0000000 --- a/modules/sops.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ ... }: -{ - sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; - sops.age.generateKey = false; -} -- 2.44.2 From 527651706e75207c202a217d96df01f1f810412c Mon Sep 17 00:00:00 2001 From: Rouven Seifert Date: Tue, 12 Mar 2024 12:06:21 +0100 Subject: [PATCH 4/7] options: move to tree root --- flake.nix | 2 +- modules/options.nix => options/default.nix | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename modules/options.nix => options/default.nix (100%) diff --git a/flake.nix b/flake.nix index 24c42bd..b995abb 100755 --- a/flake.nix +++ b/flake.nix @@ -71,7 +71,7 @@ course-management.nixosModules.default vscode-server.nixosModules.default ./hosts/quitte/configuration.nix - ./modules/options.nix + ./options ./modules/core ./modules/ldap diff --git a/modules/options.nix b/options/default.nix similarity index 100% rename from modules/options.nix rename to options/default.nix -- 2.44.2 From fea01b0b2e289bb027cff250901e654f557fa17d Mon Sep 17 00:00:00 2001 From: Rouven Seifert Date: Tue, 12 Mar 2024 12:11:44 +0100 Subject: [PATCH 5/7] courses: move into folder --- flake.nix | 4 +--- modules/{course-management.nix => courses/default.nix} | 1 + modules/{courses-phil.nix => courses/phil.nix} | 0 3 files changed, 2 insertions(+), 3 deletions(-) rename modules/{course-management.nix => courses/default.nix} (98%) rename modules/{courses-phil.nix => courses/phil.nix} (100%) diff --git a/flake.nix b/flake.nix index b995abb..97cf582 100755 --- a/flake.nix +++ b/flake.nix @@ -77,18 +77,16 @@ ./modules/ldap ./modules/mail ./modules/web + ./modules/courses ./modules/nix-serve.nix ./modules/hedgedoc.nix ./modules/padlist.nix ./modules/wiki - #./modules/stream.nix ./modules/nextcloud.nix ./modules/matrix.nix ./modules/mautrix-telegram.nix ./modules/vaultwarden.nix - ./modules/course-management.nix - ./modules/courses-phil.nix ./modules/gitea.nix ./modules/kanboard.nix ./modules/zammad.nix diff --git a/modules/course-management.nix b/modules/courses/default.nix similarity index 98% rename from modules/course-management.nix rename to modules/courses/default.nix index 098d40e..86f4c5a 100644 --- a/modules/course-management.nix +++ b/modules/courses/default.nix @@ -3,6 +3,7 @@ let hostName = "kurse.${config.networking.domain}"; in { + imports = [ ./phil.nix ]; sops.secrets = let inherit (config.services.course-management) user; in diff --git a/modules/courses-phil.nix b/modules/courses/phil.nix similarity index 100% rename from modules/courses-phil.nix rename to modules/courses/phil.nix -- 2.44.2 From 39320d987cadf2b4899369b5a979eae5f9f06b1d Mon Sep 17 00:00:00 2001 From: Rouven Seifert Date: Tue, 12 Mar 2024 12:34:20 +0100 Subject: [PATCH 6/7] matrix: move into folder --- flake.nix | 5 ++--- modules/{matrix.nix => matrix/default.nix} | 1 + modules/{ => matrix}/mautrix-telegram.nix | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename modules/{matrix.nix => matrix/default.nix} (99%) rename modules/{ => matrix}/mautrix-telegram.nix (100%) diff --git a/flake.nix b/flake.nix index 97cf582..e55c42f 100755 --- a/flake.nix +++ b/flake.nix @@ -78,14 +78,13 @@ ./modules/mail ./modules/web ./modules/courses + ./modules/wiki + ./modules/matrix ./modules/nix-serve.nix ./modules/hedgedoc.nix ./modules/padlist.nix - ./modules/wiki ./modules/nextcloud.nix - ./modules/matrix.nix - ./modules/mautrix-telegram.nix ./modules/vaultwarden.nix ./modules/gitea.nix ./modules/kanboard.nix diff --git a/modules/matrix.nix b/modules/matrix/default.nix similarity index 99% rename from modules/matrix.nix rename to modules/matrix/default.nix index bd23979..95fd87d 100644 --- a/modules/matrix.nix +++ b/modules/matrix/default.nix @@ -22,6 +22,7 @@ let matrix-synapse-ldap3 = config.services.matrix-synapse.package.plugins.matrix-synapse-ldap3; in { + imports = [ ./mautrix-telegram.nix ]; sops.secrets.matrix_ldap_search = { key = "portunus/search-password"; owner = config.systemd.services.matrix-synapse.serviceConfig.User; diff --git a/modules/mautrix-telegram.nix b/modules/matrix/mautrix-telegram.nix similarity index 100% rename from modules/mautrix-telegram.nix rename to modules/matrix/mautrix-telegram.nix -- 2.44.2 From 7023c328d9dc0a8da4a93ed605549c6883bf8544 Mon Sep 17 00:00:00 2001 From: Rouven Seifert Date: Thu, 14 Mar 2024 00:09:06 +0100 Subject: [PATCH 7/7] mail: move mailman options to mailman.nix --- modules/mail/mailman.nix | 9 +++++++++ modules/mail/postfix.nix | 8 +------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/mail/mailman.nix b/modules/mail/mailman.nix index 9b691f0..c8dba9b 100644 --- a/modules/mail/mailman.nix +++ b/modules/mail/mailman.nix @@ -40,6 +40,15 @@ superUserGroup = "cn=admins,ou=groups,dc=ifsr,dc=de"; }; }; + services.postfix = { + relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ]; + config = { + mailbox_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp"; + transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ]; + virtual_alias_maps = [ "hash:/var/lib/mailman/data/postfix_vmap" ]; + local_recipient_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ]; + }; + }; services.postgresql = { enable = true; ensureUsers = [ diff --git a/modules/mail/postfix.nix b/modules/mail/postfix.nix index 4a79e04..fb5887a 100644 --- a/modules/mail/postfix.nix +++ b/modules/mail/postfix.nix @@ -37,7 +37,6 @@ in networksStyle = "host"; # localhost and own public IP sslCert = "/var/lib/acme/${hostname}/fullchain.pem"; sslKey = "/var/lib/acme/${hostname}/key.pem"; - relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ]; config = { home_mailbox = "Maildir/"; # 25 MiB @@ -94,12 +93,7 @@ in smtpd_sasl_auth_enable = true; smtpd_sasl_path = "/var/lib/postfix/auth"; smtpd_sasl_type = "dovecot"; - #mailman stuff - mailbox_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp"; - - transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ]; - virtual_alias_maps = [ "hash:/var/lib/mailman/data/postfix_vmap" ]; - local_recipient_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" "ldap:${config.sops.secrets."postfix_ldap_aliases".path}" "$alias_maps" ]; + local_recipient_maps = [ "ldap:${config.sops.secrets."postfix_ldap_aliases".path}" "$alias_maps" ]; }; }; }; -- 2.44.2