From 1c01ebffa950bf25911a092e7b46d556297ca541 Mon Sep 17 00:00:00 2001 From: Julien Moutinho <julm@sourcephile.fr> Date: Mon, 5 Apr 2021 13:20:52 +0200 Subject: [PATCH] discourse: prepare postfix, postgresql and redis --- hosts/losurdo.nix | 4 +- hosts/losurdo/fail2ban.nix | 2 +- hosts/losurdo/postfix.nix | 318 ++++++++++++++++++++++++ hosts/losurdo/postfix/sourcephile.nix | 31 +++ hosts/losurdo/postgresql.nix | 27 +- hosts/losurdo/redis.nix | 39 +++ hosts/mermet/postfix.nix | 54 +--- hosts/mermet/postfix/autogeree.net.nix | 5 +- hosts/mermet/postfix/sourcephile.fr.nix | 7 +- nixos/defaults.nix | 1 + nixos/modules.nix | 1 + nixos/modules/services/mail/postfix.nix | 47 ++++ 12 files changed, 468 insertions(+), 68 deletions(-) create mode 100644 hosts/losurdo/postfix.nix create mode 100644 hosts/losurdo/postfix/sourcephile.nix create mode 100644 hosts/losurdo/redis.nix create mode 100644 nixos/modules/services/mail/postfix.nix diff --git a/hosts/losurdo.nix b/hosts/losurdo.nix index 72d6389..98baa27 100644 --- a/hosts/losurdo.nix +++ b/hosts/losurdo.nix @@ -32,7 +32,9 @@ modules = [ losurdo/hardware.nix losurdo/networking.nix losurdo/nginx.nix - #losurdo/postgresql.nix + losurdo/postfix.nix + losurdo/postgresql.nix + losurdo/redis.nix losurdo/sanoid.nix losurdo/security.nix losurdo/syncoid.nix diff --git a/hosts/losurdo/fail2ban.nix b/hosts/losurdo/fail2ban.nix index 528695e..854c22a 100644 --- a/hosts/losurdo/fail2ban.nix +++ b/hosts/losurdo/fail2ban.nix @@ -1,7 +1,7 @@ { pkgs, lib, config, hosts, ... }: { services.openssh.logLevel = "VERBOSE"; -services.postgresql.settings.log_line_prefix = "%h "; +services.postgresql.logLinePrefix = "%h "; /* systemd.services.nftables.postStart = '' systemctl reload fail2ban ''; */ diff --git a/hosts/losurdo/postfix.nix b/hosts/losurdo/postfix.nix new file mode 100644 index 0000000..45fce73 --- /dev/null +++ b/hosts/losurdo/postfix.nix @@ -0,0 +1,318 @@ +{ pkgs, lib, config, ... }: +let + inherit (lib) types; + inherit (config) networking users; + inherit (config.services) postfix; +in +{ +imports = [ + #postfix/autogeree.net.nix + #postfix/sourcephile.fr.nix +]; +users.groups.acme.members = [ postfix.user ]; +/* +networking.nftables.ruleset = '' + add rule inet filter net2fw tcp dport 25 counter accept comment "SMTP" + add rule inet filter net2fw tcp dport 465 counter accept comment "submissions" + add rule inet filter fw2net meta skuid ${postfix.user} tcp dport 25 counter accept comment "SMTP" +''; +*/ +services.postfix = { + enable = true; + networksStyle = "host"; + hostname ="${networking.hostName}.${networking.domain}"; + domain = networking.domain; + origin = "$myhostname"; + destination = [ + "localhost" + "localhost.localdomain" + "$myhostname" + ]; + postmasterAlias = "root"; + rootAlias = "root@${networking.domain}"; + sslKey = "/var/lib/acme/${networking.domain}/key.pem"; + sslCert = "/var/lib/acme/${networking.domain}/fullchain.pem"; + networks = [ + "127.0.0.0/8" + "[::1]/128" + ]; + setSendmail = true; + # Parse the extension in email address, eg. contact+extension@ + recipientDelimiter = "+"; + config = { + debug_peer_level = "4"; + debug_peer_list = [ + #"chomsky.autogeree.net" + #"localhost" + #"mail.sourcephile.fr" + ]; + + # + # Sending to the world + # + # Appending .domain is the MUA's job + append_dot_mydomain = false; + smtp_body_checks = ""; + #smtp_cname_overrides_servername = false; + smtp_connect_timeout = "60s"; + #smtp_header_checks = "regexp:/var/lib/postfix/smtp_header_checks"; + smtp_mime_header_checks = ""; + smtp_nested_header_checks = ""; + smtp_tls_exclude_ciphers = [ "ADH" "MD5" "CAMELLIA" "SEED" "3DES" "DES" "RC4" "eNULL" "aNULL" ]; + #smtp_tls_fingerprint_digest = "sha1"; + smtp_tls_loglevel = "1"; + #smtp_tls_note_starttls_offer = true; + #smtp_tls_policy_maps = "hash:/var/lib/postfix/conf/tls_policy"; + # Only allow TLSv* protocols + smtp_tls_protocols = [ "!SSLv2" "!SSLv3" ]; + #smtp_tls_scert_verifydepth = "5"; + #smtp_tls_secure_cert_match = [ "nexthop" "dot-nexthop" ]; + smtp_tls_security_level = "may"; + smtp_tls_session_cache_database = "btree:$data_directory/smtp_tls_session_cache"; + #smtp_tls_session_cache_timeout = "3600s"; + #smtp_tls_verify_cert_match = "hostname"; + + # + # Receiving from the world + # + message_size_limit = "20480000"; + maximal_queue_lifetime = "5d"; + default_extra_recipient_limit = "5000"; + line_length_limit = "2048"; + duplicate_filter_limit = "5000"; + # Stops mail from poorly written software + strict_rfc821_envelopes = true; + mime_header_checks = []; + milter_header_checks = []; + nested_header_checks = []; + body_checks = []; + content_filter = ""; + permit_mx_backup_networks = []; + propagate_unmatched_extensions = [ "canonical" "virtual" "alias" ]; + #masquerade_classes = [ "envelope_sender" "header_sender" "header_recipient" ]; + #masquerade_domains = ""; + #masquerade_exceptions = "root"; + queue_minfree = "0"; + # Stops some techniques used to harvest email addresses + disable_vrfy_command = true; + enable_long_queue_ids = false; + # Useful to test restrictions + smtpd_authorized_xclient_hosts = "127.0.0.1"; + smtpd_banner = "$myhostname ESMTP $mail_name (NixOS)"; + smtpd_client_connection_count_limit = "50"; + smtpd_client_connection_rate_limit = "0"; + smtpd_client_event_limit_exceptions = "$mynetworks"; + smtpd_client_message_rate_limit = "0"; + smtpd_client_new_tls_session_rate_limit = "0"; + smtpd_client_port_logging = false; + smtpd_client_recipient_rate_limit = "0"; + # Ban 5 sec on error + smtpd_error_sleep_time = "5"; + # Needed to enforce reject_unknown_helo_hostname + smtpd_helo_required = true; + smtpd_helo_restrictions = [ + "reject_invalid_helo_hostname" + "reject_non_fqdn_helo_hostname" + # Don't talk to mail systems that don't know their own hostname. + "reject_unknown_helo_hostname" + "permit" + ]; + smtpd_client_restrictions = [ + ]; + # Set in postfix/*.nix and used in submissions/smptd + # with reject_sender_login_mismatch + smtpd_sender_login_maps = []; + smtpd_sender_restrictions = [ + "reject_non_fqdn_sender" + "permit" + ]; + smtpd_reject_unlisted_recipient = true; + # Check the RCPT TO, before smtpd_recipient_restrictions + # Restrictions based on what is allowed or not, + # these are applied before smtpd_recipient_restrictions + smtpd_relay_restrictions = [ + "permit_mynetworks" + # Check the recipient's address in virtual_mailbox_domains and virtual_mailbox_maps + "permit_auth_destination" + # The world is only authorized to use our relay for the above destinations. + "reject" + ]; + # Restrictions based on what is working or not + smtpd_recipient_restrictions = [ + # Reject if the domain is not fully qualified + "reject_non_fqdn_recipient" + # Reject if the domain is not working, even before bothering to check the address + "reject_unknown_recipient_domain" + # Reject if the address is not working + # WARNING: this does not work if the recipient is greylisting. + # WARNING: verify(8) has a cache, dumpable if verify(8) is stopped, with: + # postmap -s btree:/var/lib/postfix/data/verify_cache + #"reject_unverified_recipient" + "permit" + ]; + # Trust the verify database + #unverified_recipient_reject_code = "550"; + smtpd_data_restrictions = [ + # Force the smtpd's client to wait OK before sending + "reject_unauth_pipelining" + "permit" + ]; + smtpd_end_of_data_restrictions = [ + # Enforce mail volume quota via policy service callouts. + #check_policy_service unix:private/policy + ]; + #smtpd_milters = ""; + smtpd_peername_lookup = true; + smtpd_recipient_limit = "5000"; + smtpd_recipient_overshoot_limit = "5000"; + #smtpd_restriction_classes = ""; + #smtpd_sasl_auth_enable = true; + #smtpd_sasl_path = "private/auth"; + #smtpd_sasl_security_options = "noanonymous"; + #smtpd_sasl_type = "dovecot"; + smtpd_starttls_timeout = "300s"; + #smtpd_tls_always_issue_session_ids = true; + #smtpd_tls_CApath = "/etc/postfix/x509/ca/"; + smtpd_tls_ask_ccert = false; + #smtpd_tls_ccert_verifydepth = "5"; + smtpd_tls_ciphers = "high"; + smtpd_tls_eecdh_grade = "auto"; + # Disable weak ciphers as reported by https://ssl-tools.net + # https://serverfault.com/questions/744168/how-to-disable-rc4-on-postfix + smtpd_tls_exclude_ciphers = [ "ADH" "MD5" "CAMELLIA" "SEED" "3DES" "DES" "RC4" "eNULL" "aNULL" ]; + smtpd_tls_fingerprint_digest = "sha512"; + # Log only a summary message on TLS handshake completion + smtpd_tls_loglevel = "1"; + smtpd_tls_mandatory_ciphers = "high"; + smtpd_tls_mandatory_protocols = [ "!SSLv2" "!SSLv3" ]; + # Only allow TLSv* + smtpd_tls_protocols = [ "!SSLv2" "!SSLv3" ]; + #smtpd_tls_received_header = false; + smtpd_tls_req_ccert = false; + # Postfix 2.3 and later + # encrypt + # Mandatory TLS encryption: announce STARTTLS support to SMTP clients, and require that clients use TLS + # encryption. According to [1720]RFC 2487 this MUST NOT be applied in case of a publicly-referenced + # SMTP server. Instead, this option should be used only on dedicated servers. + smtpd_tls_security_level = "may"; + smtpd_tls_session_cache_database = "btree:$data_directory/smtpd_tls_session_cache"; + #smtpd_tls_session_cache_timeout = "3600s"; + #smtpd_tls_chain_files = + + relayhost = []; + #relay_clientcerts = hash:/var/lib/postfix/conf/relay_clientcerts + # This is where to put backup MX domains + relay_domains = []; + relay_recipient_maps = []; + + # Use a non blocking source of randomness + tls_random_source = "dev:/dev/urandom"; + # Map each domain to a specific X.509 certificate + tls_server_sni_maps = "hash:/run/keys/postfix-sni"; + + # Only explicitely aliased accounts have a mail, not all the passwd + local_recipient_maps = "$alias_maps"; + # Note that the local transport rewrites the envelope recipient + # according to the alias_maps, and thus the aliasing is transparent + # to the nexthop (eg. dovecot) + #local_transport = local:$myhostname + # No console bell on new mail + biff = false; + forward_path = [ + /* + "$home/.forward''${recipient_delimiter}''${extension}" + */ + "$home/.forward" + ]; + + # Filled by the postfix/*.nix + virtual_mailbox_domains = []; + # Completed by the postfix/*.nix + virtual_mailbox_maps = [ + "hash:/etc/postfix/virtual" + ]; + #virtual_transport = "lmtp:unix:private/dovecot-lmtp"; + /* + dovecot_destination_recipient_limit = "1"; + virtual_transport = "dovecot"; + */ + + # There is no fallback + fallback_transport = ""; + }; + virtualMapType = "hash"; + masterConfig = + let + mkVal = value: + if lib.isList value + then lib.concatStringsSep "," value + else + if value == true then "yes" + else if value == false then "no" + else toString value; + mkKeyVal = opt: val: [ "-o" (opt + "=" + mkVal val) ]; + mkArgs = args: lib.concatLists (lib.mapAttrsToList mkKeyVal args); + in { + pickup = { + args = mkArgs { + cleanup_service_name = "submissions-header-cleanup"; + }; + }; + /* + # Implicit TLS on port 465 + # https://tools.ietf.org/html/rfc8314#section-3.3 + submissions = { + type = "inet"; + private = false; + command = "smtpd"; + args = mkArgs { + syslog_name = "postfix/submissions"; + # Implicit TLS, not STARTTLS + smtpd_tls_wrappermode = true; + smtpd_tls_mandatory_protocols = [ + "TLSv1.3" + # FIXME: to be removed when K-9 Mail will support TLSv1.3, + # K-9 Mail 5.600 does not. + "TLSv1.2" + ]; + milter_macro_daemon_name = "ORIGINATING"; + smtpd_helo_restrictions = [ + "permit_sasl_authenticated" + ] ++ postfix.config.smtpd_helo_restrictions; + smtpd_relay_restrictions = [ + # SASL authorizes to send to the world + "permit_sasl_authenticated" + "reject" + ]; + smtpd_sasl_auth_enable = true; + smtpd_sasl_type = "dovecot"; + smtpd_sasl_path = "private/auth"; + smtpd_sasl_local_domain = ""; + # Offer SASL authentication only after a TLS-encrypted session has been established + smtpd_tls_auth_only = true; + smtpd_sasl_tls_security_options = [ "noanonymous" ]; + # Do not put SASL logins in mail headers + smtpd_sasl_authenticated_header = false; + # Who cares about (old) Outlook + broken_sasl_auth_clients = false; + smtpd_sender_restrictions = [ + "reject_non_fqdn_sender" + # Check that the SASL user is using only its own + # mail addresses on the envelope, as indicated in smtpd_sender_login_maps + "reject_sender_login_mismatch" + "permit" + ]; + # No X.509 certificates for users, for now + smtpd_tls_ask_ccert = false; + smtpd_tls_ccert_verifydepth = 0; + smtpd_tls_loglevel = 1; + smtpd_tls_req_ccert = false; + cleanup_service_name = "submissions-header-cleanup"; + }; + }; + */ + }; + extraMasterConf = '' + ''; +}; +} diff --git a/hosts/losurdo/postfix/sourcephile.nix b/hosts/losurdo/postfix/sourcephile.nix new file mode 100644 index 0000000..36fe1a8 --- /dev/null +++ b/hosts/losurdo/postfix/sourcephile.nix @@ -0,0 +1,31 @@ +{ pkgs, lib, config, ... }: +let domain = "sourcephile.fr"; in +{ +services.postfix = { + extraAliases = '' + ''; + virtual = '' + root@${domain} julm+root@${domain} + ''; + tls_server_sni_maps = + let chain = [ + "/var/lib/acme/${domain}/key.pem" + "/var/lib/acme/${domain}/fullchain.pem" + ]; in { + "smtp.${domain}" = chain; + "mail.${domain}" = chain; + }; + config = { + virtual_mailbox_domains = [ + domain + ]; + }; +}; +security.acme.certs."${domain}" = { + postRun = "systemctl reload postfix"; +}; +systemd.services.postfix = { + wants = [ "acme-selfsigned-${domain}.service" "acme-${domain}.service"]; + after = [ "acme-selfsigned-${domain}.service" ]; +}; +} diff --git a/hosts/losurdo/postgresql.nix b/hosts/losurdo/postgresql.nix index 3622384..33824c7 100644 --- a/hosts/losurdo/postgresql.nix +++ b/hosts/losurdo/postgresql.nix @@ -1,32 +1,37 @@ { pkgs, lib, config, hostName, ... }: let - inherit (config) networking; + inherit (config.networking) domain; inherit (config.services) postgresql; inherit (config.users) users; in { imports = + []; + /* map (eta: (import postgresql/openconcerto.nix) eta) [ {db = "openconcerto1";} {db = "openconcerto2";} {db = "lbec";} {db = "lbm";} ]; + */ +/* networking.nftables.ruleset = '' add rule inet filter net2fw tcp dport 5432 counter accept comment "PostgreSQL" ''; +*/ users.groups.acme.members = [ users."postgres".name ]; -security.acme.certs."${networking.domain}" = { +security.acme.certs."${domain}" = { postRun = "systemctl reload postgresql"; }; systemd.services.postgresql = { - wants = [ "acme-selfsigned-${networking.domain}.service" "acme-${networking.domain}.service"]; - after = [ "acme-selfsigned-${networking.domain}.service" ]; + wants = [ "acme-selfsigned-${domain}.service" "acme-${domain}.service"]; + after = [ "acme-selfsigned-${domain}.service" ]; }; services.postgresql = { enable = true; - package = pkgs.postgresql_9_6; - enableTCPIP = true; + package = pkgs.postgresql_12; + #enableTCPIP = true; settings = { # ZFS is Copy on Write (CoW). As a result, itâs not possible # to have a torn page because a page canât be partially written @@ -37,10 +42,10 @@ services.postgresql = { log_hostname = false; max_connections = 25; max_locks_per_transaction = 1024; - password_encryption = "on"; # FIXME: replace md5 by scram-sha-256, which requires postfix >= 11 - ssl = true; - ssl_cert_file = "/var/lib/acme/${networking.domain}/fullchain.pem"; - ssl_key_file = "/var/lib/acme/${networking.domain}/key.pem"; + password_encryption = "scram-sha-256"; # requires postfix >= 11 + ssl = false; + ssl_cert_file = "/var/lib/acme/${domain}/fullchain.pem"; + ssl_key_file = "/var/lib/acme/${domain}/key.pem"; unix_socket_permissions = "0770"; }; authentication = lib.mkForce '' @@ -67,7 +72,7 @@ fileSystems."/var/lib/postgresql" = { services.syncoid.commands = { "${hostName}/var/postgresql" = { sendOptions = "raw"; - target = "backup@mermet.${networking.domain}:rpool/backup/${hostName}/var/postgresql"; + target = "backup@mermet.${domain}:rpool/backup/${hostName}/var/postgresql"; }; }; services.sanoid.datasets = { diff --git a/hosts/losurdo/redis.nix b/hosts/losurdo/redis.nix new file mode 100644 index 0000000..5b1f904 --- /dev/null +++ b/hosts/losurdo/redis.nix @@ -0,0 +1,39 @@ +{ pkgs, lib, config, ... }: +let + inherit (config.networking) hostName; + inherit (config.users) users; +in +{ +fileSystems."/var/lib/redis" = { + device = "${hostName}/var/redis"; + fsType = "zfs"; +}; + +services.redis = { + enable = true; + unixSocket = "/run/redis/redis.socket"; + databases = 16; + syslog = true; + bind = "127.0.0.1 ::1"; + settings = { + unixsocketperm = "660"; + maxclients = 1024; + maxmemory = "500mb"; + maxmemory-policy = "volatile-ttl"; + }; +}; + +users.users.redis.group = "redis"; +users.groups."redis" = {}; + +systemd.services.redis.serviceConfig = { + RuntimeDirectoryMode = "0750"; + Group = users.redis.group; +}; + +# As suggested by redis in its logs +boot.kernel.sysctl."vm.overcommit_memory" = 1; +system.activationScripts.redis = '' + echo never >/sys/kernel/mm/transparent_hugepage/enabled +''; +} diff --git a/hosts/mermet/postfix.nix b/hosts/mermet/postfix.nix index d7dec64..fc0eb00 100644 --- a/hosts/mermet/postfix.nix +++ b/hosts/mermet/postfix.nix @@ -1,38 +1,16 @@ { pkgs, lib, config, ... }: let - inherit (builtins) attrNames concatStringsSep readFile toPath; + inherit (builtins) attrNames readFile toPath; inherit (lib) types; - inherit (pkgs.lib) loadFile unlines unwords unlinesAttrs; inherit (config) networking users; inherit (config.services) postfix dovecot2 openldap; - domains = [ - "sourcephile.fr" - "autogeree.net" - ]; in { -imports = map (domain: (./postfix + "/${domain}.nix")) domains; -options = { - services.postfix = { - tls_server_sni_maps = lib.mkOption { - type = types.attrsOf (types.listOf types.path); - default = {}; - apply = m: pkgs.writeText "sni" (lib.concatStringsSep "\n" (lib.mapAttrsToList (domain: x509: '' - ${domain} ${unwords x509} - '') m)); - }; - }; -}; -config = { +imports = [ + postfix/autogeree.net.nix + postfix/sourcephile.fr.nix +]; users.groups.acme.members = [ postfix.user ]; -systemd.services.postfix = { - wants = ["openldap.service"]; - after = ["openldap.service"]; - preStart = '' - install -m 400 -o root -g root ${postfix.tls_server_sni_maps} /run/keys/postfix-sni - ${pkgs.postfix}/bin/postmap -F hash:/run/keys/postfix-sni - ''; -}; networking.nftables.ruleset = '' add rule inet filter net2fw tcp dport 25 counter accept comment "SMTP" add rule inet filter net2fw tcp dport 465 counter accept comment "submissions" @@ -266,7 +244,7 @@ services.postfix = { let mkVal = value: if lib.isList value - then concatStringsSep "," value + then lib.concatStringsSep "," value else if value == true then "yes" else if value == false then "no" @@ -330,25 +308,6 @@ services.postfix = { cleanup_service_name = "submissions-header-cleanup"; }; }; - submissions-header-cleanup = { - type = "unix"; - private = false; - maxproc = 0; - command = "cleanup"; - args = mkArgs { - header_checks = "pcre:" + pkgs.writeText "submission_header_cleanup_rules" '' - # Removes sensitive headers from mails handed in via the submission or smtps port. - # See https://thomas-leister.de/mailserver-debian-stretch/ - # Uses "pcre" style regex. - - /^Received:/ IGNORE - /^User-Agent:/ IGNORE - /^X-Enigmail:/ IGNORE - /^X-Mailer:/ IGNORE - /^X-Originating-IP:/ IGNORE - ''; - }; - }; }; extraMasterConf = '' #spfcheck unix - n n - 0 spawn @@ -434,5 +393,4 @@ services.postfix = { #noclue unix - n n - - pipe # flags=q user=noclue argv=/usr/local/bin/noclue-delivery ${recipient} ${sender} }; -}; } diff --git a/hosts/mermet/postfix/autogeree.net.nix b/hosts/mermet/postfix/autogeree.net.nix index 9609404..cbdacfc 100644 --- a/hosts/mermet/postfix/autogeree.net.nix +++ b/hosts/mermet/postfix/autogeree.net.nix @@ -1,6 +1,5 @@ { pkgs, lib, config, ... }: let - inherit (pkgs.lib) loadFile; domain = "autogeree.net"; domainSuffix = "dc=autogeree,dc=net"; in @@ -62,7 +61,7 @@ security.acme.certs."${domain}" = { postRun = "systemctl reload postfix"; }; systemd.services.postfix = { - wants = [ "acme-selfsigned-${domain}.service" "acme-${domain}.service"]; - after = [ "acme-selfsigned-${domain}.service" ]; + wants = [ "openldap.service" "acme-selfsigned-${domain}.service" "acme-${domain}.service"]; + after = [ "openldap.service" "acme-selfsigned-${domain}.service" ]; }; } diff --git a/hosts/mermet/postfix/sourcephile.fr.nix b/hosts/mermet/postfix/sourcephile.fr.nix index 8584a89..3e8b9a9 100644 --- a/hosts/mermet/postfix/sourcephile.fr.nix +++ b/hosts/mermet/postfix/sourcephile.fr.nix @@ -1,6 +1,5 @@ { pkgs, lib, config, ... }: let - inherit (pkgs.lib) loadFile; domain = "sourcephile.fr"; domainSuffix = "dc=sourcephile,dc=fr"; in @@ -16,7 +15,7 @@ services.postfix = { ecole@${domain} public-inbox@localhost environnement@${domain} public-inbox@localhost labo@${domain} public-inbox@localhost - hosts@${domain} public-inbox@localhost + hosts@${domain} public-inbox@localhost pont@${domain} public-inbox@localhost test@${domain} public-inbox@localhost ''; @@ -73,7 +72,7 @@ security.acme.certs."${domain}" = { postRun = "systemctl reload postfix"; }; systemd.services.postfix = { - wants = [ "acme-selfsigned-${domain}.service" "acme-${domain}.service"]; - after = [ "acme-selfsigned-${domain}.service" ]; + wants = [ "openldap.service" "acme-selfsigned-${domain}.service" "acme-${domain}.service"]; + after = [ "openldap.service" "acme-selfsigned-${domain}.service" ]; }; } diff --git a/nixos/defaults.nix b/nixos/defaults.nix index 0c7ccaf..b8446c4 100644 --- a/nixos/defaults.nix +++ b/nixos/defaults.nix @@ -127,6 +127,7 @@ environment.systemPackages = with pkgs; [ nethogs nload nmon + #ntop pv rdfind smem diff --git a/nixos/modules.nix b/nixos/modules.nix index 5e43a91..32e922e 100644 --- a/nixos/modules.nix +++ b/nixos/modules.nix @@ -5,6 +5,7 @@ imports = [ #modules/services/databases/openldap.nix modules/services/mail/public-inbox.nix + modules/services/mail/postfix.nix modules/services/networking/upnpc.nix #modules/services/security/tor.nix #modules/services/backup/syncoid.nix diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix new file mode 100644 index 0000000..916dffa --- /dev/null +++ b/nixos/modules/services/mail/postfix.nix @@ -0,0 +1,47 @@ +{ pkgs, lib, config, ... }: +let + inherit (lib) types; + inherit (config.services) postfix; +in +{ +options = { + services.postfix = { + tls_server_sni_maps = lib.mkOption { + type = types.attrsOf (types.listOf types.path); + default = {}; + apply = m: pkgs.writeText "sni" (lib.concatStringsSep "\n" (lib.mapAttrsToList (domain: x509: '' + ${domain} ${lib.concatStringsSep " " x509} + '') m)); + }; + }; +}; +config = { + systemd.services.postfix = { + preStart = '' + install -m 400 -o root -g root ${postfix.tls_server_sni_maps} /run/keys/postfix-sni + ${pkgs.postfix}/bin/postmap -F hash:/run/keys/postfix-sni + ''; + }; + services.postfix = { + masterConfig = { + submissions-header-cleanup = { + type = "unix"; + private = false; + maxproc = 0; + command = "cleanup"; + args = ["-o" ("header_checks=pcre:" + pkgs.writeText "submission_header_cleanup_rules" '' + # Removes sensitive headers from mails handed in via the submission or smtps port. + # See https://thomas-leister.de/mailserver-debian-stretch/ + # Uses "pcre" style regex. + + /^Received:/ IGNORE + /^User-Agent:/ IGNORE + /^X-Enigmail:/ IGNORE + /^X-Mailer:/ IGNORE + /^X-Originating-IP:/ IGNORE + '')]; + }; + }; + }; +}; +} -- 2.47.2