nixConfig/nixos/modules/mailman.nix

139 lines
4.9 KiB
Nix
Raw Normal View History

2024-02-05 20:36:51 +00:00
# Adapted and simplified from https://nixos.wiki/wiki/Mailman
{
config,
lib,
2024-03-31 14:26:11 +00:00
pkgs,
2024-02-05 20:36:51 +00:00
...
}: let
inherit
(lib)
mkIf
mkEnableOption
mkOption
;
inherit (lib.types) nonEmptyStr;
cfg = config.services.mathebau-mailman;
in {
options.services.mathebau-mailman = {
enable = mkEnableOption "mathebau mailman service";
hostName = mkOption {
type = nonEmptyStr;
};
siteOwner = mkOption {
type = nonEmptyStr;
};
};
config = mkIf cfg.enable {
services = {
postfix = {
enable = true;
relayDomains = ["hash:/var/lib/mailman/data/postfix_domains"];
sslCert = config.security.acme.certs.${cfg.hostName}.directory + "/full.pem";
sslKey = config.security.acme.certs.${cfg.hostName}.directory + "/key.pem";
config = {
transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
local_recipient_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
proxy_interfaces = "130.83.2.184";
smtputf8_enable = "no"; # HRZ does not know SMTPUTF8
};
2024-03-31 18:28:40 +00:00
relayHost = "192.168.0.24"; # Relay to eihort which relays to HRZ (see https://www.hrz.tu-darmstadt.de/services/it_services/email_infrastruktur/index.de.jsp)
2024-02-05 20:36:51 +00:00
};
mailman = {
enable = true;
inherit (cfg) siteOwner;
hyperkitty.enable = true;
webHosts = [cfg.hostName];
serve.enable = true; #
2024-03-31 14:26:11 +00:00
# Don't include confirmation tokens in reply addresses, because we would need to send them to HRZ otherwise.
settings.mta.verp_confirmations = "no";
2024-02-05 20:36:51 +00:00
};
nginx.virtualHosts.${cfg.hostName} = {
2024-03-31 14:26:11 +00:00
enableACME = true; # Get certificates (primarily for postfix)
forceSSL = false; # Don't use HTTPS behind the proxy
2024-02-05 20:36:51 +00:00
};
};
environment.persistence.${config.impermanence.name} = {
directories = [
"/var/lib/acme" # Persist TLS keys and account
"/var/lib/mailman"
"/var/lib/mailman-web"
];
2024-03-31 18:28:40 +00:00
files = ["/root/.ssh/known_hosts"]; # for the backup server bragi
2024-02-05 20:36:51 +00:00
};
security.acme.defaults.email = cfg.siteOwner;
security.acme.acceptTerms = true;
networking.firewall.allowedTCPPorts = [25 80 443];
2024-03-31 14:26:11 +00:00
# Update HRZ allowlist
# For account details see https://www-cgi.hrz.tu-darmstadt.de/mail/
# will stop working if no valid TUIDs are associated to our domain.
systemd.timers."mailAllowlist" = {
wantedBy = ["timers.target"];
timerConfig = {
OnBootSec = "5m"; # Run every 5 minutes
OnUnitActiveSec = "5m";
RandomizedDelaySec = "2m"; # prevent overload on regular intervals
Unit = "mailAllowlist.service";
};
};
systemd.services."mailAllowlist" = {
description = "Allowlist update: Post the mail addresses used by mailman to the HRZ allowllist";
script = ''
# Get the mail addresses' local-part
cut -d '@' -f 1 /var/lib/mailman/data/postfix_lmtp | grep -v '#' | grep "\S" > /tmp/addresses
# Post local-parts to HRZ
${pkgs.curl}/bin/curl https://www-cgi.hrz.tu-darmstadt.de/mail/whitelist-update.php -F emaildomain=${cfg.hostName} -F password=$(cat /run/secrets/allowlistPass) -F emailliste=@/tmp/addresses -F meldungen=voll
# Cleanup
rm /tmp/addresses
'';
serviceConfig = {
Type = "oneshot";
User = "mailman";
NoNewPrivileges = true;
# See https://www.man7.org/linux/man-pages/man5/systemd.exec.5.html
2024-03-31 14:26:11 +00:00
PrivateTmp = true;
ProtectHome = true;
ReadOnlyPaths = "/";
ReadWritePaths = "/tmp";
InaccessiblePaths = "-/lost+found";
PrivateDevices = true;
PrivateUsers = true;
ProtectHostname = true;
ProtectClock = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
2024-03-31 14:26:11 +00:00
};
};
2024-03-31 18:28:40 +00:00
# Backups
services.borgbackup.jobs.mailman = {
paths = [
"/var/lib/mailman/data"
"/var/lib/mailman-web"
];
encryption.mode = "none"; # Otherwise the key is next to the backup or we have human interaction.
environment = {
BORG_RSH = "ssh -i /run/secrets/backupKey";
# “Borg ensures that backups are not created on random drives that just happen to contain a Borg repository.”
# https://borgbackup.readthedocs.io/en/stable/deployment/automated-local.html
# We don't want this in order to not need to persist borg cache and simplify new deployments.
BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK = "yes";
};
repo = "borg@192.168.1.11:lobon"; # TODO for https://gitea.mathebau.de/Fachschaft/nixConfig/issues/33
startAt = "daily";
user = "root";
group = "root";
2024-03-31 14:26:11 +00:00
};
2024-02-05 20:36:51 +00:00
};
}