nyarlathotep: cleanup after deployment #55
|
@ -88,7 +88,7 @@
|
|||
./patches/sieve-rs.patch
|
||||
];
|
||||
# Replace the string with `lib.fakeHash` after version changes in order to get the new hash value.
|
||||
cargoHash = "sha256-gb2oFlVA/vE6DoWWW8SCFA3l7rtV2RuosPUY+6IcKNM=";
|
||||
cargoHash = "sha256-0U0Z13a2vRxMFnaaHeXBjvYDjKStgqmuDboUVssVMQw=";
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
8
flake.lock
generated
|
@ -9,11 +9,11 @@
|
|||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1740490964,
|
||||
"narHash": "sha256-05mpcJZCX631rNCxJohUu+nhVOlAc3EfcNPBzOFSHMo=",
|
||||
"lastModified": 1742814048,
|
||||
"narHash": "sha256-8BK8oLQcpxTsQQiOrP80pPWirdOIk50ecCZjkUYMLVI=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "c37b6ec8654db4c6e3d79acaeeccb577a9fb66ce",
|
||||
"revCount": 21,
|
||||
"rev": "3570db39fda3627d60fbd4ef9c6326b3de074eb8",
|
||||
"revCount": 23,
|
||||
Gonne marked this conversation as resolved
|
||||
"type": "git",
|
||||
"url": "https://gitea.mathebau.de/fachschaft/alias_to_sieve"
|
||||
},
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
stalwartAdminHash = "$argon2i$v=19$m=4096,t=3,p=1$d0hYOTkzclpzSmFTZUplWnhVeWE$I7q9uB19RWL0oZKaPlMPSlGfFp6FQ/vrx80FFKCsalg";
|
||||
domains = [
|
||||
# lists.mathebau.de is forwarded to another VM and does not need to be listed here.
|
||||
{
|
||||
/*
|
||||
{
|
||||
domain = "matheball.de";
|
||||
allowlistPass = config.sops.secrets."allowlistPass/matheball".path;
|
||||
}
|
||||
*/
|
||||
{
|
||||
domain = "mathebau.de";
|
||||
allowlistPass = config.sops.secrets."allowlistPass/mathebau".path;
|
||||
|
@ -73,6 +75,18 @@
|
|||
group = "stalwart-mail";
|
||||
mode = "0440";
|
||||
};
|
||||
"dkim_rsa" = {
|
||||
sopsFile = ./dkimKeys.secrets.yaml;
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
see below see below
|
||||
owner = "stalwart-mail";
|
||||
group = "stalwart-mail";
|
||||
mode = "0440";
|
||||
};
|
||||
"dkim_ed25519" = {
|
||||
sopsFile = ./dkimKeys.secrets.yaml;
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
see below see below
|
||||
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
|
||||
stalwartAdmin = {
|
||||
sopsFile = ./stalwartAdmin.secrets.yaml;
|
||||
|
|
40
nixos/machines/nyarlathotep/dkimKeys.secrets.yaml
Normal 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
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
/*
|
||||
* Building: We patch our version of stalwart and thus need to built it locally.
|
||||
nerf marked this conversation as resolved
Outdated
nerf
commented
how did this went up from 12 to 20? how did this went up from 12 to 20?
Gonne
commented
I assume version updates from stalwart. I assume version updates from stalwart.
nerf
commented
sigh, no local builds for me anymore (except nixpkgs, starts to cache stalwart) sigh, no local builds for me anymore (except nixpkgs, starts to cache stalwart)
|
||||
* Be aware that this needs some hours, about 12Gb RAM and a few Gb free space in /tmp.
|
||||
* Be aware that this needs some hours, about 20Gb RAM and a few Gb free space in /tmp.
|
||||
* If you only want to deploy configuration changes and no software updates, consider building on the target VM.
|
||||
* It has stalwart in its nix store and does not need to rebuild it.
|
||||
* Forwarding mails: Update the Sops-secrets in the machine directory, rebuild on the VM and deploy.
|
||||
|
@ -65,7 +66,7 @@ in {
|
|||
openFirewall = true;
|
||||
settings = {
|
||||
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 = {
|
||||
"smtp" = {
|
||||
bind = ["[::]:25"];
|
||||
|
@ -82,7 +83,7 @@ in {
|
|||
tls.implicit = true;
|
||||
};
|
||||
"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
|
||||
# whereas the rest of the management interface is not available publically.
|
||||
# It can be reached via SSH and portforwarding.
|
||||
|
@ -95,19 +96,28 @@ in {
|
|||
directory = "https://acme-v02.api.letsencrypt.org/directory"; # This setting is necessary for this block to be activated
|
||||
challenge = "http-01";
|
||||
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;
|
||||
};
|
||||
# Reevaluate after DKIM and DMARC deployment
|
||||
spam.header.is-spam = "Dummyheader"; # disable moving to spam which would conflict with forwarding
|
||||
auth = {
|
||||
nerf marked this conversation as resolved
Outdated
nerf
commented
But Mailman shouldn't sign its mail, right? how do we solve that? But Mailman shouldn't sign its mail, right? how do we solve that?
Gonne
commented
Possibly by moving all submission from our other vms to a separate listener. Possibly by moving all submission from our other vms to a separate listener.
nerf
commented
I open an issue for later I open an issue for later
|
||||
# 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";
|
||||
arc.verify = "relaxed";
|
||||
dmarc.verify = "relaxed";
|
||||
iprev.verify = "relaxed";
|
||||
spf.verify.ehlo = "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.
|
||||
|
@ -131,39 +141,62 @@ in {
|
|||
starttls = "optional"; # e.g. Lobon does not offer starttls
|
||||
};
|
||||
};
|
||||
remote."hrz" = {
|
||||
address = "mailout.hrz.tu-darmstadt.de";
|
||||
port = 25;
|
||||
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.
|
||||
port = 25;
|
||||
protocol = "smtp";
|
||||
tls.implicit = false; # Don't assume TLS on this port but use STARTTLS
|
||||
remote = {
|
||||
"hrz" = {
|
||||
address = "mailout.hrz.tu-darmstadt.de";
|
||||
port = 25;
|
||||
protocol = "smtp";
|
||||
tls.implicit = false; # Don't assume TLS on this port but use STARTTLS
|
||||
};
|
||||
"mailman" = {
|
||||
address = "lobon.mathebau.de"; # must be created in DNS as a MX record because this field does not accept ip addresses.
|
||||
port = 25;
|
||||
protocol = "smtp";
|
||||
tls.implicit = false; # Don't assume TLS on this port but use STARTTLS
|
||||
};
|
||||
};
|
||||
|
||||
session.rcpt = {
|
||||
# In order to accept mail that we only forward
|
||||
# without having to generate an account.
|
||||
# Invalid addresses are filtered by DFN beforehand.
|
||||
catch-all = true;
|
||||
relay = [
|
||||
session = {
|
||||
ehlo.require = [
|
||||
{
|
||||
"if" = "!is_empty(authenticated_as) || rcpt_domain == 'lists.mathebau.de' || starts_with(remote_ip, '192.168.0.')"; #TODO restrict trust by IP
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
the diff is very confusing here, this line should be compared to 182 in green the diff is very confusing here, this line should be compared to 182 in green
|
||||
"then" = true;
|
||||
"if" = "starts_with(remote_ip, '192.168.0.')"; #TODO setup vms properly
|
||||
"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;}
|
||||
];
|
||||
};
|
||||
data.script = "'redirects'";
|
||||
};
|
||||
|
||||
# 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.
|
||||
nerf
commented
Is there still something left in the database that we could move here? Is there still something left in the database that we could move here?
Gonne
commented
The list of domains served by stalwart and the existence of catch-all accounts remains in the database, but I have not found out how do set them from config. The list of domains served by stalwart and the existence of catch-all accounts remains in the database, but I have not found out how do set them from config.
nerf
commented
I think we should move it to the config file, or do we need to dynamically change these? I think we should move it to the config file, or do we need to dynamically change these?
Gonne
commented
Yes, at least while we don't provide mail boxes. But I don't know how. Yes, at least while we don't provide mail boxes. But I don't know how.
nerf
commented
That mailboxes need some state attached to them is clear to me (not necessarily, which mail boxes but user generated sieve scripts for example). Maybe I should open another question in the stalwart discussion thing. That mailboxes need some state attached to them is clear to me (not necessarily, which mail boxes but user generated sieve scripts for example). Maybe I should open another question in the stalwart discussion thing.
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
# Unfortunately, the set of served domains as well as the catch-all accounts are still not configured via this nix module.
|
||||
config.local-keys =
|
||||
[
|
||||
"store.*"
|
||||
|
@ -181,9 +214,47 @@ in {
|
|||
"lookup.default.hostname"
|
||||
"certificate.*"
|
||||
] # the default ones
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
maybe we should move this file from maybe we should move this file from `/tmp` into the `/run` directory as this usually has proper
file access rights set up.
Gonne
commented
There is also Reading https://lwn.net/Articles/436012/ I have no idea whether There is also `JoinsNamespaceOf` for `PrivateTmp` of systemd service units (https://www.man7.org/linux/man-pages/man5/systemd.exec.5.html) but I didn't succeed setting it.
Reading https://lwn.net/Articles/436012/ I have no idea whether `/run` is a better place.
nerf
commented
We don't care about the early boot discussion. So the question is, is it runtime date or temporary data, wherever the boundary between these two is. Putting things in If we already follow Lennart's advice then we also should use So after reading all of this maybe the cleanest option is to get the We don't care about the early boot discussion. So the question is, is it runtime date or temporary data, wherever the boundary between these two is. Putting things in `/tmp` is often a buggy mess as this directory is usually somewhat of a global dumpster fire, where there are no guarantees that this file does not already exist with some important information for some other process (though unlikely). `PrivateTmp` would save us here, but even the documentation says that one should not rely on this (and we would need to get it to work).
If we already follow Lennart's advice then we also should use `mkstemp` to generate files in `/tmp` which will
be very painful in a nix setting (as paths and filenames will only be available at runtime). Lennart also seems to think that `/run` is primarily for communication primitives (is this one?).
See [his blogpost](https://0pointer.net/blog/projects/tmp.html).
So after reading all of this maybe the cleanest option is to get the `JoinNamespaceOf` option to work?
Gonne
commented
I got the private I got the private `/tmp` with `JoinsNamespaceOf` working.
|
||||
++ ["sieve.trusted.scripts.*"]; #for macros to be able to include our redirection script
|
||||
sieve.trusted.scripts.redirects.contents = "%{file:/tmp/virt_aliases}%"; # generated redirect script
|
||||
session.data.script = "'redirects'";
|
||||
++ ["sieve.trusted.*"]; #for macros to be able to include our redirection script
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
the the `trusted` part is to much, also see the comment at `from-name` below
|
||||
sieve.trusted = {
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
I couldn't figure out what I couldn't figure out what `from-name` or `from-addr` actually do. Reading the documentation I believe combined they
set the default value for the `From:` header of a generated mail. But I couldn't verify this in tests.
Maybe it does something different that has to do with the `MAIL FROM:` see comment below
nerf marked this conversation as resolved
nerf
commented
where did the where did the `/tmp` folder discussion disappeared to?
nerf
commented
ahh it got marked outdated ahh it got marked outdated
|
||||
scripts.redirects.contents = "%{file:/tmp/virt_aliases}%"; # generated redirect script
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
This seems to do what we want, even though the documentation reads like it sets the This seems to do what we want, even though the documentation reads like it sets the `Return-Path:` header. But it seems to set the reverse path (which is the argument to the `MAIL FROM:` smtp command). Maybe it does both?
nerf
commented
This parameter seems to control the This parameter seems to control the `MAIL FROM:` and with this all the headers we want to set.
The documentation reads to me as if it sets the `Return-Path:` header. I'm unsure if it actually does it.
|
||||
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 = 500;
|
||||
out-messages = 500;
|
||||
};
|
||||
};
|
||||
# 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}%";
|
||||
Gonne marked this conversation as resolved
nerf
commented
I will just trust you on the header selection I will just trust you on the header selection
|
||||
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"]; # default from https://stalw.art/docs/smtp/authentication/dkim/sign#signatures
|
||||
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 = {
|
||||
user = "admin";
|
||||
|
@ -229,9 +300,10 @@ in {
|
|||
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.
|
||||
# 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
|
||||
Gonne marked this conversation as resolved
nerf
commented
The HRZ doesn't allow The HRZ doesn't allow `'` either so we don't loose anything (see the mails from the cert team, or read
our discussion in chat if you want to see the world burn)
|
||||
# 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.
|
||||
Gonne marked this conversation as resolved
nerf
commented
See above. This parses a sieve script! That includes See above. This parses a sieve script! That includes `'` in its syntax so this would break anyway if we allowed `'` in E-Mail addresses. Maybe we should parse the alias file instead. That has its own problems though.
We can discuss this in a separate issue.
|
||||
# Post local-parts to HRZ, see https://www-cgi.hrz.tu-darmstadt.de/mail/index.php?bereich=whitelist_upload
|
||||
${pkgs.curl}/bin/curl -s https://www-cgi.hrz.tu-darmstadt.de/mail/whitelist-update.php -F emaildomain=${domain} -F password=$(cat ${allowlistPass}) -F emailliste=@/tmp/addresses -F meldungen=voll
|
||||
# Cleanup submission file
|
||||
|
@ -239,12 +311,15 @@ in {
|
|||
'';
|
||||
in
|
||||
lib.strings.concatStringsSep "" (map scriptTemplate cfg.domains);
|
||||
|
||||
unitConfig.JoinsNamespaceOf = "stalwart-mail.service"; # allow access to sieve script
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "stalwart-mail";
|
||||
NoNewPrivileges = true;
|
||||
# See https://www.man7.org/linux/man-pages/man5/systemd.exec.5.html
|
||||
PrivateTmp = false; # allow access to sieve script
|
||||
PrivateTmp = true;
|
||||
ProtectHome = true;
|
||||
ReadOnlyPaths = "/";
|
||||
ReadWritePaths = "/tmp";
|
||||
|
@ -266,35 +341,8 @@ in {
|
|||
# This service is defined by the nixpkgs stalwart module and we only modify it.
|
||||
"stalwart-mail" = {
|
||||
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
|
||||
};
|
||||
"virt-aliases-generator" = {
|
||||
description = "Virtual Aliases Generator: Generate a sieve script from the virtual alias file";
|
||||
script = lib.strings.concatStringsSep "" (["${pkgs.alias-to-sieve}/bin/alias_to_sieve "] ++ map (x: "${x.virt_aliases} ${x.domain} ") cfg.domains ++ ["> /tmp/virt_aliases"]);
|
||||
wantedBy = ["stalwart-mail.service"]; # Rerun on stalwart restart because forwardings may have changed.
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "stalwart-mail";
|
||||
NoNewPrivileges = true;
|
||||
# See https://www.man7.org/linux/man-pages/man5/systemd.exec.5.html
|
||||
PrivateTmp = false;
|
||||
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;
|
||||
};
|
||||
#Generate a sieve script from the virtual alias file
|
||||
Gonne marked this conversation as resolved
nerf
commented
smart smart
|
||||
preStart = lib.strings.concatStringsSep "" (["${pkgs.alias-to-sieve}/bin/alias_to_sieve "] ++ map (x: "${x.virt_aliases} ${x.domain} ") cfg.domains ++ ["> /tmp/virt_aliases"]);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -32,8 +32,6 @@ in {
|
|||
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
|
||||
};
|
||||
Gonne marked this conversation as resolved
nerf
commented
but we talk to us and not hrz, right? but we talk to us and not hrz, right?
Gonne
commented
Does the commit message explain your question? Does the [commit message](https://gitea.mathebau.de/Fachschaft/nixConfig/pulls/55/commits/01951eadadcc19eb88b75e7341c5a40cd113c94c) explain your question?
nerf
commented
no, my comment was attached to the no, my comment was attached to the `smtputf8_enable` line not the deleted one
Gonne
commented
Ah, right. Let's test that. Ah, right. Let's test that.
Gonne
commented
Works Works
|
||||
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)
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@ index be36759b..b4316639 100644
|
|||
version = "0.6.0"
|
||||
-source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
-checksum = "15ac54053752c25a0e545dd1953de716abcc80b12cfe0b6c2f2c1c73759d4f45"
|
||||
+source = "git+https://gitea.mathebau.de/fachschaft/sieve-rs.git#71324550504c0f84fe3e814d05cbe22f90a3b228"
|
||||
+source = "git+https://github.com/stalwartlabs/sieve.git#56450c6ccdf76f1de95931db24896599159efc53"
|
||||
Gonne marked this conversation as resolved
Outdated
nerf
commented
YaY, hopefully this can disappear soon YaY, hopefully this can disappear soon
|
||||
dependencies = [
|
||||
"ahash 0.8.11",
|
||||
"bincode",
|
||||
|
@ -23,5 +23,5 @@ index f055474f..2b64c9ac 100644
|
|||
+
|
||||
+
|
||||
+[patch.crates-io]
|
||||
+sieve-rs = { git = 'https://gitea.mathebau.de/fachschaft/sieve-rs.git' }
|
||||
+sieve-rs = { git = 'https://github.com/stalwartlabs/sieve.git' }
|
||||
|
||||
|
|
at some point someone should review that script...