nyarlathotep: cleanup after deployment #55

Merged
Gonne merged 22 commits from Gonne/nixConfig:nyarlathotep into main 2025-03-24 19:38:06 +00:00
3 changed files with 102 additions and 0 deletions
Showing only changes of commit 10ca56c064 - Show all commits

View file

@ -75,6 +75,18 @@
group = "stalwart-mail";
mode = "0440";
};
"dkim_rsa" = {
sopsFile = ./dkim.keys.yaml;
Gonne marked this conversation as resolved Outdated

see below

see below
owner = "stalwart-mail";
group = "stalwart-mail";
mode = "0440";
};
"dkim_ed25519" = {
sopsFile = ./dkim.keys.yaml;
Gonne marked this conversation as resolved Outdated

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;

View file

@ -0,0 +1,40 @@
dkim_rsa: ENC[AES256_GCM,data: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,iv:QbZVXp5FQhmYZvXxXNxWKrNm5GqM+2P3a5pPk499mlc=,tag:F+KNoPRnoLLhOpEj6Czj6Q==,type:str]
Gonne marked this conversation as resolved Outdated

can this file be called <something>.secrets.yaml?

can this file be called `<something>.secrets.yaml`?
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

View file

@ -108,6 +108,15 @@ in {
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.
@ -202,12 +211,53 @@ in {
sieve.trusted.from-addr = "sender"; # set the from-address to the original sender as specified in the MAIL FROM.
sieve.trusted.from-name = "sender";
sieve.trusted.return-path = "sender";
# If we are the sender, we sign the message with DKIM. Else we leave it alone.
sieve.trusted.sign = [
{
Gonne marked this conversation as resolved Outdated

maybe we should move this file from /tmp into the /run directory as this usually has proper
file access rights set up.

maybe we should move this file from `/tmp` into the `/run` directory as this usually has proper file access rights set up.

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.

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.

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.

So after reading all of this maybe the cleanest option is to get the JoinNamespaceOf option to work?

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?

I got the private /tmp with JoinsNamespaceOf working.

I got the private `/tmp` with `JoinsNamespaceOf` working.
"if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'";
Gonne marked this conversation as resolved Outdated

the trusted part is to much, also see the comment at from-name below

the `trusted` part is to much, also see the comment at `from-name` below
"then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]";
Gonne marked this conversation as resolved Outdated

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

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

where did the /tmp folder discussion disappeared to?

where did the `/tmp` folder discussion disappeared to?

ahh it got marked outdated

ahh it got marked outdated
}
Gonne marked this conversation as resolved Outdated

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?

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?

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.

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.
{"else" = false;}
];
sieve.trusted.limits = {
redirects = 50;
out-messages = 50;
};
session.data.script = "'redirects'";
# 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}" = {
Gonne marked this conversation as resolved

I will just trust you on the header selection

I will just trust you on the header selection
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));
# Sign *our* outgoing mails with the configured signatures.
auth.dkim.sign = [
{
"if" = "is_local_domain('', sender_domain) || sender_domain == 'lists.mathebau.de'";
"then" = "['rsa-' + sender_domain, 'ed25519-' + sender_domain]";
}
{"else" = false;}
];
authentication.fallback-admin = {
user = "admin";
# see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH