WIP: nyarlathotep: cleanup after deployment #55

Draft
Gonne wants to merge 13 commits from Gonne/nixConfig:nyarlathotep into main
5 changed files with 166 additions and 35 deletions

View file

@ -15,10 +15,12 @@
stalwartAdminHash = "$argon2i$v=19$m=4096,t=3,p=1$d0hYOTkzclpzSmFTZUplWnhVeWE$I7q9uB19RWL0oZKaPlMPSlGfFp6FQ/vrx80FFKCsalg"; stalwartAdminHash = "$argon2i$v=19$m=4096,t=3,p=1$d0hYOTkzclpzSmFTZUplWnhVeWE$I7q9uB19RWL0oZKaPlMPSlGfFp6FQ/vrx80FFKCsalg";
domains = [ domains = [
# lists.mathebau.de is forwarded to another VM and does not need to be listed here. # lists.mathebau.de is forwarded to another VM and does not need to be listed here.
{ /*
{
domain = "matheball.de"; domain = "matheball.de";
allowlistPass = config.sops.secrets."allowlistPass/matheball".path; allowlistPass = config.sops.secrets."allowlistPass/matheball".path;
} }
*/
{ {
domain = "mathebau.de"; domain = "mathebau.de";
allowlistPass = config.sops.secrets."allowlistPass/mathebau".path; allowlistPass = config.sops.secrets."allowlistPass/mathebau".path;
@ -73,6 +75,18 @@
group = "stalwart-mail"; group = "stalwart-mail";
mode = "0440"; mode = "0440";
}; };
"dkim_rsa" = {
sopsFile = ./dkim.keys.yaml;
owner = "stalwart-mail";
group = "stalwart-mail";
mode = "0440";
};
"dkim_ed25519" = {
sopsFile = ./dkim.keys.yaml;
owner = "stalwart-mail";
group = "stalwart-mail";
mode = "0440";
};
# password for https://stalw.art/docs/auth/authorization/administrator/#fallback-administrator encoded to be supplied in the basic auth header # password for https://stalw.art/docs/auth/authorization/administrator/#fallback-administrator encoded to be supplied in the basic auth header
stalwartAdmin = { stalwartAdmin = {
sopsFile = ./stalwartAdmin.secrets.yaml; sopsFile = ./stalwartAdmin.secrets.yaml;

View file

@ -0,0 +1,40 @@
dkim_rsa: ENC[AES256_GCM,data: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,iv:QbZVXp5FQhmYZvXxXNxWKrNm5GqM+2P3a5pPk499mlc=,tag:F+KNoPRnoLLhOpEj6Czj6Q==,type:str]
dkim_ed25519: ENC[AES256_GCM,data:cZHm7bVpQ/VhYLt2CnNk9364k+J5ybgSLrR7Vm1GsCU6JcAvHl8Y5R7mqwgS+gTnHX7K02GuIGXa8909/aEotE0ZMY5irKJ25SGJqTaqQafbiMOz65CRQh5trtcMBF4s4wRYOkDGgz09KkELbkDHyQZFcrGqvgM=,iv:p9ROj/epqR3xtrimXF1onJJHH9JUqNG9z1MxKVu9uPg=,tag:m53rXkcu+ernS5JX+k8YcA==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6VnhvWHdsZWNHemlueFo4
L0xCTGp4NlRuU3YwRWJiSHFBbmtURTNMQkVRCnlSbFc0Q2xINjRvU2tQeStQc1U5
VElxcTVuNm9MUm01RkpGYytrYWg0czgKLS0tIHZqUWhkMGRNNjJvUTQrOHBpZXVS
NlpjeDQxbVZIRHFCcmNtT1JSVHp1K2sKSNcC0fcOar/KKzs1twaozB8wfdFT9OdB
4quV/ycNpJpfs6+2r0RTLBxYFyusybu1swosAni+PJsRXS82+PTXHQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsUTUzYzZuMkYvcTlrUmRK
aStnak5IWitFUSt0eVBQOHIzcTlrMFRFTjA4CmlYUTdobXFUK2tYMWtFekNqNnhp
R2RRRFdHc1p6bFVjYU9lbTRBeEM3Y2sKLS0tIHdsRW1wR25pVkZIYU1yMm9sQXpr
NFhiN0pyaHVWT1h5eVFXMWZDb0sxUGMKIVkYYheD8F9aaAyCA+m9ZGlV8vKbAW4r
H6FUe+ats30abxoYfHZfMJv17BxJtpodksSxWjnPYm0dfRf/EF/vSQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvU3NzY0Uxc0NhY2xJZyti
TCtTS1crV3hzMXZNV3k4cm0zUFNuY2tBL0dNCnNpYytoaUI1eERhdG1PUlZ2eE5C
R2UrVlBwcXR2L1VNR3RJL1lEQmlTSDgKLS0tIFJyLzhZeG5zejFmL2VkYy8xVEM1
U3QwOXlRdU8yd3ozL2hUVzRXNGE0bDQKT7SLAqICsbFmRUF+3s2avpBt0dLUbHLX
AgQzx5v6GpMMNwCkCrOnpFX6al7zkRSYHe7hbn03BBORz9mPHek5ew==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-03-02T07:58:00Z"
mac: ENC[AES256_GCM,data:OvERjDFfHTJbTfwq9BmXBQy6pjeyIhao6zP4we0KeYL3skbw4+aaMixjUFzjauby0C7nJjEPBSk6pwK3lN+rScS5g7J8tTNtmhfEDQbfsS5zNDKzIQjYxbUbDr2cTPWwCA73gRGMwLbyNvdfuEp46jNV8OJ8km/y2nyG9lDcBb4=,iv:0RSU2MdZWiYEapwXGzevP9/vc/Sk1MS6a0MnCRQyIs8=,tag:vvngXS2IRzH999yzo4JyFQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.4

File diff suppressed because one or more lines are too long

View file

@ -65,7 +65,7 @@ in {
openFirewall = true; openFirewall = true;
settings = { settings = {
server = { server = {
lookup.default.hostname = "fb04184.mathematik.tu-darmstadt.de"; # Because the DNS PTR of 130.83.2.184 is this and this should be used in SMTP EHLO. hostname = "fb04184.mathematik.tu-darmstadt.de"; # Because the DNS PTR of 130.83.2.184 is this and this should be used in SMTP EHLO.
listener = { listener = {
"smtp" = { "smtp" = {
bind = ["[::]:25"]; bind = ["[::]:25"];
@ -82,7 +82,7 @@ in {
tls.implicit = true; tls.implicit = true;
}; };
"management" = { "management" = {
# Cthulhu forwards requests for http://fb04184.mathematik.tu-darmstadt.de/.well-known/acme-challenge/ http://imap.mathebau.de/.well-known/acme-challenge/ and http://smtp.mathebau.de/.well-known/acme-challenge/ # Cthulhu forwards requests for http://fb04184.mathematik.tu-darmstadt.de/.well-known/acme-challenge/ http://imap.mathebau.de/.well-known/acme-challenge/ and http://smtp.mathebau.de/.well-known/acme-challenge/ and http://mathebau.de/.well-known/acme-challenge/
# for TLS certificate challenge validation # for TLS certificate challenge validation
# whereas the rest of the management interface is not available publically. # whereas the rest of the management interface is not available publically.
# It can be reached via SSH and portforwarding. # It can be reached via SSH and portforwarding.
@ -95,19 +95,28 @@ in {
directory = "https://acme-v02.api.letsencrypt.org/directory"; # This setting is necessary for this block to be activated directory = "https://acme-v02.api.letsencrypt.org/directory"; # This setting is necessary for this block to be activated
challenge = "http-01"; challenge = "http-01";
contact = ["root@mathebau.de"]; contact = ["root@mathebau.de"];
domains = ["fb04184.mathematik.tu-darmstadt.de" "imap.mathebau.de" "smtp.mathebau.de"]; domains = ["fb04184.mathematik.tu-darmstadt.de" "imap.mathebau.de" "smtp.mathebau.de" "mathebau.de"];
default = true; default = true;
}; };
# Reevaluate after DKIM and DMARC deployment # Reevaluate after DKIM and DMARC deployment
spam.header.is-spam = "Dummyheader"; # disable moving to spam which would conflict with forwarding spam.header.is-spam = "Dummyheader"; # disable moving to spam which would conflict with forwarding
auth = { auth = {
# TODO check if HRZ conforms to these standards and we can validate them strictly # TODO check if HRZ and our own VMs conform to these standards and we can validate them strictly
dkim.verify = "relaxed"; dkim.verify = "relaxed";
arc.verify = "relaxed"; arc.verify = "relaxed";
dmarc.verify = "relaxed"; dmarc.verify = "relaxed";
iprev.verify = "relaxed"; iprev.verify = "relaxed";
spf.verify.ehlo = "relaxed"; spf.verify.ehlo = "relaxed";
spf.verify.mail-from = "relaxed"; spf.verify.mail-from = "relaxed";
# Sign *our* outgoing mails with the configured signatures.
dkim.sign = [
{
"if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'";
"then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]";
}
{"else" = false;}
];
}; };
# Forward outgoing mail to HRZ or mail VMs. # Forward outgoing mail to HRZ or mail VMs.
@ -131,36 +140,61 @@ in {
starttls = "optional"; # e.g. Lobon does not offer starttls starttls = "optional"; # e.g. Lobon does not offer starttls
}; };
}; };
remote."hrz" = { remote = {
address = "mailout.hrz.tu-darmstadt.de"; "hrz" = {
port = 25; address = "mailout.hrz.tu-darmstadt.de";
protocol = "smtp"; port = 25;
tls.implicit = false; # Don't assume TLS on this port but use STARTTLS protocol = "smtp";
}; tls.implicit = false; # Don't assume TLS on this port but use STARTTLS
remote."mailman" = { };
address = "lobon.mathebau.de"; # must be created in DNS as a MX record because this field does not accept ip addresses. "mailman" = {
port = 25; address = "lobon.mathebau.de"; # must be created in DNS as a MX record because this field does not accept ip addresses.
protocol = "smtp"; port = 25;
tls.implicit = false; # Don't assume TLS on this port but use STARTTLS protocol = "smtp";
tls.implicit = false; # Don't assume TLS on this port but use STARTTLS
};
}; };
session.rcpt = { session = {
# In order to accept mail that we only forward ehlo.require = [
# without having to generate an account.
# Invalid addresses are filtered by DFN beforehand.
catch-all = true;
relay = [
{ {
"if" = "!is_empty(authenticated_as) || rcpt_domain == 'lists.mathebau.de' || starts_with(remote_ip, '192.168.0.')"; #TODO restrict trust by IP "if" = "starts_with(remote_ip, '192.168.0.')"; #TODO setup vms properly
"then" = true; "then" = false;
} }
{"else" = false;} {"else" = true;}
]; ];
ehlo.reject-non-fqdn = [
{
"if" = "starts_with(remote_ip, '192.168.0.')"; #TODO setup vms properly
"then" = false;
}
{"else" = true;}
];
rcpt = {
# In order to accept mail that we only forward
# without having to generate an account.
# Invalid addresses are filtered by DFN beforehand.
# See also https://stalw.art/docs/smtp/inbound/rcpt/#catch-all-addresses
catch-all = true;
relay = [
{
"if" = "!is_empty(authenticated_as) || rcpt_domain == 'lists.mathebau.de' || starts_with(remote_ip, '192.168.0.')"; #TODO restrict trust by IP
"then" = true;
}
{"else" = false;}
];
# The sieve script only handles the last RCPT TO command (https://stalw.art/docs/sieve/variables).
# Since we want it to run for every recipient, we need to accept them one at a time. :-(
# This setting throws a temporary error for the second RCPT TO command after which the HRZ retries in a new connection.
max-recipients = 1;
};
data.script = "'redirects'";
}; };
# Stalwart gets its configuration from two places: A TOML configuration file that we control in this module # Stalwart gets its configuration from two places: A TOML configuration file that we control in this module
# and from a database that can be configured from web management interface or via Rest API. # and from a database that can be configured from web management interface or via Rest API.
# We here define what comes from the TOML-file and especially add "sieve.trusted.scripts.*" to the default ones # We here define what comes from the TOML-file and especially add "sieve.trusted.*" to the default ones
# because only TOML-based keys may use macros to load files from disk. # because only TOML-based keys may use macros to load files from disk.
# We want this to be able to load our sieve-script for mail forwarding. # We want this to be able to load our sieve-script for mail forwarding.
# See https://stalw.art/docs/configuration/overview/#local-and-database-settings for more details. # See https://stalw.art/docs/configuration/overview/#local-and-database-settings for more details.
@ -181,9 +215,47 @@ in {
"lookup.default.hostname" "lookup.default.hostname"
"certificate.*" "certificate.*"
] # the default ones ] # the default ones
++ ["sieve.trusted.scripts.*"]; #for macros to be able to include our redirection script ++ ["sieve.trusted.*"]; #for macros to be able to include our redirection script
sieve.trusted.scripts.redirects.contents = "%{file:/tmp/virt_aliases}%"; # generated redirect script sieve.trusted = {
session.data.script = "'redirects'"; scripts.redirects.contents = "%{file:/tmp/virt_aliases}%"; # generated redirect script
return-path = "sender"; # set the outgoing MAIL FROM to the original sender as specified in the incoming MAIL FROM.
# If we are the sender, we sign the message with DKIM. Else we leave it alone.
sign = [
{
"if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'";
"then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]";
}
{"else" = false;}
];
limits = {
redirects = 50;
out-messages = 50;
};
};
# See https://stalw.art/docs/smtp/authentication/dkim/sign
# We need two blocks per domain because the domain setting in the blocks does not accept variables like `sender_domain`.
signature = let
signatureTemplate = domain: {
"rsa-${domain}" = {
private-key = "%{file:/run/secrets/dkim_rsa}%";
domain = "${domain}";
selector = "rsa-default";
headers = ["From" "To" "Cc" "Date" "Subject" "Message-ID" "Organization" "MIME-Version" "Content-Type" "In-Reply-To" "References" "List-Id" "User-Agent" "Thread-Topic" "Thread-Index"];
algorithm = "rsa-sha256";
canonicalization = "relaxed/relaxed";
};
"ed25519-${domain}" = {
private-key = "%{file:/run/secrets/dkim_ed25519}%";
domain = "${domain}";
selector = "ed-default";
headers = ["From" "To" "Cc" "Date" "Subject" "Message-ID" "Organization" "MIME-Version" "Content-Type" "In-Reply-To" "References" "List-Id" "User-Agent" "Thread-Topic" "Thread-Index"];
algorithm = "ed25519-sha256";
canonicalization = "relaxed/relaxed";
};
};
in
map signatureTemplate (["lists.mathebau.de"] ++ (map ({domain, ...}: domain) cfg.domains));
authentication.fallback-admin = { authentication.fallback-admin = {
user = "admin"; user = "admin";
@ -229,7 +301,8 @@ in {
echo "process ${domain}" echo "process ${domain}"
# This line gets the available mailboxes from stalwart's Rest API, searches for their addresses and collects them to a file for submission. # This line gets the available mailboxes from stalwart's Rest API, searches for their addresses and collects them to a file for submission.
# The regex searches for alphanumerics combined with some special characters as local paths and the right domain. # The regex searches for alphanumerics combined with some special characters as local paths and the right domain.
${pkgs.curl}/bin/curl -s --header "authorization: Basic $(<${cfg.stalwartAdmin})" http://localhost/api/principal | ${pkgs.gnugrep}/bin/grep -o -e "[A-Za-z0-9.!#\$%&'*+-/=?^_{|}~]*@${domain}" | tee /tmp/addresses # Exclude @domain.tld which is not a valid mail address but used for catch-all accounts.
${pkgs.curl}/bin/curl -s --header "authorization: Basic $(<${cfg.stalwartAdmin})" http://localhost/api/principal | ${pkgs.gnugrep}/bin/grep -o -e "[A-Za-z0-9.!#\$%&'*+-/=?^_{|}~]*@${domain}" | grep -v "@${domain}" | tee /tmp/addresses
# This line searches for available redirects and adds them to the submission file. # This line searches for available redirects and adds them to the submission file.
${pkgs.gnugrep}/bin/grep -o -e "[A-Za-z0-9.!#\$%&'*+-/=?^_{|}~]*@${domain}" /tmp/virt_aliases >> /tmp/addresses # This doesn't catch all RFC conform local parts. Improve if you need. ${pkgs.gnugrep}/bin/grep -o -e "[A-Za-z0-9.!#\$%&'*+-/=?^_{|}~]*@${domain}" /tmp/virt_aliases >> /tmp/addresses # This doesn't catch all RFC conform local parts. Improve if you need.
# Post local-parts to HRZ, see https://www-cgi.hrz.tu-darmstadt.de/mail/index.php?bereich=whitelist_upload # Post local-parts to HRZ, see https://www-cgi.hrz.tu-darmstadt.de/mail/index.php?bereich=whitelist_upload
@ -267,6 +340,7 @@ in {
"stalwart-mail" = { "stalwart-mail" = {
restartTriggers = lib.attrsets.mapAttrsToList (_: aliaslist: aliaslist.sopsFile) config.sops.secrets; # restart if secrets, especially alias files, have changed. restartTriggers = lib.attrsets.mapAttrsToList (_: aliaslist: aliaslist.sopsFile) config.sops.secrets; # restart if secrets, especially alias files, have changed.
serviceConfig.PrivateTmp = lib.mkForce false; # enable access to generated Sieve script serviceConfig.PrivateTmp = lib.mkForce false; # enable access to generated Sieve script
serviceConfig.ProtectSystem = lib.mkForce "full"; # "strict" does not allow writing to /tmp which we need for unpacking the webadmin interface. "full" is less strict.
}; };
"virt-aliases-generator" = { "virt-aliases-generator" = {
description = "Virtual Aliases Generator: Generate a sieve script from the virtual alias file"; description = "Virtual Aliases Generator: Generate a sieve script from the virtual alias file";

View file

@ -32,7 +32,6 @@ in {
config = { config = {
transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"]; transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
local_recipient_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 smtputf8_enable = "no"; # HRZ does not know SMTPUTF8
}; };
relayHost = "mathebau.de"; # Relay to mail vm which relays to HRZ (see https://www.hrz.tu-darmstadt.de/services/it_services/email_infrastruktur/index.de.jsp) relayHost = "mathebau.de"; # Relay to mail vm which relays to HRZ (see https://www.hrz.tu-darmstadt.de/services/it_services/email_infrastruktur/index.de.jsp)
@ -44,7 +43,11 @@ in {
webHosts = [cfg.hostName]; webHosts = [cfg.hostName];
serve.enable = true; # serve.enable = true; #
# Don't include confirmation tokens in reply addresses, because we would need to send them to HRZ otherwise. # Don't include confirmation tokens in reply addresses, because we would need to send them to HRZ otherwise.
settings.mta.verp_confirmations = "no"; settings.mta = {
verp_confirmations = "no";
max_recipients = "1"; # We can only send to one recipient at a time due to how forwarding currently works. See also the mail module.
max_sessions_per_connection = "1";
};
}; };
}; };