summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common.nix2
-rw-r--r--hosts/kay/configuration.nix1
-rw-r--r--hosts/kay/modules/dns/5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone1
-rw-r--r--hosts/kay/modules/dns/ddns.nix7
-rw-r--r--hosts/kay/modules/dns/sinanmohd.com.zone21
-rw-r--r--hosts/kay/modules/hurricane.nix1
-rw-r--r--hosts/kay/modules/mail.nix103
-rw-r--r--hosts/kay/modules/www.nix13
-rw-r--r--hosts/kay/secrets.yaml8
-rw-r--r--modules/stalwart-mail.nix167
-rw-r--r--modules/userdata.nix2
-rw-r--r--pkgs/stalwart-mail-config.nix43
12 files changed, 361 insertions, 8 deletions
diff --git a/common.nix b/common.nix
index c2695ab..b9d2dab 100644
--- a/common.nix
+++ b/common.nix
@@ -7,6 +7,7 @@ in
{
disabledModules = [
"services/networking/pppd.nix"
+ "services/mail/stalwart-mail.nix"
];
imports = [
./modules/userdata.nix
@@ -15,6 +16,7 @@ in
./modules/dev.nix
./modules/pppd.nix
+ ./modules/stalwart-mail.nix
];
sops = {
diff --git a/hosts/kay/configuration.nix b/hosts/kay/configuration.nix
index 78385d1..1e264e2 100644
--- a/hosts/kay/configuration.nix
+++ b/hosts/kay/configuration.nix
@@ -7,6 +7,7 @@
./modules/www.nix
./modules/sftp.nix
./modules/acme.nix
+ ./modules/mail.nix
./modules/dns
./modules/sshfwd.nix
../../common.nix
diff --git a/hosts/kay/modules/dns/5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone b/hosts/kay/modules/dns/5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone
index 3991e1f..69b3524 100644
--- a/hosts/kay/modules/dns/5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone
+++ b/hosts/kay/modules/dns/5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone
@@ -11,3 +11,4 @@ $TTL 2d
IN NS ns1.sinanmohd.com.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR ns1.sinanmohd.com.
+7.3.3.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.sinanmohd.com.
diff --git a/hosts/kay/modules/dns/ddns.nix b/hosts/kay/modules/dns/ddns.nix
index 6d0a944..e6e417a 100644
--- a/hosts/kay/modules/dns/ddns.nix
+++ b/hosts/kay/modules/dns/ddns.nix
@@ -9,8 +9,11 @@
server 2001:470:ee65::1
zone sinanmohd.com.
- update delete sinanmohd.com. A
- update add sinanmohd.com. 180 A $4
+ update delete sinanmohd.com. A
+ update add sinanmohd.com. 180 A $4
+
+ update delete mail.sinanmohd.com. A
+ update add mail.sinanmohd.com. 180 A $4
send
EOF
diff --git a/hosts/kay/modules/dns/sinanmohd.com.zone b/hosts/kay/modules/dns/sinanmohd.com.zone
index 5833a2a..5fb9ca5 100644
--- a/hosts/kay/modules/dns/sinanmohd.com.zone
+++ b/hosts/kay/modules/dns/sinanmohd.com.zone
@@ -1,8 +1,8 @@
$ORIGIN sinanmohd.com.
$TTL 2d
-@ IN SOA ns1 sinan (
- 2024021100 ; serial
+@ IN SOA ns1 hostmaster (
+ 2024022500 ; serial
2h ; refresh
5m ; retry
1d ; expire
@@ -17,8 +17,25 @@ $TTL 2d
30 IN A 127.0.0.1
30 IN AAAA ::1
+ IN MX 10 mail
+
+ IN TXT "v=spf1 mx -all"
+_dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:postmaster@sinanmohd.com; ruf=mailto:postmaster@sinanmohd.com; adkim=s; aspf=s"
+
+ed25519._domainkey IN TXT "v=DKIM1; k=ed25519; p=EHk924AruF9Y0Xaf009rpRl+yGusjmjT1Zeho67BnDU="
+rsa._domainkey IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4HEqO63fSC0cUnJt9vAQBssTkPfT4QefmAK/1BtAIRIOdGakf7PI7p3A1ETgwfYxuHj7BUSzUtESsHMThbhB1Wko79+AR+5ZBDBmD8CE0dOnZfzeG8xIaGfYkaL4gana6YZWiBT2oi/CimJfc22wacF01SufOs4R8cDpy4BZIgDD/zfF4bFTORQ0vMSJQJkp1zdQelERDU5CEezgxgVYgoSmdEpgkhc23PJSyj4Z7hA69N0amsb3cVVrfVXcYvSqTK3S2vLLA89ws4CUjCCpUW40gVIP8QP6CqTL76936Oo7OVWgmV3Sn3wa8FMN6IATY+fbMlrdOMsPY5PauJyEoQIDAQAB"
+
ns1 IN AAAA 2001:470:ee65::1
+mail 30 IN A 127.0.0.1
+mail IN AAAA 2001:470:ee65::1337
+smtp IN CNAME @
+imap IN CNAME @
+mta-sts IN CNAME @
+
+_mta-sts IN TXT "v=STSv1; id=2024022500"
+_smtp._tls IN TXT "v=TLSRPTv1; rua=mailto:postmaster@sinanmohd.com"
+
www IN CNAME @
git IN CNAME @
bin IN CNAME @
diff --git a/hosts/kay/modules/hurricane.nix b/hosts/kay/modules/hurricane.nix
index ede8e8f..9e22bf5 100644
--- a/hosts/kay/modules/hurricane.nix
+++ b/hosts/kay/modules/hurricane.nix
@@ -33,6 +33,7 @@ in
(makeAddr prefix64 "1")
(makeAddr prefix48 "1")
+ (makeAddr prefix48 "1337")
];
};
diff --git a/hosts/kay/modules/mail.nix b/hosts/kay/modules/mail.nix
new file mode 100644
index 0000000..b255650
--- /dev/null
+++ b/hosts/kay/modules/mail.nix
@@ -0,0 +1,103 @@
+{ config, ... }: let
+ ipv6 = "2001:470:ee65::1337";
+ domain = config.userdata.domain;
+
+ username = config.userdata.user;
+ secret = "$argon2i$v=19$m=4096,t=3,p=1$SWV5aWU3YWUgZWFTNm9oc28gTGFvdDdlRG8ga2FTaWVjaDYgYWV0aDFHb28$O/sDv7oy9wUxFjvKoxB5o8ZnPvjYJo9DjX0C/AZQFF0";
+ email = [
+ "${username}@${domain}"
+ "sinanmohd@${domain}"
+ "me@${domain}"
+
+ "postmaster@${domain}"
+ "hostmaster@${domain}"
+ "admin@${domain}"
+ ];
+
+ credentials_directory = "/run/credentials/stalwart-mail.service";
+in {
+ networking.firewall.allowedTCPPorts = [
+ 25 # smto
+ 465 # submission
+ 587 # submissions
+ 993 # imap ssl
+ 4190 # managesieve
+ ];
+
+ sops.secrets = {
+ "mail.${domain}/dkim_rsa" = {};
+ "mail.${domain}/dkim_ed25519" = {};
+ };
+
+ services.stalwart-mail = {
+ enable = true;
+ loadCredential = [
+ "dkim_rsa:${config.sops.secrets."mail.${domain}/dkim_rsa".path}"
+ "dkim_ed25519:${config.sops.secrets."mail.${domain}/dkim_ed25519".path}"
+
+ "cert:${config.security.acme.certs.${domain}.directory}/fullchain.pem"
+ "key:${config.security.acme.certs.${domain}.directory}/key.pem"
+ ];
+
+ settings = {
+ macros = {
+ host = "mail.${domain}";
+ default_domain = domain;
+ default_directory = "in-memory";
+ default_store = "sqlite";
+ };
+
+ queue.outbound = {
+ ip-strategy = "ipv6_then_ipv4";
+ source-ip.v6 = "['${ipv6}']";
+ tls.starttls = "optional";
+ };
+ server.listener = {
+ smtp.bind = [ "[${ipv6}]:25" "0.0.0.0:25" ];
+ jmap.bind = [ "[::]:8034" ];
+ };
+
+ signature = {
+ rsa = {
+ private-key = "file://${credentials_directory}/dkim_rsa";
+ selector = "rsa";
+ set-body-length = true;
+ };
+ ed25519 = {
+ public-key = "EHk924AruF9Y0Xaf009rpRl+yGusjmjT1Zeho67BnDU=";
+ private-key = "file://${credentials_directory}/dkim_ed25519";
+ domain = "%{DEFAULT_DOMAIN}%";
+ selector = "ed25519";
+ headers = [ "From" "To" "Date" "Subject" "Message-ID" ];
+ algorithm = "ed25519-sha256";
+ canonicalization = "relaxed/relaxed";
+ set-body-length = true;
+ report = true;
+ };
+ };
+
+ certificate."default" = {
+ cert = "file://${credentials_directory}/cert";
+ private-key = "file://${credentials_directory}/key";
+ };
+
+ storage.blob = "fs";
+ store = {
+ fs.disable = false;
+ sqlite.disable = false;
+ };
+
+ directory."in-memory" = {
+ type = "memory";
+ options.subaddressing = true;
+
+ principals = [{
+ inherit email;
+ inherit secret;
+ name = username;
+ type = "admin";
+ }];
+ };
+ };
+ };
+}
diff --git a/hosts/kay/modules/www.nix b/hosts/kay/modules/www.nix
index a0b9c20..1447b1e 100644
--- a/hosts/kay/modules/www.nix
+++ b/hosts/kay/modules/www.nix
@@ -1,4 +1,4 @@
-{ config, pkgs, ... }:
+{ config, pkgs, lib, ... }:
let
domain = config.userdata.domain;
@@ -117,6 +117,17 @@ in
extraConfig = "add_header Content-Type text/html;";
};
};
+
+ "mta-sts.${domain}" = defaultOpts // {
+ locations."= /.well-known/mta-sts.txt".return = ''200 "${
+ lib.strings.concatStringsSep "\\n" [
+ "version: STSv1"
+ "mode: enforce"
+ "mx: mail.${domain}"
+ "max_age: 86400"
+ ]
+ }"'';
+ };
};
};
}
diff --git a/hosts/kay/secrets.yaml b/hosts/kay/secrets.yaml
index 11bebda..47be11b 100644
--- a/hosts/kay/secrets.yaml
+++ b/hosts/kay/secrets.yaml
@@ -10,6 +10,10 @@ dns: ENC[AES256_GCM,data:Pa6Oo7UFDqo5ZN+eyz9MKy0p4KU1ePTpWQ+R8PuSFO9JjFt/I86ru/q
matrix-sinanmohd.com:
key: ENC[AES256_GCM,data:xsSYua3g+ySUVBtfVZ2uZR4761MC5LeJGxmcgf+dWb5+tBSmgzAQL9FFcl7GLzhTmvlq13lARUr599wShS/C9IyMVGOOT9A8hxLFF9Kak64hmM7ERGrwbmzBY1mdTtvibJqzHaeybUVIMbDagczF54zpjDGLmdC5V84wduPFCndSA5FW+4Hhqw==,iv:KJtqrGNPgMDR6Sg/fOUzVAiwnPZwve9wpVfDQPc4g/c=,tag:E2jlbt5WbRA9wu16Lr69Bg==,type:str]
sliding_sync: ENC[AES256_GCM,data:ubFeb/OgYYHaIHVky6KS3icORbpqf7PO3p8bONA8mwG8vU1LB0TDqVm6vQTa8G9pe96JzJ8+IAgSZafG9PaEJc/Bpj53aWRFO3HEV0Pj,iv:P8VD8utVEwNoeQEZUdS2R9GuDe20nKiXYCfKJl0Id3E=,tag:VksV/4IaKN0C2g/alw6r4Q==,type:str]
+mail.sinanmohd.com:
+ dkim_rsa: ENC[AES256_GCM,data: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,iv:dPnpNUPSDiq5C14YzDM2K4mFHNRFgc6p+X3Zu33OH60=,tag:MhgfV3z1wcbAfpwZmVWczw==,type:str]
+ dkim_ed25519: ENC[AES256_GCM,data:bberg3vGG9M3iPH1aLA+wIU6KNnxHRZxpGU5zT5Gqo9lohQa1wBDXCwsP0JaSfg56dhh9ZxF5HFd4V0nUzL6QMIeiExGkZmtdluaqki3fwFCssILch9pWOuM71Q1d7vi1eIN5PrAuX+6m8bmQBd1JIR+Kbz8dQ==,iv:C7wEFU7/xCh8LzyKXHSzgTX/L9OkmGWTnl5A94GLogw=,tag:j+sYtzzGN9guWa6T+ZUzbw==,type:str]
+ sinan: ENC[AES256_GCM,data:F3lhwjf6dZpDSmU=,iv:TCIzQeUBqgjqc+/z3Hh1tYpm3OeLGLpVUDeo6ufP7/4=,tag:TXUI8noaK5jyLpo8D+94jQ==,type:str]
misc:
wireguard: ENC[AES256_GCM,data:kbUtxJv3xSmikJWgtu87TSo5N8tUb2BiH3dH3oOV36waYyXI3bp2aBeAl1k=,iv:yB4UIyMDNRS+JmSnt9XuBhNRTLz+k0FqkK4ofjosRto=,tag:BDSD9SfQuQppKT4+6Cu65w==,type:str]
sops:
@@ -36,8 +40,8 @@ sops:
OXgwSml4bkc1dnloNUFsRGFFcXFHc2cK26l2eiKbZUkogmAXoha6HTUs3YFKixYz
bTkpKKyOAIIin3YM975wwvkCuWNG4tbnHBHQFh5JGK2OEyLDXuV7Pg==
-----END AGE ENCRYPTED FILE-----
- lastmodified: "2024-02-01T06:10:26Z"
- mac: ENC[AES256_GCM,data:6Gow3dOvqseuuNbpztmm3yNU+6DKo+2LPqigO1cDhmKB509RN/T9GqDQEk/uC/aOyYeYSWrQY3EzZYOXiXgyiH2hurYV8WXGAAjssXog9YaVcC+OiXXv2zDRV8o8VKigc0hlrZJuN8FeL0qxrorojBft0QR/6JhGpV+s1jvS/8o=,iv:wV/WKfl2HPFHX3aoIdMpuK5frVs9imeO6LI0igYi2+Q=,tag:IXs92PzvwQM3FGaHW/qU8Q==,type:str]
+ lastmodified: "2024-02-25T04:23:28Z"
+ mac: ENC[AES256_GCM,data:SUFBHKTM2tQHX1Xtta3spl/GaaNrIAcNrLFzKzqb2ki3FhXnLLYu0wD+IBxuj1nxICn9TDprHFdcDenfFPV1mYWtmXLmWMeDcIGKXedYex2nakdlIYngGiLkEseuehft46YtoEqLJVksBFoLKmywRi+/ZGux/heSIyD14Toxb3Q=,iv:dqYGObF1SV3VBxSZtrggRdD1ROqvlp7tn8xLdNuDxx4=,tag:N/4L6NgIqYKQ8IbpFGru2g==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1
diff --git a/modules/stalwart-mail.nix b/modules/stalwart-mail.nix
new file mode 100644
index 0000000..ebeedd9
--- /dev/null
+++ b/modules/stalwart-mail.nix
@@ -0,0 +1,167 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.stalwart-mail;
+ configFormat = pkgs.formats.toml { };
+ configFile = configFormat.generate "stalwart-mail.toml" cfg.settings;
+ dataDir = "/var/lib/stalwart-mail";
+
+ readTOML =
+ path:
+ builtins.fromTOML (builtins.unsafeDiscardStringContext (lib.readFile path));
+ recursiveUpdateList =
+ attrList:
+ lib.lists.foldr (a1: a2: lib.attrsets.recursiveUpdate a1 a2) {} attrList;
+ mkOverrideRec =
+ priority:
+ content:
+ if lib.isAttrs content then
+ lib.mapAttrs (_: v: mkOverrideRec priority v) content
+ else
+ lib.mkOverride priority content;
+ mkOptionDefaultRec = mkOverrideRec 1500;
+
+ cfgPkg = pkgs.callPackage ../pkgs/stalwart-mail-config.nix {};
+ cfgFiles = (readTOML "${cfgPkg}/config.toml").include.files;
+ settingsDefault = recursiveUpdateList (map (path: readTOML path) cfgFiles);
+in {
+ options.services.stalwart-mail = {
+ enable = mkEnableOption (mdDoc "the Stalwart all-in-one email server");
+ package = mkPackageOption pkgs "stalwart-mail" { };
+
+ loadCredential = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ default = [];
+ example = [ "dkim.private:/path/to/stalwart.private" ];
+ description = lib.mdDoc ''
+ This can be used to pass secrets to the systemd service without adding them to
+ the nix store.
+ See the LoadCredential section of systemd.exec manual for more information.
+ '';
+ };
+
+ settings = mkOption {
+ inherit (configFormat) type;
+ default = { };
+ description = mdDoc ''
+ Configuration options for the Stalwart email server.
+ See <https://stalw.art/docs/category/configuration> for available options.
+
+ By default, the module is configured to store everything locally.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ # set the default upstream settings
+ # assumptions
+ # 1. ./config.toml exists and only containts include.files and macros
+ # 2. no other files containts include.files
+ services.stalwart-mail.settings = mkOptionDefaultRec
+ (lib.attrsets.recursiveUpdate settingsDefault {
+ macros.base_path = dataDir;
+ server.run-as.user = {};
+ server.run-as.group = {};
+ global.tracing.method = "stdout";
+ # outliers as of v0.6.0
+ acme."letsencrypt".cache = "${cfg.settings.macros.base_path}/acme";
+ });
+
+ assertions = let
+ m = cfg.settings.macros;
+
+ mkMacroMessage =
+ opt:
+ "config.stalwart-mail.settings.macros.${opt} can not be empty";
+ in [
+ {
+ assertion = m ? host
+ && m.host != ""
+ && m.host != null;
+ message = mkMacroMessage "host";
+ }
+ {
+ assertion = m ? default_domain
+ && m.default_domain != ""
+ && m.default_domain != null;
+ message = mkMacroMessage "default_domain";
+ }
+ {
+ assertion = m ? default_directory
+ && m.default_directory != ""
+ && m.default_directory != null;
+ message = mkMacroMessage "default_directory";
+ }
+ {
+ assertion = m ? default_store &&
+ m.default_store != ""
+ && m.default_store != null;
+ message = mkMacroMessage "default_store";
+ }
+ ];
+
+ systemd.services.stalwart-mail = {
+ wantedBy = [ "multi-user.target" ];
+ after = [ "local-fs.target" "network.target" ];
+
+ serviceConfig = {
+ ExecStart =
+ "${cfg.package}/bin/stalwart-mail --config=${configFile}";
+
+ # Base from template resources/systemd/stalwart-mail.service
+ Type = "simple";
+ LimitNOFILE = 65536;
+ KillMode = "process";
+ KillSignal = "SIGINT";
+ Restart = "on-failure";
+ RestartSec = 5;
+ StandardOutput = "journal";
+ StandardError = "journal";
+ SyslogIdentifier = "stalwart-mail";
+
+ DynamicUser = true;
+ User = "stalwart-mail";
+ StateDirectory = "stalwart-mail";
+ LoadCredential = cfg.loadCredential;
+
+ # Bind standard privileged ports
+ AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
+ CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
+
+ # Hardening
+ DeviceAllow = [ "" ];
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ PrivateDevices = true;
+ PrivateUsers = false; # incompatible with CAP_NET_BIND_SERVICE
+ ProcSubset = "pid";
+ PrivateTmp = true;
+ ProtectClock = true;
+ ProtectControlGroups = true;
+ ProtectHome = true;
+ ProtectHostname = true;
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ ProtectProc = "invisible";
+ ProtectSystem = "strict";
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ SystemCallArchitectures = "native";
+ SystemCallFilter = [ "@system-service" "~@privileged" ];
+ UMask = "0077";
+ };
+ };
+
+ # Make admin commands available in the shell
+ environment.systemPackages = [ cfg.package ];
+ };
+
+ meta = {
+ maintainers = with maintainers; [ happysalada pacien ];
+ };
+}
diff --git a/modules/userdata.nix b/modules/userdata.nix
index 46c7377..00f0e13 100644
--- a/modules/userdata.nix
+++ b/modules/userdata.nix
@@ -18,7 +18,7 @@ in
};
email = mkOption {
type = types.str;
- default = "sinan@firemail.cc";
+ default = "sinan@${cfg.domain}";
description = mdDoc "Owner's email";
};
};
diff --git a/pkgs/stalwart-mail-config.nix b/pkgs/stalwart-mail-config.nix
new file mode 100644
index 0000000..77fc366
--- /dev/null
+++ b/pkgs/stalwart-mail-config.nix
@@ -0,0 +1,43 @@
+{ lib,
+ stdenvNoCC,
+ fetchzip,
+ stalwart-mail,
+}:
+
+stdenvNoCC.mkDerivation {
+ pname = stalwart-mail.pname + "-config";
+ version = stalwart-mail.version;
+
+ src = let
+ rev = stalwart-mail.src.rev;
+ owner = stalwart-mail.src.owner;
+ repo = stalwart-mail.src.repo;
+ in fetchzip {
+ url = "https://github.com/${owner}/${repo}/raw/${rev}/resources/config.zip";
+ # gives us a chance to manually verify config changes, if not use
+ # stalwart-mail.src
+ hash = "sha256-ji7+f3BGzVEb9gp5BXCStPR4/Umy93OTMA+DhYI/azk=";
+ };
+
+ outputs = [ "out" ];
+ patchPhase = ''
+ # TODO: remove me
+ # toml spec violation, author said this will be fixed on the next realase
+ sed -e 's/\[storage.fts\]//g' -e 's/default-language = "en"//g' \
+ -i ./common/store.toml
+
+ # outliers as of 0.6.0
+ # smtp/signature.toml:#public-key = "file://%{BASE_PATH}%/etc/dkim/%{DEFAULT_DOMAIN}%.cert"
+ # smtp/signature.toml:private-key = "file://%{BASE_PATH}%/etc/dkim/%{DEFAULT_DOMAIN}%.key"
+ # common/tls.toml:cache = "%{BASE_PATH}%/etc/acme"
+ find -type f \
+ -name '*.toml' \
+ -exec sed 's=%{BASE_PATH}%/etc=${placeholder "out"}=g' -i {} \;
+ '';
+ installPhase = "cp -r ./ $out";
+
+ meta = stalwart-mail.meta // {
+ description = "Configs for" + stalwart-mail.meta.description;
+ maintainers = with lib.maintainers; [ sinanmohd ];
+ };
+}