From 882a8ea189c55b11792939670550a49aea383ba4 Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Feb 2025 14:44:52 +0100 Subject: [PATCH 01/10] Add our own package to inputs that converts an alias file to a sieve script. Remove the simple nixos mailserver dependency thet we won't use. --- flake.lock | 210 ++++++++++++++++++++++++++++------------------------- flake.nix | 11 +-- 2 files changed, 117 insertions(+), 104 deletions(-) diff --git a/flake.lock b/flake.lock index dc1839f..ab4a759 100644 --- a/flake.lock +++ b/flake.lock @@ -1,19 +1,25 @@ { "nodes": { - "blobs": { - "flake": false, + "alias-to-sieve": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": [ + "nixpkgs" + ], + "rust-overlay": "rust-overlay" + }, "locked": { - "lastModified": 1604995301, - "narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=", - "owner": "simple-nixos-mailserver", - "repo": "blobs", - "rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265", - "type": "gitlab" + "lastModified": 1740490964, + "narHash": "sha256-05mpcJZCX631rNCxJohUu+nhVOlAc3EfcNPBzOFSHMo=", + "ref": "refs/heads/main", + "rev": "c37b6ec8654db4c6e3d79acaeeccb577a9fb66ce", + "revCount": 21, + "type": "git", + "url": "https://gitea.mathebau.de/fachschaft/alias_to_sieve" }, "original": { - "owner": "simple-nixos-mailserver", - "repo": "blobs", - "type": "gitlab" + "type": "git", + "url": "https://gitea.mathebau.de/fachschaft/alias_to_sieve" } }, "flake-parts": { @@ -21,11 +27,29 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1727826117, - "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=", + "lastModified": 1738453229, + "narHash": "sha256-7H9XgNiGLKN1G1CgRh0vUL4AheZSYzPm+zmZ7vxbJdo=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1", + "rev": "32ea77a06711b758da0ad9bd6a844c5740a87abd", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, + "locked": { + "lastModified": 1738453229, + "narHash": "sha256-7H9XgNiGLKN1G1CgRh0vUL4AheZSYzPm+zmZ7vxbJdo=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "32ea77a06711b758da0ad9bd6a844c5740a87abd", "type": "github" }, "original": { @@ -35,11 +59,11 @@ }, "impermanence": { "locked": { - "lastModified": 1727649413, - "narHash": "sha256-FA53of86DjFdeQzRDVtvgWF9o52rWK70VHGx0Y8fElQ=", + "lastModified": 1737831083, + "narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=", "owner": "nix-community", "repo": "impermanence", - "rev": "d0b38e550039a72aff896ee65b0918e975e6d48e", + "rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170", "type": "github" }, "original": { @@ -48,34 +72,53 @@ "type": "github" } }, - "nixos-mailserver": { - "inputs": { - "blobs": "blobs", - "flake-compat": [], - "nixpkgs": [], - "nixpkgs-24_05": "nixpkgs-24_05" - }, - "locked": { - "lastModified": 1722877200, - "narHash": "sha256-qgKDNJXs+od+1UbRy62uk7dYal3h98I4WojfIqMoGcg=", - "ref": "refs/heads/master", - "rev": "af7d3bf5daeba3fc28089b015c0dd43f06b176f2", - "revCount": 593, - "type": "git", - "url": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git" - }, - "original": { - "type": "git", - "url": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git" - } - }, "nixpkgs": { "locked": { - "lastModified": 1728492678, - "narHash": "sha256-9UTxR8eukdg+XZeHgxW5hQA9fIKHsKCdOIUycTryeVw=", + "lastModified": 1736320768, + "narHash": "sha256-nIYdTAiKIGnFNugbomgBJR+Xv5F1ZQU+HfaBqJKroC0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5633bcff0c6162b9e4b5f1264264611e950c8ec7", + "rev": "4bc9c909d9ac828a039f288cf872d16d38185db8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1738452942, + "narHash": "sha256-vJzFZGaCpnmo7I6i416HaBLpC+hvcURh/BQwROcGIp8=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz" + } + }, + "nixpkgs-lib_2": { + "locked": { + "lastModified": 1738452942, + "narHash": "sha256-vJzFZGaCpnmo7I6i416HaBLpC+hvcURh/BQwROcGIp8=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1740367490, + "narHash": "sha256-WGaHVAjcrv+Cun7zPlI41SerRtfknGQap281+AakSAw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0196c0175e9191c474c26ab5548db27ef5d34b05", "type": "github" }, "original": { @@ -85,62 +128,18 @@ "type": "github" } }, - "nixpkgs-24_05": { - "locked": { - "lastModified": 1717144377, - "narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "805a384895c696f802a9bf5bf4720f37385df547", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "ref": "nixos-24.05", - "type": "indirect" - } - }, - "nixpkgs-lib": { - "locked": { - "lastModified": 1727825735, - "narHash": "sha256-0xHYkMkeLVQAMa7gvkddbPqpxph+hDzdu1XdGPJR+Os=", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz" - } - }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1728156290, - "narHash": "sha256-uogSvuAp+1BYtdu6UWuObjHqSbBohpyARXDWqgI12Ss=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "17ae88b569bb15590549ff478bab6494dde4a907", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "release-24.05", - "repo": "nixpkgs", - "type": "github" - } - }, "pre-commit-hooks": { "inputs": { "flake-compat": [], "gitignore": [], - "nixpkgs": [], - "nixpkgs-stable": [] + "nixpkgs": [] }, "locked": { - "lastModified": 1728727368, - "narHash": "sha256-7FMyNISP7K6XDSIt1NJxkXZnEdV3HZUXvFoBaJ/qdOg=", + "lastModified": 1737465171, + "narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "eb74e0be24a11a1531b5b8659535580554d30b28", + "rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17", "type": "github" }, "original": { @@ -151,27 +150,44 @@ }, "root": { "inputs": { - "flake-parts": "flake-parts", + "alias-to-sieve": "alias-to-sieve", + "flake-parts": "flake-parts_2", "impermanence": "impermanence", - "nixos-mailserver": "nixos-mailserver", - "nixpkgs": "nixpkgs", + "nixpkgs": "nixpkgs_2", "pre-commit-hooks": "pre-commit-hooks", "sops-nix": "sops-nix" } }, + "rust-overlay": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1740450604, + "narHash": "sha256-T/lqASXzCzp5lJISCUw+qwfRmImVUnhKgAhn8ymRClI=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "5961ca311c85c31fc5f51925b4356899eed36221", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, "sops-nix": { "inputs": { "nixpkgs": [ "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" + ] }, "locked": { - "lastModified": 1728345710, - "narHash": "sha256-lpunY1+bf90ts+sA2/FgxVNIegPDKCpEoWwOPu4ITTQ=", + "lastModified": 1739262228, + "narHash": "sha256-7JAGezJ0Dn5qIyA2+T4Dt/xQgAbhCglh6lzCekTVMeU=", "owner": "Mic92", "repo": "sops-nix", - "rev": "06535d0e3d0201e6a8080dd32dbfde339b94f01b", + "rev": "07af005bb7d60c7f118d9d9f5530485da5d1e975", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b4b5593..4a6baaf 100644 --- a/flake.nix +++ b/flake.nix @@ -2,14 +2,11 @@ description = "Description for the project"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - nixos-mailserver = { - url = "git+https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git"; - inputs = { - flake-compat.follows = ""; - nixpkgs.follows = ""; - }; + alias-to-sieve = { + url = "git+https://gitea.mathebau.de/fachschaft/alias_to_sieve"; + inputs.nixpkgs.follows = "nixpkgs"; }; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; sops-nix = { url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; From 2aa93c98f5a195feab862cdca1c8e42786bda6a4 Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Feb 2025 15:10:15 +0100 Subject: [PATCH 02/10] Add basic machine config for kaalut, a new mail vm --- .sops.yaml | 7 +++ nixos/machines/kaalut/backupKey.yaml | 48 +++++++++++++++++++ nixos/machines/kaalut/configuration.nix | 22 +++++++++ .../kaalut/hardware-configuration.nix | 30 ++++++++++++ nixos/modules/borgbackup.nix | 7 +++ 5 files changed, 114 insertions(+) create mode 100644 nixos/machines/kaalut/backupKey.yaml create mode 100644 nixos/machines/kaalut/configuration.nix create mode 100644 nixos/machines/kaalut/hardware-configuration.nix diff --git a/.sops.yaml b/.sops.yaml index bc5cfc6..7967e56 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -5,6 +5,7 @@ keys: - &nyarlathotep age1s99d0vlj5qlm287n98jratql5fypvjrxxal0k5jl2aw9dcc8kyvqw5yyt4 - &bragi age1lqvgpmlemyg9095ujck64u59ma29656zs7a4yxgz4s6u5cld2ccss69jwe - &lobon age12nz7dtc0m5wasxm4r9crtkgwnzvauyfp0xh0n8z8jld0arn9ea9qe0agvn + - &kaalut age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a creation_rules: - path_regex: nixos/machines/nyarlathotep/.* @@ -25,6 +26,12 @@ creation_rules: - *nerf - *gonne - *lobon + - path_regex: nixos/machines/kaalut/.* + key_groups: + - age: + - *nerf + - *gonne + - *kaalut # this is the catchall clause if nothing above machtes. Encrypt to users but not # to machines - key_groups: diff --git a/nixos/machines/kaalut/backupKey.yaml b/nixos/machines/kaalut/backupKey.yaml new file mode 100644 index 0000000..3727470 --- /dev/null +++ b/nixos/machines/kaalut/backupKey.yaml @@ -0,0 +1,48 @@ +backupKey: ENC[AES256_GCM,data:4ZN6V9ihkUEyz1pih87Xi2OPvfRdx+TY9nvw3CHG0vUeWavxLD8MuzEVL2xlI3A8X1F+KgQ40noaVL5qcq+SENGSdhHJaxzxc/oGN++k5C3b0FuyspI15XqIPjXWu/ApRpPktSrr57dbiQfAUtcg8E1R0Wn3uJxdFnVj9iQjnMzy0qezZbp+8UpEuFUqi4ZsQddltf12HxAGyHcedddUhEdE7bCZcj5/zSiEvXpyp1Ta9naVWnD6KkkVcB3zou7vCjwFKHf+qKUFPC70OCUomXF6scjb47iGexLNQIwaRe3+BmD4X0WFB2EM7DedenKh7SvRdYh25yYR2SzfSb71Aj5JwVi9TuuyhJvlXsDcwERPkq2R7VgbvVqYVVfjbtDlERp11xZzuEX85Pmvfh8rEkVCNfW2pqm5F+rmvFQ4KpwwMvnVEKXvasOECiGq16sp2Zk/e5cOIX+IlqgcY/GW6hBKs8CROxi0w4qCstfyFB0KxS0dGlarvhDJ2i5Rkx9RRP91yU/8QzqNRY0ixJpB,iv:ReA4k7S4F8NBE0VBCy9ks6YZJiubdUdP/AhEwc0kHaA=,tag:zagxPVYKQhf/tdK3tJFa2A==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjSGRWTEd6TVAzWjk2cHRn + Wkg1NlhxNXVYVXpDdnFiWmJSejE4SDhuZURFCklQWUFiaHZvbkZ1T21aZHNuME5x + NXN1ZHBoQzU4RUc3Y3lJVnMyRjluckUKLS0tIDRRVTdwcVplUFJmajkvWEZ0UlFJ + ZWpXTzI2NVhldnRrYnFybzErZXBQaVkK4hi/aksGcLlELTUPjJPoVR518z+Twt6l + RCFOnLsmsRu8/pigphbGMjOxYPsEsEpclU2vAobL1H3nPE/uKt4t/Q== + -----END AGE ENCRYPTED FILE----- + - recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSByN3BGN2IvdkhkcENJZEJD + OStNdWw2Q25hSXZHcDczRnRUd3h1ZGhDODA0Clo4cktoL2FUYmlkY2JJZFp6bkVS + WHdFeDZxSEU3a0RBMmI3cGk2N05hb0UKLS0tIDdDOElueDhPR1pxVEdmaTg3RVgz + eHVGak9sRkEydjdiam5QWHNpRG1hTnMKWqSIdNP6yMw6xoPqmK9Lss2Ztb72T7+l + bK4VYCnyuuQ24AhlVHLZdbRbk4Rvp2V7bCTWwTNamrRMJieLMZwt8g== + -----END AGE ENCRYPTED FILE----- + - recipient: age1dhzugelagj6vge5jjxwwn0522ngf7fhxn04sxy2tm8557rtme5tstprwnj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlNmtkRGlCTFYvdEJWZEhv + bXY5Z3ZibjRjQTV2c3R4OE1JSXBxeTN4Z0Y0CmU3aUVNN0NEeGgwOExvOFRDc2Jl + YlQ3dDJtQ1hvSHNFSzNyNGJMYklrRzAKLS0tIFB0Q21WU0hkOWxLajhRdlZaMGFN + OTYzMW9aMERGTVdXUnBZM0hxSzBWYTAK0k+pyltKHe6FfdYPqAQcax/u5r1JKP4q + C8qXIuAXY9FI4mV8xyuRZEIDr5A2y3hCCilieGr1KGkAwBZyZhQy4w== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxZStjM25VQnQ3Y2d3Skxs + K3k2NU5yeXUwT1F6SmNUVGpPVDUxeHdKZ0JJClFYcUIzazZ2R1BIbElWS3hCeHFK + cjFRY1pIL29YUktiR0t5bm5wT1JzZ1EKLS0tIFRPYi9veS9RZHhIRHNyZjZvL3JY + RTk1RE9GRitTMFFoUUQwOWtiTWRwMjQKkoA2wiTAholKq7ngDE/OWZKHjFbDg7WZ + efax0e0/riC3EEyvR3kIfjCenc2GBvVoaMgzD3Dra9Gz+3JpM11/+w== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-11-23T09:05:51Z" + mac: ENC[AES256_GCM,data:yYBzhvg1g9GQk+Os6wkzNE3FyXIp7N2AnxuzPfexoA0aWXhYD2zQ7ylTiRGZLkbSODezXT0pD9sjYFN8yTXuY5HMIlCYSCPQGIUblZKRqB0EES3JyhQ4bULCMO7pXrsIuAICzoWM9vn7RQ9cVbL3N2rocYiSURhsGuMA47d3QFk=,iv:xS/am6/hLq2sQGB+vMzS6ZqmFr1ZOIDj1l6b56nVMhE=,tag:erNYX6U4/uSlSUBpN7kKiA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.1 diff --git a/nixos/machines/kaalut/configuration.nix b/nixos/machines/kaalut/configuration.nix new file mode 100644 index 0000000..115091d --- /dev/null +++ b/nixos/machines/kaalut/configuration.nix @@ -0,0 +1,22 @@ +{config, ...}: { + imports = [ + ./hardware-configuration.nix + ../../roles + ../../roles/vm.nix + ../../modules/vmNetwork.nix + ]; + + # System configuration here + networking.hostName = "kaalut"; + vmNetwork.ipv4 = "192.168.0.17"; + system.stateVersion = "24.05"; + + sops.secrets = { + backupKey = { + sopsFile = ./backupKey.yaml; + owner = "root"; + group = "root"; + mode = "0400"; + }; + }; +} diff --git a/nixos/machines/kaalut/hardware-configuration.nix b/nixos/machines/kaalut/hardware-configuration.nix new file mode 100644 index 0000000..ce7112d --- /dev/null +++ b/nixos/machines/kaalut/hardware-configuration.nix @@ -0,0 +1,30 @@ +{ + lib, + pkgs, + ... +}: { + imports = []; + + fileSystems."/" = { + device = "root"; + fsType = "tmpfs"; + options = ["size=1G" "mode=755"]; + }; + fileSystems."/persist" = { + device = "/dev/disk/by-label/nixos"; + fsType = "btrfs"; + options = ["subvol=persist"]; + neededForBoot = true; + }; + fileSystems."/boot" = { + device = "/dev/disk/by-label/boot"; + fsType = "ext4"; + }; + fileSystems."/nix" = { + device = "/dev/disk/by-label/nixos"; + fsType = "btrfs"; + options = ["subvol=nix"]; + }; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/nixos/modules/borgbackup.nix b/nixos/modules/borgbackup.nix index b552c8b..9889238 100644 --- a/nixos/modules/borgbackup.nix +++ b/nixos/modules/borgbackup.nix @@ -76,6 +76,13 @@ in { path = "/var/lib/backups/ithaqua"; allowSubRepos = true; }; + kaalut = { + authorizedKeysAppendOnly = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFcAJkEXcvrDEQf1zRhBXLe1CSHOTooM3qy0KMfS9oug Kaalut Backup" + ]; + path = "/var/lib/backups/kaalut"; + allowSubRepos = true; + }; lobon = { authorizedKeysAppendOnly = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICEptjf1UWRlo6DG9alAIRwkSDUAVHwDKkHC6/DeYKzi Lobon Backup" From d7b8f935cd03748f016e7e08e8397843dc04d049 Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Feb 2025 15:32:36 +0100 Subject: [PATCH 03/10] Add basic mailserver configuration --- nixos/machines/kaalut/configuration.nix | 7 + nixos/modules/mail.nix | 171 ++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 nixos/modules/mail.nix diff --git a/nixos/machines/kaalut/configuration.nix b/nixos/machines/kaalut/configuration.nix index 115091d..ac9a08b 100644 --- a/nixos/machines/kaalut/configuration.nix +++ b/nixos/machines/kaalut/configuration.nix @@ -1,12 +1,19 @@ {config, ...}: { imports = [ ./hardware-configuration.nix + ../../modules/mail.nix ../../roles ../../roles/vm.nix ../../modules/vmNetwork.nix ]; # System configuration here + services.mathebau-mail = { + enable = true; + # see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH + stalwartAdminHash = "$argon2i$v=19$m=4096,t=3,p=1$d0hYOTkzclpzSmFTZUplWnhVeWE$I7q9uB19RWL0oZKaPlMPSlGfFp6FQ/vrx80FFKCsalg"; + }; + networking.hostName = "kaalut"; vmNetwork.ipv4 = "192.168.0.17"; system.stateVersion = "24.05"; diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix new file mode 100644 index 0000000..d4fa331 --- /dev/null +++ b/nixos/modules/mail.nix @@ -0,0 +1,171 @@ +/* +* Using the web admin interface: Set your SSH to do portforwarding of some local port to port 80 of the VM and +* and use your personal admin account or create one using the fallback admin password. +* Create users with mail boxes: Go to the admin interface and create them. +* Stalwart mailserver docs can be found at https://stalw.art/docs +* DNS-Records: Collect the right DNS entries from the management interface and copy them to the DNS hoster. Caution: +* Not all entries are applicable since we relay via HRZ. +*/ +{ + config, + lib, + ... +}: let + inherit + (lib) + mkIf + mkEnableOption + mkOption + ; + inherit (lib.types) listOf strMatching str path; + cfg = config.services.mathebau-mail; +in { + options.services.mathebau-mail = { + enable = mkEnableOption "mathebau mail service"; + stalwartAdminHash = mkOption { + type = str; + description = "String containing the hashed fallback admin password"; + }; + }; + + config = mkIf cfg.enable { + services = { + stalwart-mail = { + enable = true; + 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. + listener = { + "smtp" = { + bind = ["[::]:25"]; + protocol = "smtp"; + }; + "submissions" = { + bind = ["[::]:465"]; + protocol = "smtp"; + tls.implicit = true; + }; + "imaptls" = { + bind = ["[::]:993"]; + protocol = "imap"; + 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/ + # for TLS certificate challenge validation + # whereas the rest of the management interface is not available publically. + # It can be reached via SSH and portforwarding. + bind = ["[::]:80"]; + protocol = "http"; + }; + }; + }; + acme.letsencrypt = { + 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"]; + default = true; + }; + spam.header.is-spam = "Dummyheader"; # disable moving to spam which would conflict with forwarding + auth = { + # TODO check if HRZ conforms 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"; + }; + + # Forward outgoing mail to HRZ or mail VMs. + # see https://stalw.art/docs/smtp/outbound/routing/ relay host example + queue.outbound = { + next-hop = [ + { + "if" = "rcpt_domain = 'lists.mathebau.de'"; + "then" = "'mailman'"; + } + { + "if" = "is_local_domain('', rcpt_domain)"; + "then" = "'local'"; + } + {"else" = "'hrz'";} + ]; + tls = { + # we only talk to HRZ and our own VMs anyway + mta-sts = "disable"; + dane = "disable"; + 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 + }; + + 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 = [ + { + "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;} + ]; + }; + + authentication.fallback-admin = { + user = "admin"; + # see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH + secret = cfg.stalwartAdminHash; + }; + store = { + # structured data in SQLite, blobs on filesystem + db.type = "sqlite"; + db.path = "/var/lib/stalwart-mail/data/index.sqlite3"; + fs.type = "fs"; + fs.path = "/var/lib/stalwart-mail/data/blobs"; + }; + }; + }; + }; + environment.persistence.${config.impermanence.name} = { + directories = [ + "/var/lib/stalwart-mail" + ]; + files = ["/root/.ssh/known_hosts"]; # for the backup server bragi + }; + + # Backups + services.borgbackup.jobs.mail = { + paths = [ + "/var/lib/stalwart-mail/data" + ]; + 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:kaluut"; # TODO for https://gitea.mathebau.de/Fachschaft/nixConfig/issues/33 + startAt = "daily"; + user = "root"; + group = "root"; + }; + }; +} From 7796b7aa00f2c275b45921879a037fdb33003b2e Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Feb 2025 16:09:44 +0100 Subject: [PATCH 04/10] Add mail forwarding based on alias files --- flake-module.nix | 6 ++ nixos/machines/kaalut/configuration.nix | 41 ++++++++++ nixos/machines/kaalut/koma.aliases.yaml | 48 +++++++++++ nixos/machines/kaalut/mathebau.aliases.yaml | 48 +++++++++++ nixos/machines/kaalut/mathechor.aliases.yaml | 48 +++++++++++ nixos/modules/mail.nix | 84 ++++++++++++++++++++ 6 files changed, 275 insertions(+) create mode 100644 nixos/machines/kaalut/koma.aliases.yaml create mode 100644 nixos/machines/kaalut/mathebau.aliases.yaml create mode 100644 nixos/machines/kaalut/mathechor.aliases.yaml diff --git a/flake-module.nix b/flake-module.nix index c30fff4..7bc32ef 100644 --- a/flake-module.nix +++ b/flake-module.nix @@ -53,6 +53,12 @@ _module.args.pkgs = import inputs.nixpkgs { inherit system; config.permittedInsecurePackages = ["jitsi-meet-1.0.8043"]; + + overlays = [ + (_: _: { + alias-to-sieve = inputs.alias-to-sieve.packages.x86_64-linux.default; # add custom package to convert alias files to sieve scripts on the stalwart machine + }) + ]; }; }; diff --git a/nixos/machines/kaalut/configuration.nix b/nixos/machines/kaalut/configuration.nix index ac9a08b..1b84e50 100644 --- a/nixos/machines/kaalut/configuration.nix +++ b/nixos/machines/kaalut/configuration.nix @@ -12,6 +12,28 @@ enable = true; # see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH 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; + virt_aliases = config.sops.secrets."mathebau.aliases".path; + } + { + domain = "mathechor.de"; + allowlistPass = config.sops.secrets."allowlistPass/mathechor".path; + virt_aliases = config.sops.secrets."mathechor.aliases".path; + } + { + domain = "koma89.tu-darmstadt.de"; + allowlistPass = config.sops.secrets."allowlistPass/koma".path; + virt_aliases = config.sops.secrets."koma.aliases".path; + } + ]; }; networking.hostName = "kaalut"; @@ -19,6 +41,25 @@ system.stateVersion = "24.05"; sops.secrets = { + # Virtual alias file + "mathebau.aliases" = { + sopsFile = ./mathebau.aliases.yaml; + owner = "stalwart-mail"; + group = "stalwart-mail"; + mode = "0440"; + }; + "mathechor.aliases" = { + sopsFile = ./mathechor.aliases.yaml; + owner = "stalwart-mail"; + group = "stalwart-mail"; + mode = "0440"; + }; + "koma.aliases" = { + sopsFile = ./koma.aliases.yaml; + owner = "stalwart-mail"; + group = "stalwart-mail"; + mode = "0440"; + }; backupKey = { sopsFile = ./backupKey.yaml; owner = "root"; diff --git a/nixos/machines/kaalut/koma.aliases.yaml b/nixos/machines/kaalut/koma.aliases.yaml new file mode 100644 index 0000000..bd3dd9d --- /dev/null +++ b/nixos/machines/kaalut/koma.aliases.yaml @@ -0,0 +1,48 @@ +koma.aliases: ENC[AES256_GCM,data:r9dJzjUrv9BBr6emtHuIm71OamwTQdxdAbWuh62ZPG/tbvg8YimMvUno1WXn6EXn+0q2Gf+r4UiB6RJLD62D+JU+lEAKg9LKfX+578M4eCIbwRqkHWQYAtT/V3nB8L7/dqcvdatF90+50w==,iv:SL13OY8XUNdVBkZlKBfqwzT5LTtZcykyGIK+nHHOa10=,tag:Yyu2/ZqLotmFD+cMwtXYlA==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBS283ZTdKVTVLaDRDV1N5 + SGhJQjJWdXJzc1l5OWtCWVdueTJMdjZpUjJzCmtUZFRYR0JXTW15Z0NyMktEbW5w + dkk1TjF0dVQ3MlFhNUFTbU0vMFdySWcKLS0tIDZPQmxSVGYzT2dDM244ek95dk9n + SnhtQWJic3B2YTM1ZlE3SHVRSjl1YVkKgUXW7JW3WSM5EusBoxQMsBRGwIqqi7Lo + DgWLq/P1rruuqRAS8hl4cht3jz6PlCJgVh2xpaM/kfkFS8ZuhVFw4g== + -----END AGE ENCRYPTED FILE----- + - recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKdmcyM3hSUFdlM25UUndu + RUhzdEhsakdEdytBUGRyRTFXRzdYK2RBR0dnCmJqOTlvYkZkeld3eDYvRmRmUU5u + aHArR0FkZWRtT0hoNTZpS1JmaTRHencKLS0tIGVVSWN0NWQyQWdrcXdQUnQxUjdu + MWFZWVQ3RmZZS3FnRkJPdDRrOTZrWG8KVgFqfeBLw5gTBKugfnC4a5OLwOhosSgy + 3hXbGMrJiBDwOS+70H3L+IwiNSoJ6mL+ufShCTq8wER2L9GTteI8gg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1dhzugelagj6vge5jjxwwn0522ngf7fhxn04sxy2tm8557rtme5tstprwnj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzamM5TDVQM0hnZklsbncx + SlBMM0NpcnBBai94czV5WE1Md21EeE1kVXpFClpDVTRqYm5rWFhjVjRPQm1IVWxW + WTNlZFo4Y3VVNjZhckZ0RFVlQlV0OEEKLS0tIGJOR3k0OUorYTNXL01KQWJBUzVD + V0xidWR0SnBDM01hRlkrTlY4eEIrc1EK1Hye/jrQebkEDQ8muJpgHqBLefjnEJPF + GxdANetJLuZeeiOUjaUcbP6tecqZpiWN8fFEXrjNL4vnrHvJ+bR1aA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqQURCeGJBYytCdlhrWjF5 + c1ZrbEFENDF5bTNMaE52SE5CS1dVdWJCNlFzClZtK1QxOWY0dEVRRWY4MEtlZ1N1 + eGlaYXVLMUJiUi9FckdNcllBRCt4cmMKLS0tIEZuOTZQTm9vWHQ4Y3Z6RVloT0VL + OW5ZQWIvU2x1OEN6OW84K0dqRmhGNUUKOA3ugnG/ZD7m1DKrFjpZ8opPnjPtLaQx + t8qgGuQIoX6KeUb+YybRAOAPPzl51/m9GSUB43Eanm/tVJpdaew7/g== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-02-25T17:41:29Z" + mac: ENC[AES256_GCM,data:lZ9AXtJzVuc8Jg9L0aGhS18cs8pTjOG/xNP2tG25/7/PEdEV1SNwbxubGQOFAHrNbiDbmJMKJq96mhV8e3tHszlrzQnU1uyu9MrWiAYwV3CjmwSqC4J9ezSm/AY9e9+OWKn6sb4RVsz9A7aDGUhhoZMycnPNRKlpTuzdTIJK98o=,iv:LxSsZoHkJ2HFXBLWkw+SUb/LYW2ciE1DtzpoV4YLOwQ=,tag:QeYmreRGZk4PqlLWJLLD8g==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.4 diff --git a/nixos/machines/kaalut/mathebau.aliases.yaml b/nixos/machines/kaalut/mathebau.aliases.yaml new file mode 100644 index 0000000..a4d15fa --- /dev/null +++ b/nixos/machines/kaalut/mathebau.aliases.yaml @@ -0,0 +1,48 @@ +mathebau.aliases: ENC[AES256_GCM,data:dSvAQESvLgq+k5YF695dUaBI/uMjKNg/AQ3ABa8UXXi9WoK/I4W+cwTFyppWOgKYg+p1APzJ+yfR4THlUkUOVQNcSCq4pUCcVPzv2UrkeYCOa7/0TOhEZGp4Y5AcfjQ9MH8TdX5FNZ2R4l6RrFJJTD5RKbUjuFtTkw0jpwNnICYiPrl5vm7vcN19nvurvcWERx81+rYRDEr6qWxsy3gCopZl3KGQJ2ZlM0p909xYYGk1u69nWBOP+5icEILMSSbM+dCztFS+ubDJCn1nEhmVNCqlfVIgbLkwbG1NwdC9H7RRndURskjni0m9+lbW9jY4El9OBsohQz0pkQp4W2sA5NSJvwkBDbEaxyYc9DwvpMwR5PUXxcx18fyLEXEmUuUaskiuhwBpwgf+uDsPro3DHUy9qQuGG5bk6hbmpHs8DWlyjJt/pdxAJIqEwKo3OH+QOKn/yjOGhBV9lc7YPevgaWT0859bGbfGi76hmFgAymU5/n/Oy7h6sCkG9flA5H2eoR4sjeg0OBJf1T7ZOvpCyVISBKxJBG+BOeik+0cLx6EoMhIINx2vZM6A0DBc+kLBk9weGdcWcIBDR0ml+x++JbuaVrHIr0EUbtssfmcjiW3aYL2CRjIoqdMqk1f66xwP9QhZ+0ziqpkB99mOsQb9Bkm1Zid/blpYMscd5u1E1hnXhunWFi8gXjDXYTGQQ9CzrKE24B2U9KP11mkvaWQjoveNuj8eek3u7W5gRGOAy6hoJMMwKTXIWu4YJbYT55Q6Ppvb1WNeptxuOlCfuXipOExqmwVntu2DMF1AXXImMS2UM27zChu1QvLuAqs+LKmMY38CKR5D5SzDnXNX9gQhXSyX1XHE9ed290prA1LL0TChG7QYCfnDmHuphbT1ea2l/I/2jqfZGuos2+R8chhjgCzRztuWeNF9NG43lBP37zS8/PFMb94A1YMyhGXM7k7nu6SJh1g8HMPOGXRS9athte1neOQ9YlNNAokV/PalBgHoafBPKqbMY3ovVHPT7SR8/wMkTjjXtzUS1V8GPNqQBHYR/eLTi5WTVd2PENmTbu6MQf13kTVLOzwcJIehWETTwmEo21LJSzA8ZvqgOKGYloPlsL6zpHwrPGATx/cH9eCDf3I/bxsgXAT8v6CjmU+VT02Sd5+HgKAaXLKE0aGF7hX7ZOzlhi4f1MgfaZHT+LbEag8tTzJH79P6AZtjFdBA3G0VV1sViIlSEsq8jbRdaf8dQqLlErkXFV51hnqsGrTUsOeu2kWvsHe3oQ4zGcAkfhsXEfRzB6xpOOwd4XanFgDaDxQ8CXDZ/sFbUQIBwwj02LakZEWx+oMcQo1HTpBhdoq6LVwyRCNHTzBkWdrB40iMJz5HZcTLL/eXXrdyGzNu0E1l6J+FY22O+7FRO6hzd9OGRPJAh6ATQOPJXCk6U4TSL9d1suyR/bJcBGhOwog7Y+RvXnBIwqg6zWWhv1MWjd1810F5lf+elK05Q1PmIbMbdGPhGBZ1yFhYJw550Dl6RskvqJpEMXXQ6b5glJenIE2b/WNNr8PQwqm3XKKY9V53xpvTHG5pcsyf7rmL0qHVZYLP8NBBTFnfhtVHT4fEHuaXc/Qi8/mF2Rcj/0mefVGZ8lvqaG4DvibnMTxDIQ30BWx4+m/maVXslKdGjl6Xhq5FRGpBA0SqZljAFnl9Lg/xhoMVta4XGWWsjixXVlzswxiNjCK4dUQGiE98foNi4P2oCeolV7lDWqPzQGjx2f+S4d1ZYi23JpiUXrmnalBiXlQ8AD+swtXbpbixoFLKT+nWtFwAEZgvjyxLSVfoHySEwWa69v4kNzYVjpAuqyEoD01HkNExCyE6gunpJglggbP2sua4TrRler8GcuH+tqkswm+Pnvh6pNvvkp7ZZ+lcGjUbQo/QllnH7E9uytyZhDLxsawOOhp8c+TYOAB8V+7TNdotOR30Hs5dwO+gum8zoGyeijP1/uSvk4ztxBGaJGWuZXq4HHSq3zDhOvSCnbgrDi5W2nwCkMHCcaA+9XLHWWOy6GLRIHqdDjagKRdmjx2e0MsQuXZIqgSdflNYLahuk/JJ4cqnRykz58ILQi7N7URLxs3SdJvfMZB/7ltCR5hc5raDupBWKJz1dX5qd9ZPY4QPRnSYKVuro49162b0qHwLdu5xsZUJuUey3lFvo9WHW+GcVH/irNH19ua5YzKJWd4qHHbhE5hsi91n4sWxH6gUfs5IF2fY8s98PU5VVstJlHhs8UrjbiYQdn0EhSxEBW5l+3eKLze2nPHCDbiQ6oe5c1uURBgA569ABHcapXi93ZY6Qqge0j1J8sFdyd7I3sOY7fjY6hdYzNH/nJCBMAh9iVMvu5X4v6Hh/E2J6tkZX7DinD5eoGUzxRkSejVRytfvbRLCXthJUePN2MOqBkAOEGCagDfNJx8MgqqoMgv3p/yBa9YxyxbHbaEwVv9s9EHQAabftBo7UQn47reFp6uPD+LTBkBq66oFXAkh6TxcRHjboPg5tVg9cVEg4nb+o8ylL/uyiw3svcnpH1k8WkvE8C71plitgO8cKEyiBdtQCUHi/5xn7DAPzkHO40ywDEtA747jrsaX8oNIwqKDmOarZFuYfPh33H9P6bjJ1++YUWZs9R8BTtAAeqpNthRI1Eww7qCyzthajQpxK0mQMQjj5rrWPvEnpmwKGKkBoAkQgA2FIukn+JV9cv/uM9z5DXvN2VMxe0GfH/QnYana98sWMycWjsQJMK6LDyqy1rC34Z/W7HpeVJPR4yXR94lZ+lepKrTfoVTlBmkZIadZn7TC1HIC5PZdscVRA3hOv8TshwTmT0XijbYmRqafQowMBXrTCe9xRxISaIZgbbG81/GVJnUvJS+uBLT7P3y2ekPczmfoV9DTb/TDgYSvQgVDHZc/qQrhmXMDcsOe4hiCIyJ9NlLHJMXEVvO7BQgFrC5GSsddsrd+I2G+f5p+lDReaT+EHY2yLfuSOq5uacYCXbTn2VEl+pwYqYS+ORb6PO4VLbc9MOwbYdhPQb8+jIwAm0NAYnIdOoRifsiXCDsFAU/z6epjqh2/xy5keZxwQ0ZpewMkKX3BXBqPaDRakHJhzHMYQzCokNLQDwViNYA8Ln0zfN79fjveBkn++jj2tl+x/0cYLEya+BOQjTyEo1bAWPiENTRRBW0xo5b/ynvY5KDQsJ8uz4oJ84UH3utjidw6ZeAG9ukoLxQrAR4rM+Pj/IhDYEjbmDjmpkk3REp+4ONJtaKPRL2VenIViKZfuZw0gfFY4glqtUwzDHWYzRGBSRSR0LIPiOehqgWYt+RFUJBmAuwiuBsfW5Zk2TzN46fsrKD2RBf+uZY94Dhl+L/lJqRXW5liegQEbxbGkjaRWkRTWqgimEPVXlMw3ots3skpj0ezC+5BVcvdSu6ceKBmINcKtkskfzHEx/OEO180U7M5TasfIYePomPJCqk0kht+TEzv2NLMI+k6qy35SsUmEiEaHu54ahII0ciHE56l9zUzLChhGklqu+SF2Yx3vAmcoI0Z17siVG/VJRil4vR7DdFfAqKDEeYjoqGrJRcxNnXZGJWwOTKkx7mH0d/i4z+R7Z8l0kHjsPN4piNHWSo/FnpyOP5EMnlCuO/4rMgmIOdv3LNmdu59bkbb00JCC9VU1ZbAH/uNLrFPNYhfA7VjvlApckgNwIkZKi1cElcUUnm+OJTx7lNmEGJwYJNNG1hxpZuvh2vBzySfYwH9LV34KTivylMqENGD7arBR+ghFfLXpTjnjaRiwAWT8fKyqloj9JAt7RO18DCt9JvYoaS75B/2F4h58+nl/nTmjZubLMf/HYgHEO9k2W+q75WTkz/0HiAEXRD29VTR63c3uPtlLclUEYzlUfHfsDglAUzslAkHmPxhfEfqyCPpjPKgahpMVxRg+9HQgCSxhdYEp1HjJ3ucaHE1AvaU4Z34HmcyyaJGkcbeE7tP+4jM++SZZW7xvd7uSeTVOEz0W03iSSBzCZ2timms+ILH0TSC3hTQpSYlZIqZaQjI+r/G9JvNpBPHCzWpi0OWwD01cpttty7i5P94UNIFHXgSvRFVRdrLpyiHKDeEXdFwSbhCiUmhChjf4L+u7+CI5iIil+KXFhH9RgWEIBT3sYAv9kxuOL3EHGJvHBOz9sR2FQg8X8/OkQkAJF5b99pssxSPSGrzNmoNu5IriyUyYi/P0UWH7L5FLJiKg/2LUXoNa3vD/Rs8z5fFeVVv/GaM6SB3dr1SHFw/xKt0Z0b6NpVd39T1cNNCd4eo+VBbB4/GX8mBi+ARg8NG+VbIrhoudaxxGWEbCt1wIYRE1H+mV28PgC9rOOrMiGk2aTSI+zMGcp+jLpId9zLrR/2V8h3SfLhJTBQJGw6e3QQ3k2IlY22Xw8fY4dvHk1E36+EaP5WHWJlWgnO+iH5ep5t9Kyez+6FdhHnDM+4cc9Ud3JZP2/RAofFMvqRyt4xL84K+szSUwaMcwJDRAlgoikJ7GGOQGIan5VcJ3EXzpfaEkrspijXZ5bYrntvKE9R8mivvhMw+m21c3A2qYn1Vprh0Tcb2c/oPkx+kqMzvKVniNGj0ky6+ancCW6MTmtGSbJv2lfr8R9OjKBrCMpBAe88Q/a2bvYyg+EYtyWx3dpsqyCpXN/wtgDs/N3uRfaSCGRq2F0erhbkYcJYkUwxcsD5c9LQzQvTkL6V55VWna0+tlFrZikBafQCsx3OHPynheU3T5KvE4Kra50Vk52S/a0LDK3ZZOmGcJgruK9u1P4IS4bxj3fP7D9KAadZSWaqxZVbdx+LbweQMyrpScxdD5AOBI+9S7/17syWQyWDd4jA5ADhokMYxbOponnDfm2rhbpMhhwu8OVWBZmPBIGwcECcBGNLBKkKfwoGR0ipOex6+JYfqK73XoOltJMeBUCUtEu1T7rnigfrBpEHJUJxC6Jykk4gSgvFh8lWgYoHIsYYSIkDhuBVD45FViaXq/IU4jBLHiMcNKD8F0TioI6c2TmKkO34LeroFk6KWP5w7R78oy7nO6wYjmcMx01hLUUNfTJjSWNDIyMMoonALOScg3teiDU6fvGfOmfmnjJKjXFX5Zmg48qrVgTrazRDz5TLUMdrBZOREWQJ0V7QPQAk2yk24R8Bcz5GP24txRpkaVwmgoNGHofCFY6WFj13UsDe81F0he0vSq3/FaxhPXQiBpaStuzXyAQNGqPPx3GoXRIZLq5KiGSQTiDVs0Tq5SciHH93G2vRzOQ9zHaYyQJ60fkXbFKY3E7Gbfj/j/oXODmPMxcmCPPqjvYI9gx3oR78BniEAeTq/0r7cRTGx2DcaPh5hZ11tpsBA5MRDA77B8/UjIo6glpk7BNBq2wyw6+dMUixhJ0a6Bn611rZaQDjOTO7hhQPSDUdjfWVzaosB6upriQtLCW5DVJQmc3f9auZnEeVXFI5OL70HxrWY5jbyMVeWMZHkV/4n2fn9B8ynKAzwOvHMy1eHn/F+XHsjIhVh1lCN41lgh87/qEAo0nh4xFefu7wtUChh5tKQiQwb0V7bxwvcTsnFwJf+9j7U88Rz/NkdAMquj2y7CLrdLqqVPJMbJYmRkUW1ko+S+I9V/qnSVjgMalG8Xk0Sqd+tdeboQuU6ygZlt9YkEMmFLhnmKsxEiMonXVudwSJ7tPxWnvj6Q+fbs9EY20NHPR29uT3dgxKzCXWCiADn1kEgeRi/KI0dr4tgrf11sXxrhC2cL5XMpVKJcswvQhnXB9TWZJgakOsy6lU95DYrvSmEz5nS9yIDzAChIB5nUXB6Mos5V7gA39YfrWm1TuRw528YLUdy0gjPGAVO9KfysoGd3IzOR5QkPE2iafkiRa8nuSWFuYjXuoNCTvy1t9UhO6X6i47kAohZerLEBzP9/eotPKtOASrFllg7RPlJO/OIA3y3owYCkB8bhDb07kYwtEhzLX9v14IBEfYq7vA3rcOPr3jSXVU+3Whv7h0VN032SXGq0yORoKmC4yjaWYN9XJqXHOaaq+79yxJai0Vs7tVyq9OcgD3tTSbSWp6ID6EGoT9rYTME71wUvmVG1LGI9DArT3sNDnyhcKUa9Bg/SZecX+32N1AZMxhKLIR2fsOKG7+MfEBC3nvf4VnFGpeBCybSm3WJqygvuHSU8aA3obeqHQPka1rpgtrl7Jc8zho3pAU0dn4lOxH6Hfo3eYZk1z2LF+XMoVj9V5WstfEPxIR/ndRllK0LpcLsZ2/D8llpQQNQC4sGbXzjKE8YzsIp3oh9uVHcdNXlVu9mQkndwHqAOtsKCqyyHT86gV+uiJOp1gz4j0EsbAqR5o4ui+EjA+wjpgLUctylmv6Zq8GfdWNyNUYl4s3Y+1Qw6M3b2Gl11tftQqHC2ajaUcjumLJaX3qAzoO7yyDjObix7kDmwx3e+M1/T1ku41YyBLuFCpKbC1kUmyUfazcQgzdc+tVvYJc3XrM0uKpkSRA41cSRsc82IEjILzxUox9jT7ApKxDRquSJWJc8Ri1Xk5yplFyZkUzYuvUMHEA/IuuA8Mxr2Y1Rc9Y2esOfZK9JgFhPylTZlYpv7Pklabb9KJw6pe6rLoHVtW83yNmnHME+sqSKyz/U9leJbfSKkXS+h0ez42R1Qs9eb0Hmcam9sSOjxQZrnxdiMJxZt7YFJNwaE6AqpANTIcgmOcZl0KLbKoPN9W/9/1LGB4ulbAhdB0CWCqvF3cvm75RxwBvpbsZjYsthFpKXnUF3yWnFNnACtyYGlSdsyt5CYhGYY4DnENzb6meNEkKOg3YMgupoxbeXS6YA0vxQzqEjS+f1eK+Ad5ohQK5puv5S4xtuDxgs99O91E9acCHsAaxKHwoYUuxA96RPyAUlq0jxyoBGtPXpW9sq+wLtVnytLRCfP330W1GsnixN6iGuPtBDekXkb4IVJ5+fE9l/OoKYsmN3oUZRVNdVQNuTjv2hW6mLLBxsuOSVSic/8InMd1Y/0EdyeVaC5oVx4DDyuAhkOXiBSQTSV8CFsvPaiaGpnnHSUbnpoSjmGK1QVnPJySdHtWt3rFJGOLZ2g+U66wjUmADqSyhSZGNKuq+yhFsMTHoBmoEp4qq6kfs5suEd0vdZXfmR13yQgdzYjHNIVQYAGeyTlRDrV5XiJIDFZ6x3pp8/JvlPPXSJA+dINRFHWH13zGKrE5BCkiXxQ8bs9UVMazRZ1x3p2Cx9PNPasjFHRu9xQ5TCnQH0pmmXZuyRXcTmFUyI8uyz6AOhpUqlRWbHNETMzijnkZHYsIRHAB+y2YNZrINRk9KmqXenqIXfG/eH/mUBe31CM9AwCNi3TbQNDDwkZeigbcpqW7/Xt970V0R8cFQKE2H2L7Rk2XWpI+pDSjL9rrXQwqO9o/0/eR5kPsdKBuDRaaDX05Xv0oXv6mZFcBfpq7y3qB/b0tYGKGVB+eePRavK5QVojVKBkwNLN0LpyI9Yb+tL3vyVsVWoPRGwekjAqKqInKzpHF0HujvPqzcFjjFxFrV6E9FeUGTGKH3C8yxenuve+YQaTGcK9oDwfKHgPdV6Q35EfSZVnPlk6a0TfyCerdrqaYFriSpTIlvTJFv9eh7m+x3z5JD2DKSXV2KBEDZmMZ6un6ff7q+g7Sxq9VuBlYhX1buxEP3BkdQT/qKqGP7mj0JrmwzEbyjUIeRdMBdEN0zlEYkhCjBI9KvX/HNV6ERKcurn/7h8Zf44DkDA2jQxKeBtJPGABpYNDpnmXPkglgWoW1SPUxCCMKPSPZExgIkDt9acQhJF6fYJ9wPwbFhC7aRxSj09IYIZdgJ/yCxQukLi/pEuojDg/oqN30PoBi7r0+VP39Mh7bBvSuPuamjexV4m7Ujxv5BdEvl+PcaR1Wdj1p0ctecEH/zBv0RA4qggY+dvG6nrGS/uFRJRRWAaSFuUcnk2iJV7dRs+29BBmKS+jjTRIsp4OgvUeYppZYBP8ZVC1Iqk3JhkvlEB+iBeFErkpQ2m4v8jhgYDSi2KQcBvtD9dKqJeKRg5jJaH9pzr2N7HsOZXZSzd8/xYJwNaCwblucaMQZsb0tD+ISF0APKYh8Xe94SLaZidoKMujuKGFltO4EQIvKSOiYTNSCqanT23fpOSk4nwOme1IDFEGq5cJldErUYI3sxEmF0du6AUqcGio1P/GLUHtJESB6W6QcrqeR2i4pgShkwq3g8Utu1BEUOtNEsHKXff2oV2XtTMH/msaXe+wWJo+OTXh8+TUJq761q3uelbMeevyuAjJvmkZZAdXYCJsbspMrg6ujhkDCl08dBjI/WAYhAEgUl2SjXevyKmacy91AnIP9VlVGA3NNJ4jyX8h9jr25TtW4vaWCt2SWdWhSj0wGfpJEtN8MXsG6Tb/XZHegUzA1oWEh3Tq5tciGksJ7HmrNc6imeAKnHKRYWMmK4aeat8R595IKEK1Xx+Pv4xDjxodIX2zWa91lzFdWBo1K2MwczR7KXFnQYMgss/gMmJqW3Hj/zIyE4ul1+j9QAP/ddsnq2/2rwGo5nIceuEPKLBIOdKxhymOq/w5GP9yf1i1vORDH72lDyFOSY+JzuyR8zVNTR6opbJAgvD+3UOmGN3xHNbW/UXOUw+ggX5uuEGKox0Um0wIoN6VsoB0kvdkeKy3c24puzU1aCcPhoUf+B7tyN+rsgfPSvMdrFxrKdjth8qAgGfloLH1tZMwTISYDestd6z0slKkHWsm9k5a/9VGeJXu7MtTuoFzvYLsPCJI455PBepCKbnjhLiHC6KtOtvVz+4vTUCSutdh7YpI+otnu5wfci7zaU39lx3DVAHat9ot7DKFZlFDkVcoJcrEuGrHBsSiMwLUiQYbT6YcPC5AZY8EZrYPXGp6VD0NTkpcJsf/8PC/eI7XCdqd+giiZLyDZ5UhkGzmkoqL4oG7qYsaZ0QNht4QtVnTIPM5b9QKEaN+m7b9NBj8fphFP9vy8tkir7J2cjAOUcA7tZopHRjwa9Mk1VDrHKsXDa8TyFPE/Djf0NgY7v9SaFozNss9U2830w5kRYcqlMBMz5+34db4LVF8CZJGJqvdKI7jMs76YqlpdVpE6D5oBI6c5y2Xrp9fYKbVYrt8JPGYm+X7DGKdeSoWAXEBrDRIPifpSWl7PLn/jLfZFOFf1SDiA0fG+pH9ufRUL6S0G2xwcO6U32diMf2P/+ZpiQGk+wMsmToSLiyoQzG0eHT5+WdfxtYjoC+wNkxKC8cWxNZTBj+fpi5CsHsCd9rPz17ueK7VCZ9jnPAdSvDNfIJGgZ7CrwDHLt1mlGtfjtmY1IWziGEfH3ygxnwmxWtHJdt31UTiAbLNoYLsElKYy++67JryHIPbqbR1ciXvHjCupjwfBZ+i/LpDmYEY3Neawo56hEoSmxPJyShBGBUpRXLLdOv6w3siPy6vi9f8O22tC34tD1mzg576wmL9H5SzTzPmayHPaYkPMhLpuyshe4TZZ13c7la+V+Z7BJYVwXQ9GRu2cSXiowgi/FEofAYqEpUynVwBtlrzU2z6b2LpikEpP/ifkoanosFamG1NOmHruB7v8J/YCzjBejdLU7qRWnLnd1NqLQ4KkbJ86I2FCQ/MMZF10dp6RrzVuC8Sf/CQzTyy0szaRgAO6DVj5yXJoXiMEcGrwUICA8ayB12ylmGrwcsWlMyrejxEoDmqNN1AHQ2dX8VeMDkFQAt9pTo2GXPrA0YvBjT8HqVW2eYTjY0uEhKuajjDg8/n+NxK/fYFHwLa6sEMNannVWUGXhsfPc3CP/Muvhdirr1SH0Ksa7S+IR27LSE/EpUZ/VGJW0SaTd2ywqH4i6zb3fyKs2a+4qzSe2UTHDMa/qLLtxdAIS09DqOH2tIk+FHMSkI8nVENnOrFZJemSk3Kw82EAqLsBN/IzQ9JXRH3mP7BcGOhVPFo6wJPFsRTPUklIoV7sOBrAEi68qbNP/ECmAz4hlCYOOHVOgp6vjaY//dB+QmLyt+naeU+d9bas0DvmfkN4M5qnm9s6qd7GPs2bD9nOkz0Zbjg7g7gtNtVOiJcfGCU3Yetn/XwlsoDexl+Dq9zp01PEgk1+gxdA2cDY8PTxg9TdrkAsPvUxlbW/ZW4Ub++ObMHfPTeYC2AE4idx/FVYH8NXOYNpHRF0ZNJykUSvXMFi6+dKSw6G+j2BzEYIbryUKtHF1S8ET5J1vcnHX58ULZ9DlVhGjZ0haNHidZhWGn2SeO6YSUxEYrPFYRZbu58dmNMpsb5Dw7IL6i/9dkG58VnBP+e0pYwR4Q7PY82KYqHxfnKuAfKuB4KFzecyz7AvLGQkZrQQNP1gpdJ8GdiL82fL+/2DBXRxRuXtMsTL73Y1cjH8zHpGoydwPnPurtWvWHnHRLhB7CKQHu86CY+wRx9dOvY8grIXJcckDpnLM4HzH/4Doqp0n+JEjTkKzNyGm4v2bvocEYGAQbTz6FRflTXjxhhCdgPXL8hn7gyKRaZM59ugbSqdm+MOmxbtQz3S6UmgxVAB04ZBDozUGV1MJs/tSn+jArvvQE+N3AgrdAAXJesaR8CMWpA/ZWclJMsifC/NB0y2hBZrcgve+BpYsmVRfUh4AUz3n9pAkaL6tFVI16gYjMLzWQ+yaNh3cyaYalCSyU7U4I9yJYnmjnsOeVCz2XVHFl9sDvKAXVJztNzvxvfomy+77kqH45Bs89kAej9VH2feAO8rkJjCaCysOrFWyDgWIiz4YWG5m47nQruEqxWOqAV2TlJhOlO+7SNHO7nYnizIusCJcIPuCCmI8NySrsxMvUC117/u0vcA9hvuzoDB3oJHLNua71QhYknnYtOBKK9h98obLrfe6PVUTdPTI4UehpGK8Nf4+TqVGxt/f9YRkrlHFQLPUKTWTM1p/iK9L+70fZscGJsqGAAzC7OCDJB8dP1mEv7wg/TGKJQO+HU2X9OJnZqeRdxKoeCzBhGZxlxPdNhWPE2zAELWAX8ALJZ/VCMLmLLSx7zN4qxI/iYIj3WScKLpdaXqDIM4f85MAlKVPma759NTMaa/g2HRplFpS/8+HBDhiexfo6ylFjaeJXrOa/tTo+esviG2FYk/bcLMdVGqKR6t0gwdMh+gjmJDo0UkKCHgHCjivj1a/20kkpdl6xnOtNNG46/7wacclDm9Kw3WzX+O+4OglXFtU+ngxITNOE8OvKGmJC9wolzKKft+u7QrcrB70TQsJgjK7M95RzOnUBoq4qqBw4zicTrLojDJyZfTdPRxQFwFD15hj2ZP0c9ud6Tsy2kFrl3V8kl7a3jf+TGXhFR+ht+FxGkMKXgYUradYImeUTnQ95MY+maFyY0iXdAbet/wxUv9m8q8Bx1MIkLbZLq1ajfCM197+jjDdAmJraRqazPgw1AWfisa1wYwMUlSZ5LiaVl6dP/rrQLx+Ifb2L2QAAQFRvoDtByA2i5NQb+5XzPLWDQrSP+Vr/9sop5hDypHIsLUZfPDeLWTNDKhaJ1PtIxl9/eVv6iQOYZ/+4JqXoY3yx5Iu9zUHpo5QsdinIBpxMwZVt1QRl6tNfOiQyAGbV+kTRbafAFSpuEFJ55sMJCFypOSG4/5A1qwrLymeav1/l3KdD7lVPBoLXDFaYUMTdTYu6h8g8SlUIGwxCw2J3kYe9F8kwr5u/RXdyYCy4b+GcZ+z/SGINNfjDu70rmbwuzNr8osRpmAhAnkfauRgKand3Txi9Q+gOafAneLvG6+ulP8REz2VyJxIDkigrl6BhW8H41GYzyrncTfUk2d9jSn04bKRR4mW1iuYiizFALIAV9jzxlb/k7jr4IkisBCxHqSYEz96AtS/JX9XGTQe1BtWZagM2s3oifp1IRALhzo9r4pCCREo6TgxbSBCFS/3fZDxxMzWPO3y3DTX2JMkFKTDR99t0eMpDxwZ8+W6mMBabPrsR8OGgRevosNT9U9huDSvxYv9Zzop4SnpvYx21ZufiYoj+lrwjCw7AU7goFV8oM/na+IJuHmd5/2weiZmQ2+PfVztpXUgNRMPIYQwgmg70VEYGVPlJu5CK+DegPHOttdojVrKCixh3c7tSVXw2rqRmaYCLbIaQcZXXmgmAhEdiPLj9XOXo1Q2gY4hM+nyXtuCwwdFAQnHu1Clk4tzJKwg631PM3qkeWfY4iNpEYEbdoC5yjsDogJHtrM6FA8GuTvktet5aixycW+Da8urbDrutHJxS0+8Cm79BiLzRMGjSPk6wHoxGPqrnahay33E7TuPA+UUVCCWncOjkzFBi/otstuN5Radvx4teaWNDFZzls3viQISXNkiCyjWnJu7PEtpfXeLLAdQn2sYIZdzbfrWEpgLNwBWuF4MfCw/dg2t1CtZfYxd6lJ1vcCmvoUMzK+kXAWMSZCckxEMNVtEfW5vkPYhkAsVG8+oN6pg4fiYxn5ukE1qvGpMgDs2fxsV3agGLcWzN4wo6KhYeaLXfcf64e3iQyjGGQNL5WSdUM+7gzfG+I7ldh/9JyIK8DejEjWSunQnwehG3iur2+c0+XoVIU/t626f4cRamKnLYPVG2z9PqA9p/8lX3Y48BoxFvzG6ckJZ6+4h4/hcAo4AyTGTIMk1BE1OUR57BxZp+Yn7ymrljk/tBl+nxTj5Oy8Y0Jyvx3q5I7I44Ip3wrKBm7ZikhroMFtAfPr9gBXpqnnioyMiYAOyBwRpMKH2l0kBgETuKtsuB5CRdsXLYJgB/ZC/oAnAatyDmjSjeEN66xhLCxYbrapiKkx6ivOIE3G8n//eoxjL4/Ay5BIxWZPzOkwLeyevNCjdfki+5h9ZGkvnD/WafwWa/2j8bV4YZbfElsXW07zMN90V+uLJAhzCtAtix3qo4pA9uUvQ/3GdVdqK2/0CPjOY13Si+2Eyhf552YRR4BYO3v4c5PH9VbcXzxtOpbkgUrTbLbFNIINjxPR+ho0SLUGfF8qbE6zXrzSCNGaTKuZbKWWoIlEXY6UPM58vNwG0vjN9JqKRBuRoY8R9C07ASDsm96qQyIcCHUer1VIVe8Ej6tUdus1ncrAzBMZhGMjeUSLH/UepNCp9aBlW0dMGOFV8okJO5Jt8AobgaohDVntatfQX2vD0BbrOUPE7SmlUCGgwr+nC/kWx80sCekTsu74I3oTsWDaXnimTHgil5hfgNv50lwKq+5dRY7noiMEaI5MJEYDAtLhvQQtu1jj+t+UU/WKnL0vk/Wx9WxjgtStAW1i0ADvCBOsTeQv4VdTmVt5t0X87y6Z9UKsoiMRzpDBTsxEACtJE51oF0oZJLOKcshRgNoXafo9IsDe+t7dv+raRhAO8eacBzBqabW1VTKPcRFKX+ZQtMLNtsNQvN666O6JGs1BHazWZPbUCHGFWqk/xYq7tWtaeKLw5CqRyl5cR+6qyWgMEK4Jnyc60U980WPOcKOKo/x+nbPQ5aO4RBvp0MdAlFqRd8fK0WEk05opxWdYrysn3Sc0VKc0eqMAMC5jUGoQzozGQtg56NwtXbS++eVdW0dBwg1d4GVC38t/M27bblQgtAD/YwRr9eEcGt/yOZCk3x83rzIlLF53lyD84YuU4YC/H/+XxJS0EDAE61ml2JXTxZPzy+MAXVDtjsR8RdOZhTmItTKM/xcKgqc5RUnxO1IuhUAJMfPh14s9c7THzJRA7r/aKFeszJ/KfJbOJnZsyCpluDuNpmckfmUK+lUk+Y/QeRMhd77CH3sQlbw1Tk64Rt0Zx21G6tRfqt7sRuhnVyELDQItdMYcTKmk3pMQTxEHCnbNNSbTZcqFgpX/AFDxqea09QLRyw0+rSypEX0kOuNGJzdTHpUh79gpvjeiOTBt+yID57br1XPdazJ2Mrwl4FBnbo8Q/QVJRrBMzBfZm1odzsW5eUGUmXQhJwJbPOOsFPi+LGdwLgigh8S+EU7UM188Xx6Kwj+vg1raoLClkymtX5LZSP5sZGgclB4lOAqX5fhsY2n23Q5A2CAWYcq7X0zGcyzS6VAOj1PBx9y6QjGBhlHSHaIG1aXnjw3m2I52jZooZRovHs+l9gGXtjGHzMT6X5oQmqCxP8zLuawsDmg/RPf0VmkG3+AiidnESCmrD9xe1w0SwesW0PONI9djYJZ9W7EfHnGHl1FIGX+95TeS2qZvUiQt8CnChGq7trswiRERz9Q1S6sHBfKLOJpfWBAf/Po3ZcZzPqXhrlQrwx6sb4hFWwfaTOm+RlqGb7sbInWeji/AxUBcNTq4sLCq3SB/jppCFe90SccCqiYQI7wi3UANBOdr79OdGudlwlX8jhkYYEEIx20cl487BA9ojGewjXkJmmTdhVYPvewbd0P2R2SRrmGlUL/5/N8qoUmNKWYHCV7mprmVoNu/9RIwoRr+oDwblng4ZqUlVWXe0tZooRTqIr8e4HzmPC9LJEyq1silHUbLoHkSehCnEOlyGrdxRKqSlonW05Jdi2aQ3SP9WVJFqI2S1U9n9i4WTX3cYisdLJI6BNSse6H+hOY1yTh6NWefMp7c7r4HwT3pa4WlWUF6XgI40aAwn4NDkTdSe9JlNIDm8yxXDOdP9sNrDcrKMn4t6pE15eozBJVqkFRJO34IIGmSZ5ZbNlA9jIeEfvpRol66aqrpA5c/as38MfAVCDzZBb5xbfAN80fYC+cZ6C/3qNnRcnz4qzSKQVpSVBJucBz0u8IH6HHfIQFaP68AkTYbayxWPBph6lDsSdR2991+hm1Uw10ZJg7jReDC9WgAPgdAjxvcCDuNZNDKEBmTNvAk3fbISZ/2WuOjd6jWkecm7I6qXKmRtFuJu0tCjqicpRQ4wBkYrU+RzlASOUDoC0/bz6UjTLeVm87+kKNry+F+n0MgcTjvW7u8tDlJe6t3PRcM8qFzJ15gWk0WUWebcf+GQqTcvGHQc16l+4qqxKlavkifsP975aOwT2TFVb9fhNZum2pynxItD5VVi0sNbrYG2qXj04BmhxRVrJcxsxEVIitwoaWrjiXrYfdnCyhdv5Bzce1Cqetqe2dgTrgCMzXuAgkmbaChrG28TQ5rCkWnDfkNmaq6N5cPzeOE5qAejwtY0peYMkeOzy9xbL+QUGtAgp2d8HHK905v+n2tV8P9FnMpEZUby5wq0IfKMufboIAJyY/yP69od0eEGrbN9qEQHUxlyvHmb8oKGbnCRpM+GHVVsl7+DcsoHQsudKcfpjPRAsVAb/5dCHTR9wEzQqv/UyMTe3xABpT9tjpnyiT8Q1MvdH6nzpJ5UaXPnRoatDNIgq2l4QJ9RrRQwhX2/EckSYVL4s4iUHXm+a22Z4kva1801Ig5OJQa6qhfevJEMK0IAnh/NL5/EPc8faEHn+F12g/JvcVJZnL6VSgqZMLP8naGyAmClks3pLAw2gQYTuNnt8Atqdr6rmeuWRHEmjas4eQHGodDTFEDv3jROYnKmdB/JJ5ey4WF7PgGwaqf0iFBND0pTSUj/SiijIDoFekC3ZQd/17EWeF2a+nCHp6/h7wi6uCI9h2JbGuZj/uxmOsnK+zXWurtzygyyZPO2k8OZRYAdIijjwrmwqt4/NSaOtkL6GT90amDWZAoMYjEkUZ8+vaDVdSUyrsACLuHIefygOdgh2+R5jsmbL+s7X8fpEkV38hF+FKlRFdRHEdg4vc6xZjotbttJhUC+C94XvrNNKDxTirMjN6eq2+Q7McJQRNXeZdWF0ZSC8EAm8NQTCCV5IQSEZXGCRFpo3qzip3BfNrpsNNGSwLsrn+5BIFQm4EvqS0EF7kci2RwdqTCsblt1CQ2pZHRc/aop8P9wyWTTNG7JcbWMKJMJPdjvTEW+H9w1LmJLW9mEIK375TKWt9chmDcmz5eAg01n9SHHn3oj72o+mn6TzzCvsZFCkfIUlQwFH4Y7iljD0YIJ06Ar1XbIRo/GsZUwfI6gnKd05tO0ZP43MKItEzhCsQ9Z+XWpkHsw/riE/hZipyobv7ZgKl+iBa5aA2icXPcChs3MWWrhR3awoSkeP6hL6es2c64CXaofzfx1tzcT1B3XklX+l3VxEaTGvlsdQQBcVBt/sNWk4wbIwkMa+RZBJrnhyfO2aLjTt+XQHrMZiyCB9f7rndc5Ny2Tzn5WQJTafeHmkl1aPoVHqrGZ5WnJnjRcrk+bVwVx2MC2nhE+7yn6sEIwH8IaUwuh6okOBjcfPDL0Is/N9O9zwlmRTASMFQucuK/RRmZzvmZikztAztErV6gaQEjvDTtb7j0q9VH8ostEgETkU97ej5ngYTQ0NH4cXnbMBF+lnBmcx6MrvxG4KhK19giDFxZlDRB7iBagxjm7oAXrrFwgP7BA8ByT9+khHyg22h9jELbZ4UpIuuu614+yaO+MPcmiZJKBv71MltJTcQz/LBTx//uQqBL2MnBWgNMF289jyg7XiiJ1lQfnQb8b4bzoyuXzLNZYMqON2ZwV7jbe9yfEEwBzhM+NhLLoothbi/6yPU7+mPzZH/QwPQEDjbjFE6vs7VSiqVvVfbiKvjkwy5YYJ0k4WMetIdbRbknVu54UY5br202wx0Lf1/funtVrgIi5DnixNjWOzN1T2jrPyhd2BtxLJpANY/xsCZMDkp4fX3AYFKNa2TkLB45KIN32NvjPxgjSnEIqTWXCH+haCRgwoVWj2qH4GU0BaqawyGGVho7XIFlNaO2GAWckjUSFFSAIixCaN9itSrKBeAsGVplCvrSCX974qjArY9ky8SGue833HuoVKVCkI7EVA1Yk1dAbaQEXj5ZDyU5wkH7+/qiANI7a0VPP1LK1FgVL5JNn1/v/pPoIf/0qOacAJBQac0JUgXPGirxKchdjMc8WLOtfLEw2FUocjZtmVcPvqNnELxCO+JwKvvWdMBFe9oP3821f0txp+uvCu6dxnOrK43zAqEuq4Nfi78EJZNnPvEoPIugUjnr1YKiIuU3Xb9vPZ8i7/T4CnPK/8Fr5uWfZ/CocynebDaclrKojSpa01vTgaWA5byxQhgy97dJQsKnaDEgAFqoO8XdrC1bbC+9s74HHn6irLCri61xS4UjxWSMHV+PNIOBNHbJvSZHLIexT62VSRNkQc+7KP0U9eWoaX1hu7Xd8pBuxNbr0A6JOOKVXZxoLU9Hjr5qT39kEGdgJja1ijQkFDpwhdU6tK1haUf2YpbGQarTEQyP/t9Du0hzjJM4t1gkQsQ610096X/O4fRszsA+91J6sDczbuVv+zNl89TB7Qkv5DDgrgFfYcWFhfaTEVDZdC/WdZtxrKx83S8AOs4ezy2ueUG6Sjrw8Xq5T7WleT8l2E98ZBHPWW/KE0lrC5enp/7voUavowVLwcJ0peNRb8EZ/y6SZW0vr4CcxHCXjv2RBWnwXxHw5pDfRHwcgvRq2XSEQiVP8+/bABHbvjVNZjA2HGBiNChp3s49OneLsH0FWNnmDM5FTpgotyUOvOh30H4mgo5vNsnIHb7HPLUxa5aKGCcRQUQ8lXpjw3ekgfgy7A2IbISLPwfUqdClmJ6D0hiTQBdgUPbUsjq8CHxAkyk+ayGWnJOk284VD33fivPHRF4Gf8zBRtBFJvHbyrrH26wiWPVtmrPpulCESBVok/hl/PQhpu5evmxl+o/2j2YYc/s5MOi96/jEVhPpW/H7hRdrJAyv7wRZWvmjxjNbhNqCEip/BsXku0/Uft/ZfxtE8/xACAcJg4xF+4Bv/JTE60xX6fksTAgDI9L16noXcGcqrUiNv1TNAYdxctAgqwhUwT/hV+oOuzKhtQLCLK5ojehQIYFE0w2qIT1wLH2Jk66KvMD51lQTGV2KQZN068wWrAbH+vGsAQHlwQKaAat4RkA91hF1wFvvHtEC/QxvF9OvzExSei5/T5D7anAq1xI3DW99qTQ1spIdrtGwECTjRq2AmFi1Q//kQdWmEJpTEqKXRclKVdF76uQhExiCEklxHTtu2UcNMcyQtGv2vFVPIfzpwvwppmCewvIc3mP2dNME9GRDfRfBPi4NYv/8jmlDbKJyScqyrp6QSmBSaoaGpQEYpAPgc93vmPr2IxdzOO66CIhLxZzhfOiHaTxgRiNl2pdFayotmdYTO+HPXgY0KP4kXLcy8cjW7isQ1/yfwydyEAKOb+eiulRFOimpRNvQklud/LiuT9ZDetX0CxpS0y7ujLKMoxfFvylMZMcnuE3/KDw1IFN0HZegmwXbHzpABDRxUxIBlqPQ3bPPviV0HMYj4rQu5acm0X5juLkQKce89iGGYaA348lifhxB5Ocplzy3SRgEDaVHTzzGw4kZoYIBNKN1cH6AlqdtAK87FGZsHpRp0Oc/jw7WjwbGam1dxolK/n+4H11Um8POkL7pH1KePIesHaZR/kjNYV6jx5vGOv8vEnaiki5MAyJnD1tBNUgB4GMaJ4drQIWo6RETfupS3vcGwfZF9JD2Tpw9fsgVFW+MqNpbZgrmVjc3QC0jTW46eH+qQBtYhEDuDmGAVs6pm9ljxua8fjZ1qoX60fWdpvegFPCe/tyXzHaL5/5fsuAKfuXT/q0APHahnuLnLl/3W6sx28JOWoRI9aDOrGOPSQVYIjP2sbLeyiXjSrN8fOcOSSOVr6uXyIb+tllbzw7c01zfjbv96H,iv:2jIbgMhGa8GWlDQeQNuAOrxiC03V7sdfy8EorUcjP5M=,tag:8/owPwtrW4khSqCraE+PDQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzQmE1dlVQSi9MRzZ1WGpR + dFYzZU8rR1V1VnQzUHB0VnFOckpIL2tvMzB3CnpXQXk0S0JNSkpNN0FMclBOdjFy + cFZYTjcrN2djbzBkZUFmNCtXS3lRM0EKLS0tIFB2V2FoMU5rZzlxQW5SSHhlZkNx + c1BCVEV4dEU4aE5YeDZMRlFyVHYyQ1EK+znjkJ/JuE5VgYUpkCfDCZV5mFmSXUxU + MtByksmGshA8oyk0SH6B+qg07yDh+jRn4gtvnTxxudtqcVf5EX0vcg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0MUhyeCs3Qjl6RmIwVHN1 + cHBQMFEvQU1ZTFE0d0lESXgya3FZRW01cjJJCnNPNGgrVmhYeWhlOTZMYjdyd0Fm + QzJwQ25IOUJOeXpxbC85YlJlTElia00KLS0tIHdHL20yakxaNy9CZmUyaHVUSmxZ + SkZhM3ByQ2o3a0pVZnV2M2lob2xRU1UK14PKZz5blclSkUVJwUFm+A9G5nPD0U0h + AH2kt/kdSxj+0I6uWrD+0KHh8KA0Tgp9Auyv/UF1dB9MoiuQPG15vg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1dhzugelagj6vge5jjxwwn0522ngf7fhxn04sxy2tm8557rtme5tstprwnj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrOVFHcloyYW5OK2d1eXJt + NWxLWitrUWdwd0J6R1phaFA1Z2FUV0ROdFhNClg4bG5WSW8zWTdsWGhQUGFySS8w + UFpjK3dzYjdPVTNsbFg0YVl0UnQ3WmMKLS0tIFhBODRqK25TVWpabTVteTRtSURO + NTdYNkFuSm9xVi9QME5DMkRqOUpJYk0KK0e8LjmPqPQD1FzXyAuoUY1d8u//WHvT + S4ijZF8udwPzKTIHd5OiQVfCdmVughKmmRwQEHdFC69fjn6wOqLJhw== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUa2VYR0RZa0pOSFljVzgz + TS9aRW9OZ2hEV3pWbncyNlp2c0REZk1GRndvClk5U3l5b0dlcktkRXZBa3VPaWpU + ZmVuS3UwV3RmbzdQWC9qYXpCNnJpODQKLS0tIGNabjdpYXp4d2VyMEcxSXhHdGNr + Y21YcmlWTkJDRUh3czJEUWVGaG44cXMKoibsYSOYv329WNzktBVJ18aGAMXCxz3B + c9938x3U7BCsSatnNch/cTbxPFYt8GhgAXXZb8/vsT9URH+9/K2iuA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-02-25T17:40:56Z" + mac: ENC[AES256_GCM,data:5jtuwMlqF+0FFo/QWnogC+Gm4ADUrhZLFJ9qoLMxDfrY8c8AHPDV+rNk9e/zO+tmqWcNmktWsVrK8xhmCTD8cszTMHdGRxjtqvjVatd+xjAziBik5SFR4pWO7doVx25iD6DOItARW8yxRLk+yMhTgWpe6ozxFhnGH+YdEH/rVNQ=,iv:f3xIO/MSBVfIeAfGtMUzqhY9/U10we/fftRe3/88uCA=,tag:nBSRI/FpOIqrknmlos9Vvg==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.4 diff --git a/nixos/machines/kaalut/mathechor.aliases.yaml b/nixos/machines/kaalut/mathechor.aliases.yaml new file mode 100644 index 0000000..55872b1 --- /dev/null +++ b/nixos/machines/kaalut/mathechor.aliases.yaml @@ -0,0 +1,48 @@ +mathechor.aliases: ENC[AES256_GCM,data:VKEGY6KVtgKApnV7N2e2cqy9erDWQ2fb88Gwcpp5th/t0VGp16KGDtGiuQXhY80j6dDIcQMd9bLHzqAzc4+i/WhmEPhiXUkGiEKuarMfvqNl1LBlXFCoIrUXMMSIqab9q+fE3ignVQapE/YZt9aniyvg1prcmBcwIy9rDoHkiTY006ux5CM+vX0F60ADX8Nf6Qmn/JncPxXgq2jYsBxjXPj7BwJaair/+nxrbVf0,iv:Elj1NDeR1fdIIjIbjvkV3BmcVAKjwdMfknuNxMXJsa4=,tag:AkXWQ8sTMLsd7a+MfRcF/w==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjMlRsWnkrREVaQitsWHMy + WHZFVG1qN25QbWFHcUxNS1Z0SFRDd1oxeG5RCi8wNUhkeWh2VjI4ZGowM1ExaExh + SE1yVGFTUHZadUdDL3pxaGdKTHQ0VTgKLS0tIHVNM2xlOFNNS3dFalJqZUtPODRn + b2NOTHpXSUVyaFRJNG5ONCt0TTVjOEkKYld7KN995QxdrGBVRYgCxO7kGwsiq+cp + iQJTjMdoFygIrTkgE5Rj89/GCiVe0+yAWJuQF7PEnC3cyq0M1g+fzw== + -----END AGE ENCRYPTED FILE----- + - recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPRFJCeXhwQVFSWmgzNHBu + SHlTTGtiRkI5bmhKa1B0QTZMY3FERmlUd0FBCk1vOUpydEFZUExpR2hpWm9mRHpE + dk9MQ042K0FpSVJ3dUlQcktGT2k1VjAKLS0tIHpGRmwzNE01YkV1TW94RkNmMjN4 + YnNXZUlta3NMVW9Cc3V2T0t4R01RSlkKNTW3gnF49BuPwF3jwciOYThJe+gJa0a6 + WKYt+aJuHi0a4y5rS/wfttij+hS5vYVNOrgfJ5bGinkNuAygA2hMOg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1dhzugelagj6vge5jjxwwn0522ngf7fhxn04sxy2tm8557rtme5tstprwnj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6MjZOR1dwb3RjZnlNNW4v + SzJnT1BRVktWNDI5S2Z2NnhQQzdNeS9ralI0CnN0SU9ESEV3ZCtRQmpZK3VZOGYx + Y3FVUy9zY3RZcGxyVmttVzFJL1haYWsKLS0tIENGRW1KZkpUdldOZWgzSXVoenpX + dTVpNUpWallSTzJ3cEZJTXk3c2t1czgKzJCwhMspzAsjzwSRdSPUoseEAsKp8HFy + cL9if92ar68HMHTdoy0Zvy+5AbxKUxgXZ2t8cDgkL8bNG5Ri2xYaUA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtNm5xUGkrK1dYd2ZtamFW + NXpNMEtvNTl3U3MzeVNSbVJOdGdlWGsxRHlZCllQVmNtYzBJNDc2Y0dmUlNsbTF5 + RHB4QWZ1VGNFVkx1Q0hNK3FDTTRrUlkKLS0tIG9hbldDeHk0YmVZV2IwMXNpYStU + Q29uVHBCb2pTeWVJVmVXbWpycnFneWMKnDmu5917dddV8vjO0L8OP3wXMjDi46Ro + b9eOY8l74jm4sTxyKNvnkEjD6iHn1t7f8J7HAbWrpZY+J0i77nrzQw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-11-23T09:05:51Z" + mac: ENC[AES256_GCM,data:Xnulo0681LtgH9SZt9DL3nd9bSDH+TCQDvbKdggVBJ66rxBiKmlbu5MAblAWqxbdZ6EelldaVeX9OaL2rYJoYbTWxzw2iuPieldp3Ah3PsTI2C8W+UD9KVHcB+3AMOmVmJZzFlZvTwyfPfZRNNb0HAijkN97P3fP0r1Iqf3YjiI=,iv:vhu38HM4e+PyyChXvI87LWSGtKQQiXUr4MKrI7kotzk=,tag:eNuQD74kUO+duqEXNbLJBw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.1 diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index d4fa331..45db3e1 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -1,4 +1,6 @@ /* +* Forwarding mails: Update the Sops-secrets in the machine directory, rebuild on the VM and deploy. +* Everything else should happen automatically but new redirects might take up to two hours due HRZ infrastructure. * Using the web admin interface: Set your SSH to do portforwarding of some local port to port 80 of the VM and * and use your personal admin account or create one using the fallback admin password. * Create users with mail boxes: Go to the admin interface and create them. @@ -9,6 +11,7 @@ { config, lib, + pkgs, ... }: let inherit @@ -26,6 +29,25 @@ in { type = str; description = "String containing the hashed fallback admin password"; }; + domains = mkOption { + type = listOf (lib.types.submodule { + options = { + domain = mkOption { + description = "Domain name that we serve. We also push its addresses to HRZ."; + type = strMatching "^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$"; #Regex from https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html + }; + allowlistPass = mkOption { + description = "Password file for the HRZ API that gets a list of mailaddresses that we serve"; + type = path; + }; + virt_aliases = mkOption { + description = "File path to a virtual alias file applicable for this domain"; + type = path; + default = "/dev/null"; # there might not be an alias file and reading an empty one works with our implementation + }; + }; + }); + }; }; config = mkIf cfg.enable { @@ -127,6 +149,32 @@ in { ]; }; + # 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. + # We here define what comes from the TOML-file and especially add "sieve.trusted.scripts.*" 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. + config.local-keys = + [ + "store.*" + "directory.*" + "tracer.*" + "server.*" + "!server.blocked-ip.*" + "authentication.fallback-admin.*" + "cluster.node-id" + "storage.data" + "storage.blob" + "storage.lookup" + "storage.fts" + "storage.directory" + "lookup.default.hostname" + "certificate.*" + ] # the default ones + ++ ["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'"; + authentication.fallback-admin = { user = "admin"; # see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH @@ -149,6 +197,42 @@ in { files = ["/root/.ssh/known_hosts"]; # for the backup server bragi }; + systemd = { + services = { + "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; + }; + }; + }; + }; # Backups services.borgbackup.jobs.mail = { paths = [ From 5a80d86bd384cbdda1a52c5a0cfd87256d5e5ff6 Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Feb 2025 16:16:12 +0100 Subject: [PATCH 05/10] Post mailaddresses to HRZ allowlist --- nixos/machines/kaalut/allowlistPass.yaml | 52 +++++++++++++++++++++ nixos/machines/kaalut/configuration.nix | 22 ++++++++- nixos/machines/kaalut/stalwartAdmin.yaml | 48 ++++++++++++++++++++ nixos/modules/mail.nix | 57 ++++++++++++++++++++++++ 4 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 nixos/machines/kaalut/allowlistPass.yaml create mode 100644 nixos/machines/kaalut/stalwartAdmin.yaml diff --git a/nixos/machines/kaalut/allowlistPass.yaml b/nixos/machines/kaalut/allowlistPass.yaml new file mode 100644 index 0000000..4d60823 --- /dev/null +++ b/nixos/machines/kaalut/allowlistPass.yaml @@ -0,0 +1,52 @@ +allowlistPass: + matheball: ENC[AES256_GCM,data:4y83ZJ4=,iv:+B1hTSGs5cskmUA9gLpRHPjhxzvwOrplB+lIbNUKtz4=,tag:ZsKA2A4ltbI3px1Z16EgvA==,type:str] + mathebau: ENC[AES256_GCM,data:ZlIv0MrCVtsyF3t9Gr/zcg==,iv:ZdBlnx4/zQZjT75ssB0osfDlWVerUe6yvwbMxlXpHZs=,tag:ytlNq7zP2WtPafcSQFZ6RQ==,type:str] + mathechor: ENC[AES256_GCM,data:d5KyoD/P8/j+poJSGF1nDA==,iv:ayKtvj4EEqUtMLi/7njbxuUql1A58WNi729svHtZju4=,tag:JqWoxxMN5mVN+gaQTmBv1Q==,type:str] + koma: ENC[AES256_GCM,data:bB7px1n5q1+++sctsmIMJg==,iv:DIJGpC9+JyFv3SU9dBVLdnEkRlZzY7DBRAL4zXSbpec=,tag:WaZUGvYtm+5ys2RsBNILog==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpWW9FZHEwejRaRER1MHJQ + VXgyaE1GQmhhNFh1dEtBNjRnZXVqWm5hV25vCjliank4KzFobEZtbitzaXBhT1F6 + cCtqeVorS1BLMmMzZkVVOEN6NERFdDAKLS0tIGkzUUt1NnBUWUJWTy9Pd2FIeTF0 + cDVaUHowSEpoRjR3Zm81Z1p5NlYzV1kKMRvC7+3TS5EKjWg/NPnbwvVIikxf+Bpa + zNo9jhw3GREMScBXOiarm+xgMZ1e2SRrLrUwfR4DiXI4uvg1Jk/tPg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRYk1LQTVDNGhHWXJZSmsy + NEZ0WTNlek4yVnRwL3BKNXYrcm84SzIvNlRZCjlDdXU1a2NRNUVHZmkyK2ltZ3pE + bmtmVE5TR1hBcVNhaTBGK2F6VWZ1d2MKLS0tIDVKcXhDbjBncFlsR3FzanRhWWQv + Um1jcExjN2RWbHhzY2ZpcWVTWE1IbHMKfRSAmfbk+JDWdhSTSg9GZ+lws5DOHv9T + ZO9nQV37X9zFD6sXDWaspG3sf4kJZUCbWjCTKyQL/xmh4+E8+CAXYw== + -----END AGE ENCRYPTED FILE----- + - recipient: age1dhzugelagj6vge5jjxwwn0522ngf7fhxn04sxy2tm8557rtme5tstprwnj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzOXBwTUF3ZXJCTFJOQjVC + bGplRDRCQVhtUEJPcnhENEF3UVVnbmVKNnprCjFOZW94ajI2d21RamZKT0xFMmtZ + ZzZFYjg3WDBmOVhlaFZyOW83M1NYVXcKLS0tIGltWUJGczNJS0pWTmxaZHU5Wi9t + TDRCdStocXRvLzBPUTd2blZFV0IyblkKjufZg39n/TI6BhGhIFNz4jplUx6u3/bo + NMbr9uJy/I1sdlfGNaheG/TIGOgFG1KqGkGdwpisU3gUD9uMUo1dvw== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzdDdsdW44ZlQyMzdJNmsv + aTIzVWRoSDhzamlqTDFOemZlc1JQMFdZbFJNCmVZbDVVaDBSVi8yTkdOQ1UySy9X + MlhXTzRvNWtqUzQxTlNqQ2RlN2J1OXMKLS0tIC9aZEZMVkFybnRTQmhpM1dzc1lt + bDdvdHc3Y1NmeE5WUzl3cXVRc3pmOUkK+9WueS1wDQDJlenec4jJCfynbPnuOFYR + HFsWmvEZJ+XhH6N9Q0phCHQgZGiR67FH6CHkCblmb6ZfZcWSEe1oTg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-01-05T13:49:19Z" + mac: ENC[AES256_GCM,data:i7t/Hb5aW0lIvPLk84geQ792uUGP25vX8FC7kK/3H19tz5i4zsIcvl1d+oB5gJ004gP5pRogcuKL1xHUUl+A0UXXNzRpxc0BBVZaxnIhjfPunORbmZeJQRP298tQpvYYqI/pGhjrlit37U9jecGf1l12Cgv97sGW42d2F+S2Soc=,iv:My21fMF3SEr6mg2+eh8KA6B8tzmQVEDy2BG3hfkafrU=,tag:xdU6j8ti8Z68rbiRxkj7Pw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.2 diff --git a/nixos/machines/kaalut/configuration.nix b/nixos/machines/kaalut/configuration.nix index 1b84e50..2134b42 100644 --- a/nixos/machines/kaalut/configuration.nix +++ b/nixos/machines/kaalut/configuration.nix @@ -10,6 +10,7 @@ # System configuration here services.mathebau-mail = { enable = true; + stalwartAdmin = config.sops.secrets.stalwartAdmin.path; # see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH stalwartAdminHash = "$argon2i$v=19$m=4096,t=3,p=1$d0hYOTkzclpzSmFTZUplWnhVeWE$I7q9uB19RWL0oZKaPlMPSlGfFp6FQ/vrx80FFKCsalg"; domains = [ @@ -40,7 +41,19 @@ vmNetwork.ipv4 = "192.168.0.17"; system.stateVersion = "24.05"; - sops.secrets = { + sops.secrets = let + allowlistSops = { + sopsFile = ./allowlistPass.yaml; + owner = "stalwart-mail"; + group = "stalwart-mail"; + mode = "0400"; + }; + in { + # Password for the HRZ API that gets a list of mailaddresses that we serve + "allowlistPass/matheball" = allowlistSops; + "allowlistPass/mathebau" = allowlistSops; + "allowlistPass/mathechor" = allowlistSops; + "allowlistPass/koma" = allowlistSops; # Virtual alias file "mathebau.aliases" = { sopsFile = ./mathebau.aliases.yaml; @@ -60,6 +73,13 @@ 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.yaml; + owner = "stalwart-mail"; + group = "stalwart-mail"; + mode = "0400"; + }; backupKey = { sopsFile = ./backupKey.yaml; owner = "root"; diff --git a/nixos/machines/kaalut/stalwartAdmin.yaml b/nixos/machines/kaalut/stalwartAdmin.yaml new file mode 100644 index 0000000..9fb24d8 --- /dev/null +++ b/nixos/machines/kaalut/stalwartAdmin.yaml @@ -0,0 +1,48 @@ +stalwartAdmin: ENC[AES256_GCM,data:4vpvxtFa2KiF3ojl+cw3ic/MI7UM9JQCQn76bidYvbW31zgF,iv:DtLAi68oQRf3U69uFK0Cz4qHMkxM6NnB3lVYft/DtqQ=,tag:HYm2mdpTuXNHdQIv2Rkwig==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxcTRqZXRoNTJCdFhQUG9o + Qmx2cVl0TWdaQzZZUThTOEpQdjIxVFh3eHhzCjlHWHhSYmM1ajYrdjl3Nm90TkRh + YWE3c0hJYzdFWXpZUGI0cHBQdThSWWsKLS0tIFh5M20wV2ZZbzllS1BNOGtaRUVF + MFN3bENrZ0tDMllJM1E5MWkyZ2thZEkKfZlUzE5t8K0oHZYOSVItvRJZP2MJlA7N + SLozGlpwCoZKWP6qAqP5jisTG/npQRhcqwkd7P39EytO2HXU9m8sJA== + -----END AGE ENCRYPTED FILE----- + - recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkVldRVmtPUzFxV0ltK0d2 + SHRqbXZCTW5wZUtZM0ZkL3lXOEJmVXdjMXdZCjE5MUUrSEhnWHRSOVhtWWQxdndv + ckUzTFl4ZXM5VHBTRlY3SzVsZWpxNUEKLS0tIEtpbTBhaWR1c3RhSW5nclZvMTdO + eTBYL1Q5cXNvTGkvQzJMWHZHaEZseVUK5w2MPZMquT0luq+tl2owLrrSBx9KPskS + FupcAZTcCo+YsemKLjJ6GlHch5x8Mw98NHS5h1AKxwZYtcfwg3lfbQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1dhzugelagj6vge5jjxwwn0522ngf7fhxn04sxy2tm8557rtme5tstprwnj + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpUitNeHNWOTVjWkF4YWhB + MnEwWDFnT0wyNUx3VmlQMmZTRmZRbXBGOVFvCmpoOHZZSXRweUtZaHZ6azF2Q3dK + NFBwa242U3JSVjhtOUlRTUZuakhkcXcKLS0tIEN5TGhMRFphdEpvcU5zTmVlTTJN + d2JRc2p4YmpuUHAycUoxc1FuZmxhemcKOgGyieFVS57tsvUtVooahqswYZH0Fi6+ + jxM6Ga/tIM/bZ/qSwYrNlNiz0XHm8/XFH2s8sxypDZ+NHGLs3zGjsw== + -----END AGE ENCRYPTED FILE----- + - recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBERTdvSTZ3eEVNbEZpUnQ2 + ZC85blRQVzgrckljcnZPeVhZWUxGd01tankwCjBCZHdWRnpoZkdRQWdoK0VmOFVy + VmpiOFkvNisrWmp2NE1kalB4dUhzdWsKLS0tIEJ6T1FsTFlIMUVWd3FwbEtldmlC + UjFHWHNZci8zRlFXNVpNNk5oSUNvaTQKW9T88GflSysJwqMnBrc/jZVwL/fRdg2a + 5XysXb/dCo4uNxLQit/KNSpINj7rAkf4Pk819DO6SKiIiuIJDXw9cA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-11-23T11:43:23Z" + mac: ENC[AES256_GCM,data:GZ1Q67n43WU3fDQd6SGsD2EZgoaq1mzh5biy42cx6FQWlveK5lhb0F2HUuWWv5zSHKpslEPD6odvkQmMNCRY8NsvT3+KBAnHHU0aHzM9AEV27cDL4x6oBvO52EMxsNCMm+fXPD1CubQxfbfvx/aIuqb1sovgKGgwf4u6yqIrHJ0=,iv:ExX+ySMXhF/c1w2IP7y8mdlcy8W9Zxiy6X67b2f4AeY=,tag:shxQJdaW3HsG6sNY+zDNCA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.1 diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 45db3e1..77b058a 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -25,6 +25,10 @@ in { options.services.mathebau-mail = { enable = mkEnableOption "mathebau mail service"; + stalwartAdmin = mkOption { + type = path; + description = "Path to a file that contains the stalwart fallback admin password encoded for HTTP Basic Auth"; + }; stalwartAdminHash = mkOption { type = str; description = "String containing the hashed fallback admin password"; @@ -198,7 +202,60 @@ in { }; systemd = { + timers."mailAllowlist" = { + wantedBy = ["timers.target"]; + timerConfig = { + OnBootSec = "1h"; # Run every hour + OnUnitActiveSec = "1h"; + RandomizedDelaySec = "10m"; # prevent overload on regular intervals + Unit = "mailAllowlist.service"; + }; + }; services = { + "mailAllowlist" = { + description = "Allowlist update: Post the mail addresses to the HRZ allowllist"; + script = let + scriptTemplate = { + domain, + allowlistPass, + ... + }: '' + 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. + ${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 + # 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. + # 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 + rm /tmp/addresses + ''; + in + lib.strings.concatStringsSep "" (map scriptTemplate cfg.domains); + 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 + 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; + }; + }; "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 From f0e584e239740b39e4f9ddf5f47943b2ccf94b50 Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Feb 2025 16:19:10 +0100 Subject: [PATCH 06/10] Add patch to allow alias files to redirect to their sender --- flake-module.nix | 41 +++++++++++++++++++++++++++++++++++++++-- nixos/modules/mail.nix | 4 ++++ patches/sieve-rs.patch | 27 +++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 patches/sieve-rs.patch diff --git a/flake-module.nix b/flake-module.nix index 7bc32ef..962d08b 100644 --- a/flake-module.nix +++ b/flake-module.nix @@ -1,4 +1,8 @@ -{inputs, ...}: { +{ + inputs, + lib, + ... +}: { # debug = true; # We only define machines config in this flake yet, so we only include # the module that builds these. This file might get fuller, if we need to @@ -55,8 +59,41 @@ config.permittedInsecurePackages = ["jitsi-meet-1.0.8043"]; overlays = [ - (_: _: { + (_: prev: { alias-to-sieve = inputs.alias-to-sieve.packages.x86_64-linux.default; # add custom package to convert alias files to sieve scripts on the stalwart machine + stalwart-mail = assert lib.assertMsg (prev.stalwart-mail.version == "0.11.6-unstable-2025-02-04") '' + 1. If the bug https://github.com/stalwartlabs/sieve/issues/11 is resolved to our satisfaction, try to remove this overlay. + 2. Check whether sieve-rs recieved new updates that our patch needs to be rebased upon. + 3. Check whether the sieve-rs patch below that exchanges the dependency needs updates. + 4. Then update the version comparison in this assert statement. + 5. Update the `cargoHash` by setting it to `lib.fakeHash` and then inserting the result. + 6. Check if we can get rid of alias-to-sieve when stalwart-mail has a builtin mail-forwarding feature. + ''; + # This override encapsulates the buildRustPackage function in a function that takes the arguments given by the nixpkgs-version of stalwart-mail + # and adds our patch to the arguments before handing the new arguments to buildRustPackage. + prev.stalwart-mail.override ( + let + rp = pkgs.rustPlatform; + in { + rustPlatform = + rp + // { + buildRustPackage = args: + rp.buildRustPackage ( + args + // rec { + cargoPatches = [ + # Let stalwart-mail depend on our own version of the sieve crate that does not have some “loop prevention” that disables redirects to the original sender. + # We want to redirect to sender if we simulate alias files and not doing so barely prevents loops in my opinion. + ./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="; + } + ); + }; + } + ); }) ]; }; diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 77b058a..f1861a2 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -1,4 +1,8 @@ /* +* Building: We patch our version of stalwart and thus need to built it locally. +* Be aware that this needs some hours, about 12Gb 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. * Everything else should happen automatically but new redirects might take up to two hours due HRZ infrastructure. * Using the web admin interface: Set your SSH to do portforwarding of some local port to port 80 of the VM and diff --git a/patches/sieve-rs.patch b/patches/sieve-rs.patch new file mode 100644 index 0000000..b706d03 --- /dev/null +++ b/patches/sieve-rs.patch @@ -0,0 +1,27 @@ +diff --git a/Cargo.lock b/Cargo.lock +index be36759b..b4316639 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -6404,8 +6404,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] + name = "sieve-rs" + 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" + dependencies = [ + "ahash 0.8.11", + "bincode", +diff --git a/Cargo.toml b/Cargo.toml +index f055474f..2b64c9ac 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -63,3 +63,7 @@ incremental = false + debug-assertions = false + overflow-checks = false + rpath = false ++ ++ ++[patch.crates-io] ++sieve-rs = { git = 'https://gitea.mathebau.de/fachschaft/sieve-rs.git' } + From 70b3a694c4512bcf8416dca14840c433caf7a36a Mon Sep 17 00:00:00 2001 From: Gonne Date: Tue, 25 Feb 2025 16:22:31 +0100 Subject: [PATCH 07/10] Submit mailing list mails to correct vm based on port forwarding and run allowlist job less often --- nixos/modules/mailman.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nixos/modules/mailman.nix b/nixos/modules/mailman.nix index 5cfa63d..f4ecd0e 100644 --- a/nixos/modules/mailman.nix +++ b/nixos/modules/mailman.nix @@ -35,7 +35,7 @@ in { proxy_interfaces = "130.83.2.184"; smtputf8_enable = "no"; # HRZ does not know SMTPUTF8 }; - 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) + 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) }; mailman = { enable = true; @@ -64,9 +64,9 @@ in { systemd.timers."mailAllowlist" = { wantedBy = ["timers.target"]; timerConfig = { - OnBootSec = "5m"; # Run every 5 minutes - OnUnitActiveSec = "5m"; - RandomizedDelaySec = "2m"; # prevent overload on regular intervals + OnBootSec = "1h"; # Run every hour + OnUnitActiveSec = "1h"; + RandomizedDelaySec = "10m"; # prevent overload on regular intervals Unit = "mailAllowlist.service"; }; }; From 361eed84afd235dba758f24e79749a9c2149c37f Mon Sep 17 00:00:00 2001 From: Gonne Date: Wed, 26 Feb 2025 14:35:46 +0100 Subject: [PATCH 08/10] Rename machine to Nyarlathotep --- .sops.yaml | 6 +++--- flake-module.nix | 4 ++-- .../{kaalut => nyarlathotep}/allowlistPass.yaml | 0 .../{kaalut => nyarlathotep}/backupKey.yaml | 0 .../{kaalut => nyarlathotep}/configuration.nix | 2 +- .../hardware-configuration.nix | 0 .../{kaalut => nyarlathotep}/koma.aliases.yaml | 0 .../{kaalut => nyarlathotep}/mathebau.aliases.yaml | 0 .../mathechor.aliases.yaml | 0 .../{kaalut => nyarlathotep}/stalwartAdmin.yaml | 0 nixos/modules/borgbackup.nix | 14 +++++++------- nixos/modules/mail.nix | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) rename nixos/machines/{kaalut => nyarlathotep}/allowlistPass.yaml (100%) rename nixos/machines/{kaalut => nyarlathotep}/backupKey.yaml (100%) rename nixos/machines/{kaalut => nyarlathotep}/configuration.nix (98%) rename nixos/machines/{kaalut => nyarlathotep}/hardware-configuration.nix (100%) rename nixos/machines/{kaalut => nyarlathotep}/koma.aliases.yaml (100%) rename nixos/machines/{kaalut => nyarlathotep}/mathebau.aliases.yaml (100%) rename nixos/machines/{kaalut => nyarlathotep}/mathechor.aliases.yaml (100%) rename nixos/machines/{kaalut => nyarlathotep}/stalwartAdmin.yaml (100%) diff --git a/.sops.yaml b/.sops.yaml index 7967e56..b80b8f3 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -5,7 +5,7 @@ keys: - &nyarlathotep age1s99d0vlj5qlm287n98jratql5fypvjrxxal0k5jl2aw9dcc8kyvqw5yyt4 - &bragi age1lqvgpmlemyg9095ujck64u59ma29656zs7a4yxgz4s6u5cld2ccss69jwe - &lobon age12nz7dtc0m5wasxm4r9crtkgwnzvauyfp0xh0n8z8jld0arn9ea9qe0agvn - - &kaalut age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a + - &nyarlathotep age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a creation_rules: - path_regex: nixos/machines/nyarlathotep/.* @@ -26,12 +26,12 @@ creation_rules: - *nerf - *gonne - *lobon - - path_regex: nixos/machines/kaalut/.* + - path_regex: nixos/machines/nyarlathotep/.* key_groups: - age: - *nerf - *gonne - - *kaalut + - *nyarlathotep # this is the catchall clause if nothing above machtes. Encrypt to users but not # to machines - key_groups: diff --git a/flake-module.nix b/flake-module.nix index 962d08b..789d7b8 100644 --- a/flake-module.nix +++ b/flake-module.nix @@ -69,8 +69,8 @@ 5. Update the `cargoHash` by setting it to `lib.fakeHash` and then inserting the result. 6. Check if we can get rid of alias-to-sieve when stalwart-mail has a builtin mail-forwarding feature. ''; - # This override encapsulates the buildRustPackage function in a function that takes the arguments given by the nixpkgs-version of stalwart-mail - # and adds our patch to the arguments before handing the new arguments to buildRustPackage. + # This override encapsulates the buildRustPackage function in a function that takes the arguments given by the nixpkgs-version of stalwart-mail + # and adds our patch to the arguments before handing the new arguments to buildRustPackage. prev.stalwart-mail.override ( let rp = pkgs.rustPlatform; diff --git a/nixos/machines/kaalut/allowlistPass.yaml b/nixos/machines/nyarlathotep/allowlistPass.yaml similarity index 100% rename from nixos/machines/kaalut/allowlistPass.yaml rename to nixos/machines/nyarlathotep/allowlistPass.yaml diff --git a/nixos/machines/kaalut/backupKey.yaml b/nixos/machines/nyarlathotep/backupKey.yaml similarity index 100% rename from nixos/machines/kaalut/backupKey.yaml rename to nixos/machines/nyarlathotep/backupKey.yaml diff --git a/nixos/machines/kaalut/configuration.nix b/nixos/machines/nyarlathotep/configuration.nix similarity index 98% rename from nixos/machines/kaalut/configuration.nix rename to nixos/machines/nyarlathotep/configuration.nix index 2134b42..6cbfd19 100644 --- a/nixos/machines/kaalut/configuration.nix +++ b/nixos/machines/nyarlathotep/configuration.nix @@ -37,7 +37,7 @@ ]; }; - networking.hostName = "kaalut"; + networking.hostName = "nyarlathotep"; vmNetwork.ipv4 = "192.168.0.17"; system.stateVersion = "24.05"; diff --git a/nixos/machines/kaalut/hardware-configuration.nix b/nixos/machines/nyarlathotep/hardware-configuration.nix similarity index 100% rename from nixos/machines/kaalut/hardware-configuration.nix rename to nixos/machines/nyarlathotep/hardware-configuration.nix diff --git a/nixos/machines/kaalut/koma.aliases.yaml b/nixos/machines/nyarlathotep/koma.aliases.yaml similarity index 100% rename from nixos/machines/kaalut/koma.aliases.yaml rename to nixos/machines/nyarlathotep/koma.aliases.yaml diff --git a/nixos/machines/kaalut/mathebau.aliases.yaml b/nixos/machines/nyarlathotep/mathebau.aliases.yaml similarity index 100% rename from nixos/machines/kaalut/mathebau.aliases.yaml rename to nixos/machines/nyarlathotep/mathebau.aliases.yaml diff --git a/nixos/machines/kaalut/mathechor.aliases.yaml b/nixos/machines/nyarlathotep/mathechor.aliases.yaml similarity index 100% rename from nixos/machines/kaalut/mathechor.aliases.yaml rename to nixos/machines/nyarlathotep/mathechor.aliases.yaml diff --git a/nixos/machines/kaalut/stalwartAdmin.yaml b/nixos/machines/nyarlathotep/stalwartAdmin.yaml similarity index 100% rename from nixos/machines/kaalut/stalwartAdmin.yaml rename to nixos/machines/nyarlathotep/stalwartAdmin.yaml diff --git a/nixos/modules/borgbackup.nix b/nixos/modules/borgbackup.nix index 9889238..03df3e2 100644 --- a/nixos/modules/borgbackup.nix +++ b/nixos/modules/borgbackup.nix @@ -76,13 +76,6 @@ in { path = "/var/lib/backups/ithaqua"; allowSubRepos = true; }; - kaalut = { - authorizedKeysAppendOnly = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFcAJkEXcvrDEQf1zRhBXLe1CSHOTooM3qy0KMfS9oug Kaalut Backup" - ]; - path = "/var/lib/backups/kaalut"; - allowSubRepos = true; - }; lobon = { authorizedKeysAppendOnly = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICEptjf1UWRlo6DG9alAIRwkSDUAVHwDKkHC6/DeYKzi Lobon Backup" @@ -90,6 +83,13 @@ in { path = "/var/lib/backups/lobon"; allowSubRepos = true; }; + nyarlathotep = { + authorizedKeysAppendOnly = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFcAJkEXcvrDEQf1zRhBXLe1CSHOTooM3qy0KMfS9oug nyarlathotep Backup" + ]; + path = "/var/lib/backups/nyarlathotep"; + allowSubRepos = true; + }; sanctamariamaterdei = { authorizedKeysAppendOnly = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH9Le5OI4ympQ0mQKYHmxgxGF598rzpD5VVpWK1mGfd8 Sanctamariamaterdei Backupsystem" diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index f1861a2..54644bd 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -307,7 +307,7 @@ in { # 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:kaluut"; # TODO for https://gitea.mathebau.de/Fachschaft/nixConfig/issues/33 + repo = "borg@192.168.1.11:nyarlathotep"; # TODO for https://gitea.mathebau.de/Fachschaft/nixConfig/issues/33 startAt = "daily"; user = "root"; group = "root"; From cc91339f800abc946258507c8808f54e70aaf013 Mon Sep 17 00:00:00 2001 From: Gonne Date: Thu, 27 Feb 2025 13:22:48 +0100 Subject: [PATCH 09/10] Address second round of review --- nixos/modules/mail.nix | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nixos/modules/mail.nix b/nixos/modules/mail.nix index 54644bd..4d7f950 100644 --- a/nixos/modules/mail.nix +++ b/nixos/modules/mail.nix @@ -24,18 +24,18 @@ mkEnableOption mkOption ; - inherit (lib.types) listOf strMatching str path; + inherit (lib.types) listOf strMatching nonEmptyStr path; cfg = config.services.mathebau-mail; in { options.services.mathebau-mail = { enable = mkEnableOption "mathebau mail service"; stalwartAdmin = mkOption { type = path; - description = "Path to a file that contains the stalwart fallback admin password encoded for HTTP Basic Auth"; + description = "Path to a file that contains the stalwart fallback admin password encoded for HTTP Basic Auth. Update together with the stalwartAdminHash and the pass store."; }; stalwartAdminHash = mkOption { - type = str; - description = "String containing the hashed fallback admin password"; + type = nonEmptyStr; + description = "String containing the hashed fallback admin password. Update together with the stalwartAdmin setting and the pass store."; }; domains = mkOption { type = listOf (lib.types.submodule { @@ -98,6 +98,7 @@ in { domains = ["fb04184.mathematik.tu-darmstadt.de" "imap.mathebau.de" "smtp.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 = { # TODO check if HRZ conforms to these standards and we can validate them strictly @@ -162,6 +163,7 @@ in { # We here define what comes from the TOML-file and especially add "sieve.trusted.scripts.*" 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. config.local-keys = [ "store.*" @@ -226,6 +228,7 @@ 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 # 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. @@ -260,6 +263,7 @@ in { RestrictSUIDSGID = true; }; }; + # 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 From 753b34592ca486048399dce37fd4d9b6f69269db Mon Sep 17 00:00:00 2001 From: Gonne Date: Wed, 26 Feb 2025 13:47:32 +0100 Subject: [PATCH 10/10] Increase root file system to make space for /tmp folder which needs lots of space during builds --- nixos/machines/nodens/hardware-configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/machines/nodens/hardware-configuration.nix b/nixos/machines/nodens/hardware-configuration.nix index 31b5450..ebb45bc 100644 --- a/nixos/machines/nodens/hardware-configuration.nix +++ b/nixos/machines/nodens/hardware-configuration.nix @@ -7,7 +7,7 @@ fileSystems."/" = { device = "root"; fsType = "tmpfs"; - options = ["size=1G" "mode=755"]; + options = ["size=10G" "mode=755"]; }; # Different than usual names in order to automount other VMs fileSystems."/persist" = {