summaryrefslogtreecommitdiff
path: root/hosts/surtr/email/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'hosts/surtr/email/default.nix')
-rw-r--r--hosts/surtr/email/default.nix105
1 files changed, 85 insertions, 20 deletions
diff --git a/hosts/surtr/email/default.nix b/hosts/surtr/email/default.nix
index 845f6455..c6253e4c 100644
--- a/hosts/surtr/email/default.nix
+++ b/hosts/surtr/email/default.nix
@@ -1,4 +1,4 @@
1{ config, pkgs, lib, flakeInputs, ... }: 1{ config, pkgs, lib, flake, flakeInputs, ... }:
2 2
3with lib; 3with lib;
4 4
@@ -15,7 +15,7 @@ let
15 15
16 for file in $out/pipe/bin/*; do 16 for file in $out/pipe/bin/*; do
17 wrapProgram $file \ 17 wrapProgram $file \
18 --set PATH "${pkgs.coreutils}/bin:${pkgs.rspamd}/bin" 18 --set PATH "${makeBinPath (with pkgs; [coreutils rspamd])}"
19 done 19 done
20 ''; 20 '';
21 }; 21 };
@@ -33,12 +33,28 @@ let
33 }); 33 });
34 }); 34 });
35 }; 35 };
36 internal-policy-server =
37 let
38 workspace = flakeInputs.uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./internal-policy-server; };
39 pythonSet = flake.lib.pythonSet {
40 inherit pkgs;
41 python = pkgs.python312;
42 overlay = workspace.mkPyprojectOverlay {
43 sourcePreference = "wheel";
44 };
45 };
46 virtualEnv = pythonSet.mkVirtualEnv "internal-policy-server-env" workspace.deps.default;
47 in virtualEnv.overrideAttrs (oldAttrs: {
48 meta = (oldAttrs.meta or {}) // {
49 mainProgram = "internal-policy-server";
50 };
51 });
36 52
37 nftables-nologin-script = pkgs.writeScript "nftables-mail-nologin" '' 53 nftables-nologin-script = pkgs.resholve.writeScript "nftables-mail-nologin" {
38 #!${pkgs.zsh}/bin/zsh 54 inputs = with pkgs; [inetutils nftables gnugrep findutils];
39 55 interpreter = lib.getExe pkgs.zsh;
56 } ''
40 set -e 57 set -e
41 export PATH="${lib.makeBinPath (with pkgs; [inetutils nftables])}:$PATH"
42 58
43 typeset -a as_sets mnt_bys route route6 59 typeset -a as_sets mnt_bys route route6
44 as_sets=(${lib.escapeShellArgs config.services.email.nologin.ASSets}) 60 as_sets=(${lib.escapeShellArgs config.services.email.nologin.ASSets})
@@ -51,7 +67,7 @@ let
51 elif [[ "''${line}" =~ "^route6:\s+(.+)$" ]]; then 67 elif [[ "''${line}" =~ "^route6:\s+(.+)$" ]]; then
52 route6+=($match[1]) 68 route6+=($match[1])
53 fi 69 fi
54 done < <(whois -h whois.radb.net "!i''${as_set},1" | egrep -o 'AS[0-9]+' | xargs -- whois -h whois.radb.net -- -i origin) 70 done < <(whois -h whois.radb.net "!i''${as_set},1" | grep -Eo 'AS[0-9]+' | xargs whois -h whois.radb.net -- -i origin)
55 done 71 done
56 for mnt_by in $mnt_bys; do 72 for mnt_by in $mnt_bys; do
57 while IFS=$'\n' read line; do 73 while IFS=$'\n' read line; do
@@ -190,6 +206,7 @@ in {
190 "reject_unauth_destination" 206 "reject_unauth_destination"
191 "reject_unknown_recipient_domain" 207 "reject_unknown_recipient_domain"
192 "reject_unverified_recipient" 208 "reject_unverified_recipient"
209 "check_policy_service unix:/run/postfix-internal-policy.sock"
193 ]; 210 ];
194 unverified_recipient_reject_code = "550"; 211 unverified_recipient_reject_code = "550";
195 unverified_recipient_reject_reason = "Recipient address lookup failed"; 212 unverified_recipient_reject_reason = "Recipient address lookup failed";
@@ -251,7 +268,7 @@ in {
251 virtual_transport = "dvlmtp:unix:/run/dovecot-lmtp"; 268 virtual_transport = "dvlmtp:unix:/run/dovecot-lmtp";
252 smtputf8_enable = false; 269 smtputf8_enable = false;
253 270
254 authorized_submit_users = "inline:{ root= postfwd= }"; 271 authorized_submit_users = "inline:{ root= postfwd= dovecot2= }";
255 272
256 postscreen_access_list = ""; 273 postscreen_access_list = "";
257 postscreen_denylist_action = "drop"; 274 postscreen_denylist_action = "drop";
@@ -280,7 +297,7 @@ in {
280 hosts = postgresql:///email 297 hosts = postgresql:///email
281 dbname = email 298 dbname = email
282 query = SELECT action FROM virtual_mailbox_access WHERE lookup = '%s' OR (lookup = regexp_replace('%s', '\+[^@]*@', '@') AND NOT EXISTS (SELECT 1 FROM virtual_mailbox_access WHERE lookup = '%s')) 299 query = SELECT action FROM virtual_mailbox_access WHERE lookup = '%s' OR (lookup = regexp_replace('%s', '\+[^@]*@', '@') AND NOT EXISTS (SELECT 1 FROM virtual_mailbox_access WHERE lookup = '%s'))
283 ''},permit_tls_all_clientcerts,reject}'' 300 ''},check_policy_service unix:/run/postfix-internal-policy.sock,permit_tls_all_clientcerts,reject}''
284 "-o" "smtpd_relay_restrictions=permit_tls_all_clientcerts,reject" 301 "-o" "smtpd_relay_restrictions=permit_tls_all_clientcerts,reject"
285 "-o" "{smtpd_data_restrictions = check_policy_service unix:/run/postfwd3/postfwd3.sock}" 302 "-o" "{smtpd_data_restrictions = check_policy_service unix:/run/postfwd3/postfwd3.sock}"
286 "-o" "unverified_sender_reject_code=550" 303 "-o" "unverified_sender_reject_code=550"
@@ -310,7 +327,7 @@ in {
310 hosts = postgresql:///email 327 hosts = postgresql:///email
311 dbname = email 328 dbname = email
312 query = SELECT action FROM virtual_mailbox_access WHERE lookup = '%s' OR (lookup = regexp_replace('%s', '\+[^@]*@', '@') AND NOT EXISTS (SELECT 1 FROM virtual_mailbox_access WHERE lookup = '%s')) 329 query = SELECT action FROM virtual_mailbox_access WHERE lookup = '%s' OR (lookup = regexp_replace('%s', '\+[^@]*@', '@') AND NOT EXISTS (SELECT 1 FROM virtual_mailbox_access WHERE lookup = '%s'))
313 ''},permit_sasl_authenticated,reject}'' 330 ''},check_policy_service unix:/run/postfix-internal-policy.sock,permit_sasl_authenticated,reject}''
314 "-o" "smtpd_relay_restrictions=permit_sasl_authenticated,reject" 331 "-o" "smtpd_relay_restrictions=permit_sasl_authenticated,reject"
315 "-o" "{smtpd_data_restrictions = check_policy_service unix:/run/postfwd3/postfwd3.sock}" 332 "-o" "{smtpd_data_restrictions = check_policy_service unix:/run/postfwd3/postfwd3.sock}"
316 "-o" "unverified_sender_reject_code=550" 333 "-o" "unverified_sender_reject_code=550"
@@ -672,7 +689,7 @@ in {
672 plugin { 689 plugin {
673 plugin = fts fts_xapian 690 plugin = fts fts_xapian
674 fts = xapian 691 fts = xapian
675 fts_xapian = partial=2 full=20 attachments=1 verbose=1 692 fts_xapian = partial=3 full=20 attachments=1 verbose=1
676 693
677 fts_autoindex = yes 694 fts_autoindex = yes
678 695
@@ -692,7 +709,7 @@ in {
692 startAt = "*-*-* 22:00:00 Europe/Berlin"; 709 startAt = "*-*-* 22:00:00 Europe/Berlin";
693 serviceConfig = { 710 serviceConfig = {
694 Type = "oneshot"; 711 Type = "oneshot";
695 ExecStart = "${pkgs.dovecot}/bin/doveadm fts optimize -A"; 712 ExecStart = "${getExe' pkgs.dovecot "doveadm"} fts optimize -A";
696 PrivateDevices = true; 713 PrivateDevices = true;
697 PrivateNetwork = true; 714 PrivateNetwork = true;
698 ProtectKernelTunables = true; 715 ProtectKernelTunables = true;
@@ -777,7 +794,7 @@ in {
777 systemd.services.dovecot2 = { 794 systemd.services.dovecot2 = {
778 preStart = '' 795 preStart = ''
779 for f in /etc/dovecot/sieve_flag.d/*.sieve /etc/dovecot/sieve_before.d/*.sieve; do 796 for f in /etc/dovecot/sieve_flag.d/*.sieve /etc/dovecot/sieve_before.d/*.sieve; do
780 ${pkgs.dovecot_pigeonhole}/bin/sievec $f 797 ${getExe' pkgs.dovecot_pigeonhole "sievec"} $f
781 done 798 done
782 ''; 799 '';
783 800
@@ -844,15 +861,16 @@ in {
844 charset utf-8; 861 charset utf-8;
845 source_charset utf-8; 862 source_charset utf-8;
846 ''; 863 '';
847 root = pkgs.runCommand "mta-sts.${domain}" {} '' 864 root = pkgs.writeTextFile {
848 mkdir -p $out/.well-known 865 name = "mta-sts.${domain}";
849 cp ${pkgs.writeText "mta-sts.${domain}.txt" '' 866 destination = "/.well-known/mta-sts.txt";
867 text = ''
850 version: STSv1 868 version: STSv1
851 mode: enforce 869 mode: enforce
852 max_age: 2419200 870 max_age: 2419200
853 mx: mailin.${domain} 871 mx: mailin.${domain}
854 ''} $out/.well-known/mta-sts.txt 872 '';
855 ''; 873 };
856 }; 874 };
857 }) emailDomains); 875 }) emailDomains);
858 }; 876 };
@@ -869,7 +887,7 @@ in {
869 systemd.services.spm = { 887 systemd.services.spm = {
870 serviceConfig = { 888 serviceConfig = {
871 Type = "notify"; 889 Type = "notify";
872 ExecStart = "${pkgs.spm}/bin/spm-server"; 890 ExecStart = getExe' pkgs.spm "spm-server";
873 User = "spm"; 891 User = "spm";
874 Group = "spm"; 892 Group = "spm";
875 893
@@ -927,7 +945,7 @@ in {
927 serviceConfig = { 945 serviceConfig = {
928 Type = "notify"; 946 Type = "notify";
929 947
930 ExecStart = "${ccert-policy-server}/bin/ccert-policy-server"; 948 ExecStart = getExe' ccert-policy-server "ccert-policy-server";
931 949
932 Environment = [ 950 Environment = [
933 "PGDATABASE=email" 951 "PGDATABASE=email"
@@ -960,6 +978,53 @@ in {
960 }; 978 };
961 users.groups."postfix-ccert-sender-policy" = {}; 979 users.groups."postfix-ccert-sender-policy" = {};
962 980
981 systemd.sockets."postfix-internal-policy" = {
982 requiredBy = ["postfix.service"];
983 wants = ["postfix-internal-policy.service"];
984 socketConfig = {
985 ListenStream = "/run/postfix-internal-policy.sock";
986 };
987 };
988 systemd.services."postfix-internal-policy" = {
989 after = [ "postgresql.service" ];
990 bindsTo = [ "postgresql.service" ];
991
992 serviceConfig = {
993 Type = "notify";
994
995 ExecStart = lib.getExe internal-policy-server;
996
997 Environment = [
998 "PGDATABASE=email"
999 ];
1000
1001 DynamicUser = false;
1002 User = "postfix-internal-policy";
1003 Group = "postfix-internal-policy";
1004 ProtectSystem = "strict";
1005 SystemCallFilter = "@system-service";
1006 NoNewPrivileges = true;
1007 ProtectKernelTunables = true;
1008 ProtectKernelModules = true;
1009 ProtectKernelLogs = true;
1010 ProtectControlGroups = true;
1011 MemoryDenyWriteExecute = true;
1012 RestrictSUIDSGID = true;
1013 KeyringMode = "private";
1014 ProtectClock = true;
1015 RestrictRealtime = true;
1016 PrivateDevices = true;
1017 PrivateTmp = true;
1018 ProtectHostname = true;
1019 ReadWritePaths = ["/run/postgresql"];
1020 };
1021 };
1022 users.users."postfix-internal-policy" = {
1023 isSystemUser = true;
1024 group = "postfix-internal-policy";
1025 };
1026 users.groups."postfix-internal-policy" = {};
1027
963 services.postfwd = { 1028 services.postfwd = {
964 enable = true; 1029 enable = true;
965 cache = false; 1030 cache = false;