diff options
Diffstat (limited to 'hosts/surtr/email/default.nix')
-rw-r--r-- | hosts/surtr/email/default.nix | 90 |
1 files changed, 76 insertions, 14 deletions
diff --git a/hosts/surtr/email/default.nix b/hosts/surtr/email/default.nix index 404e9e4b..947aa328 100644 --- a/hosts/surtr/email/default.nix +++ b/hosts/surtr/email/default.nix | |||
@@ -21,6 +21,8 @@ let | |||
21 | }; | 21 | }; |
22 | 22 | ||
23 | spmDomains = ["bouncy.email"]; | 23 | spmDomains = ["bouncy.email"]; |
24 | |||
25 | spm = pkgs.callPackage ./spm {}; | ||
24 | in { | 26 | in { |
25 | config = { | 27 | config = { |
26 | nixpkgs.overlays = [ | 28 | nixpkgs.overlays = [ |
@@ -115,6 +117,8 @@ in { | |||
115 | "reject_unknown_recipient_domain" | 117 | "reject_unknown_recipient_domain" |
116 | "reject_unverified_recipient" | 118 | "reject_unverified_recipient" |
117 | ]; | 119 | ]; |
120 | unverified_recipient_reject_code = "550"; | ||
121 | unverified_recipient_reject_reason = "Recipient address rejected: undeliverable address"; | ||
118 | 122 | ||
119 | smtpd_relay_restrictions = [ | 123 | smtpd_relay_restrictions = [ |
120 | "permit_mynetworks" | 124 | "permit_mynetworks" |
@@ -177,6 +181,9 @@ in { | |||
177 | "-o" "smtpd_tls_req_ccert=yes" | 181 | "-o" "smtpd_tls_req_ccert=yes" |
178 | "-o" "smtpd_client_restrictions=permit_tls_all_clientcerts,reject" | 182 | "-o" "smtpd_client_restrictions=permit_tls_all_clientcerts,reject" |
179 | "-o" "smtpd_relay_restrictions=permit_tls_all_clientcerts,reject" | 183 | "-o" "smtpd_relay_restrictions=permit_tls_all_clientcerts,reject" |
184 | "-o" "smtpd_sender_restrictions=reject_unknown_sender_domain,reject_unverified_sender" | ||
185 | "-o" "unverified_sender_reject_code=550" | ||
186 | "-o" "unverified_sender_reject_reason={Sender address rejected: undeliverable address}" | ||
180 | "-o" "smtpd_recipient_restrictions=reject_unauth_pipelining,reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_tls_all_clientcerts,reject" | 187 | "-o" "smtpd_recipient_restrictions=reject_unauth_pipelining,reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_tls_all_clientcerts,reject" |
181 | "-o" "milter_macro_daemon_name=surtr.yggdrasil.li" | 188 | "-o" "milter_macro_daemon_name=surtr.yggdrasil.li" |
182 | "-o" ''smtpd_milters=${config.services.opendkim.socket}'' | 189 | "-o" ''smtpd_milters=${config.services.opendkim.socket}'' |
@@ -600,24 +607,79 @@ in { | |||
600 | }; | 607 | }; |
601 | }; | 608 | }; |
602 | 609 | ||
603 | services.nginx.virtualHosts = listToAttrs (map (domain: nameValuePair "spm.${domain}" { | 610 | services.nginx = { |
604 | forceSSL = true; | 611 | upstreams.spm = { |
605 | sslCertificate = "/run/credentials/nginx.service/spm.${domain}.pem"; | 612 | servers = { |
606 | sslCertificateKey = "/run/credentials/nginx.service/spm.${domain}.key.pem"; | 613 | "unix:/run/spm/server.sock" = {}; |
607 | extraConfig = '' | 614 | }; |
608 | ssl_stapling off; | 615 | }; |
609 | ssl_verify_client on; | 616 | |
610 | ssl_client_certificate ${toString ./ca/ca.crt}; | 617 | virtualHosts = listToAttrs (map (domain: nameValuePair "spm.${domain}" { |
611 | ''; | 618 | forceSSL = true; |
612 | locations."/".extraConfig = '' | 619 | sslCertificate = "/run/credentials/nginx.service/spm.${domain}.pem"; |
613 | default_type text/plain; | 620 | sslCertificateKey = "/run/credentials/nginx.service/spm.${domain}.key.pem"; |
614 | return 200 "$ssl_client_verify $ssl_client_s_dn ${domain}"; | 621 | extraConfig = '' |
615 | ''; | 622 | ssl_stapling off; |
616 | }) spmDomains); | 623 | ssl_verify_client on; |
624 | ssl_client_certificate ${toString ./ca/ca.crt}; | ||
625 | ''; | ||
626 | locations."/" = { | ||
627 | proxyPass = "http://spm"; | ||
628 | |||
629 | extraConfig = '' | ||
630 | proxy_set_header SSL-CLIENT-VERIFY $ssl_client_verify; | ||
631 | proxy_set_header SSL-CLIENT-S-DN $ssl_client_s_dn; | ||
632 | proxy_set_header SPM-DOMAIN "${domain}"; | ||
633 | ''; | ||
634 | }; | ||
635 | }) spmDomains); | ||
636 | }; | ||
617 | 637 | ||
618 | systemd.services.nginx.serviceConfig.LoadCredential = concatMap (domain: [ | 638 | systemd.services.nginx.serviceConfig.LoadCredential = concatMap (domain: [ |
619 | "spm.${domain}.key.pem:${config.security.acme.certs."spm.${domain}".directory}/key.pem" | 639 | "spm.${domain}.key.pem:${config.security.acme.certs."spm.${domain}".directory}/key.pem" |
620 | "spm.${domain}.pem:${config.security.acme.certs."spm.${domain}".directory}/fullchain.pem" | 640 | "spm.${domain}.pem:${config.security.acme.certs."spm.${domain}".directory}/fullchain.pem" |
621 | ]) spmDomains; | 641 | ]) spmDomains; |
642 | |||
643 | systemd.services.spm = { | ||
644 | serviceConfig = { | ||
645 | Type = "notify"; | ||
646 | ExecStart = "${spm}/bin/spm-server"; | ||
647 | User = "spm"; | ||
648 | Group = "spm"; | ||
649 | |||
650 | Environment = [ | ||
651 | "SPM_INSTANCE=ed1c0e1d-7be4-4dd5-b51a-291bad3ac9c9" | ||
652 | "PGCONNSTR=dbname=email" | ||
653 | ]; | ||
654 | |||
655 | LoadCredential = [ | ||
656 | "spm-keys.json:${config.sops.secrets."spm-keys.json".path}" | ||
657 | ]; | ||
658 | }; | ||
659 | }; | ||
660 | systemd.sockets.spm = { | ||
661 | wantedBy = [ "nginx.service" ]; | ||
662 | |||
663 | socketConfig = { | ||
664 | ListenStream = "/run/spm/server.sock"; | ||
665 | SocketUser = "spm"; | ||
666 | SocketGroup = "spm"; | ||
667 | SocketMode = 0660; | ||
668 | }; | ||
669 | }; | ||
670 | |||
671 | users.users.spm = { | ||
672 | isSystemUser = true; | ||
673 | group = "spm"; | ||
674 | }; | ||
675 | |||
676 | users.groups.spm = { | ||
677 | members = [ config.services.nginx.user ]; | ||
678 | }; | ||
679 | |||
680 | sops.secrets."spm-keys.json" = { | ||
681 | format = "binary"; | ||
682 | sopsFile = ./spm-keys.json; | ||
683 | }; | ||
622 | }; | 684 | }; |
623 | } | 685 | } |