From e185d301ff9b1b41ba239e912061685d28eb0d6a Mon Sep 17 00:00:00 2001 From: Thomas Preisner Date: Thu, 5 Dec 2024 16:04:01 +0100 Subject: [PATCH] mailsystem: Add option to use selfsigned certificates in preparation for testing --- mailsystem/common.nix | 18 +++++++++++++++--- mailsystem/default.nix | 14 ++++++++++++++ mailsystem/nginx.nix | 35 ++++++++++++++++++++--------------- mailsystem/rspamd.nix | 2 ++ mailsystem/selfsigned.nix | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 mailsystem/selfsigned.nix diff --git a/mailsystem/common.nix b/mailsystem/common.nix index f74539a..ab7174c 100644 --- a/mailsystem/common.nix +++ b/mailsystem/common.nix @@ -1,9 +1,21 @@ {config, ...}: let cfg = config.mailsystem; in rec { - sslCertPath = "${config.security.acme.certs.${cfg.fqdn}.directory}/fullchain.pem"; - sslKeyPath = "${config.security.acme.certs.${cfg.fqdn}.directory}/key.pem"; - sslCertService = ["acme-finished-${cfg.fqdn}.target"]; + certificateDirectory = "/var/certs"; + sslCertPath = + if cfg.certificateScheme == "acme" + then "${config.security.acme.certs.${cfg.fqdn}.directory}/fullchain.pem" + else "${certificateDirectory}/cert-${cfg.fqdn}.pem"; + + sslKeyPath = + if cfg.certificateScheme == "acme" + then "${config.security.acme.certs.${cfg.fqdn}.directory}/key.pem" + else "${certificateDirectory}/key-${cfg.fqdn}.pem"; + + sslCertService = + if cfg.certificateScheme == "acme" + then ["acme-finished-${cfg.fqdn}.target"] + else ["mailsystem-selfsigned-certificate.service"]; dovecotDynamicStateDir = "/var/lib/dovecot"; dovecotDynamicPasswdFile = "${dovecotDynamicStateDir}/passwd"; diff --git a/mailsystem/default.nix b/mailsystem/default.nix index 7cc0dc6..8da5133 100644 --- a/mailsystem/default.nix +++ b/mailsystem/default.nix @@ -151,6 +151,19 @@ in { ''; default = {}; }; + + certificateScheme = lib.mkOption { + type = lib.types.enum ["acme" "selfsigned"]; + default = "acme"; + description = '' + The scheme to use for managing TLS certificates: + + 1. `acme`: The server retrieves letsencrypt certificates via NixOS's acme module using nginx. + 2. `selfsigned`: The server creates self-signed certificates on the fly (intended for testing). + ''; + internal = true; + visible = false; + }; }; imports = [ @@ -161,6 +174,7 @@ in { ./redis.nix ./roundcube.nix ./rspamd.nix + ./selfsigned.nix ./user.nix ]; } diff --git a/mailsystem/nginx.nix b/mailsystem/nginx.nix index 7edd771..03e8f26 100644 --- a/mailsystem/nginx.nix +++ b/mailsystem/nginx.nix @@ -3,23 +3,28 @@ pkgs, lib, ... -}: let +}: +with (import ./common.nix {inherit config;}); let cfg = config.mailsystem; in { - config = lib.mkIf cfg.enable { - services.nginx = { - enable = true; - virtualHosts."${cfg.fqdn}" = { - forceSSL = true; - enableACME = true; + config = + lib.mkIf cfg.enable { + services.nginx = { + enable = true; + virtualHosts."${cfg.fqdn}" = { + forceSSL = true; + enableACME = cfg.certificateScheme == "acme"; + sslCertificate = lib.mkIf (cfg.certificateScheme == "selfsigned") sslCertPath; + sslCertificateKey = lib.mkIf (cfg.certificateScheme == "selfsigned") sslKeyPath; + }; }; + + networking.firewall.allowedTCPPorts = lib.optionals cfg.openFirewall [80 443]; + } + // lib.mkIf (cfg.enable && cfg.certificateScheme == "acme") { + security.acme.certs."${cfg.fqdn}".reloadServices = [ + "postfix.service" + "dovecot2.service" + ]; }; - - networking.firewall.allowedTCPPorts = lib.optionals cfg.openFirewall [80 443]; - - security.acme.certs."${cfg.fqdn}".reloadServices = [ - "postfix.service" - "dovecot2.service" - ]; - }; } diff --git a/mailsystem/rspamd.nix b/mailsystem/rspamd.nix index 9117072..55079ed 100644 --- a/mailsystem/rspamd.nix +++ b/mailsystem/rspamd.nix @@ -121,6 +121,8 @@ in { proxyPass = "http://unix:${rspamdControllerSocket}:/"; basicAuthFile = cfg.rspamd.webUi.basicAuthFile; }; + sslCertificate = lib.mkIf (cfg.certificateScheme == "selfsigned") sslCertPath; + sslCertificateKey = lib.mkIf (cfg.certificateScheme == "selfsigned") sslKeyPath; }; }; }; diff --git a/mailsystem/selfsigned.nix b/mailsystem/selfsigned.nix new file mode 100644 index 0000000..4506fcf --- /dev/null +++ b/mailsystem/selfsigned.nix @@ -0,0 +1,33 @@ +{ + config, + pkgs, + lib, + ... +}: +with (import ./common.nix {inherit config;}); let + cfg = config.mailsystem; +in { + config = lib.mkIf (cfg.enable && cfg.certificateScheme == "selfsigned") { + systemd.services.mailsystem-selfsigned-certificate = { + after = ["local-fs.target"]; + script = '' + # Create certificates if they do not exist yet + dir="${certificateDirectory}" + fqdn="${cfg.fqdn}" + [[ $fqdn == /* ]] && fqdn=$(< "$fqdn") + key="${sslKeyPath}" + cert="${sslCertPath}" + + if [[ ! -f $key || ! -f $cert ]]; then + mkdir -p "$dir" + (umask 077; "${pkgs.openssl}/bin/openssl" genrsa -out "$key" 4096) && + "${pkgs.openssl}/bin/openssl" req -new -key "$key" -x509 -subj "/CN=$fqdn" -days 3650 -out "$cert" + fi + ''; + serviceConfig = { + Type = "oneshot"; + PrivateTmp = true; + }; + }; + }; +}