commit eab5b8088f1762429f8fb43ceb35cdfd33ca484a
parent 7c261696367e639d615553ffb643350858289cdb
Author: Leah (ctucx) <leah@ctu.cx>
Date: Sun, 19 Jun 2022 10:39:38 +0200
parent 7c261696367e639d615553ffb643350858289cdb
Author: Leah (ctucx) <leah@ctu.cx>
Date: Sun, 19 Jun 2022 10:39:38 +0200
machines/osterei/maddy: use nixos module
4 files changed, 245 insertions(+), 294 deletions(-)
A
|
228
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D
|
102
-------------------------------------------------------------------------------
D
|
186
-------------------------------------------------------------------------------
diff --git a/machines/osterei/configuration.nix b/machines/osterei/configuration.nix @@ -7,22 +7,33 @@ ../../configurations/common.nix ../../configurations/notify-failure.nix - ../../configurations/services/prometheus-node-exporter.nix + # dns server ../../configurations/services/bind + # monitoring + ../../configurations/services/prometheus-node-exporter.nix + ./prometheus.nix + ./grafana + ./fritzbox-exporter.nix + ./box-availablilty-checker.nix + + # git server (gitolite+stagit) ./git + ./syncthing.nix + + # communication ./matrix-synapse.nix ./pleroma - ./maddy - ./prometheus.nix - ./grafana + ./maddy.nix + + # cal- and card-dav server ./radicale.nix + + # websites ./oeffisearch.nix ./oeffi-web.nix - ./fritzbox-exporter.nix ./websites - ./box-availablilty-checker.nix ]; age.secrets.restic-server-lollo.file = ../../secrets/restic-server/lollo.age;
diff --git a/machines/osterei/maddy.nix b/machines/osterei/maddy.nix @@ -0,0 +1,228 @@ +{ config, lib, pkgs, ... }: + +{ + + users.groups.maddy = {}; + users.users.maddy = { + isSystemUser = true; + home = "/var/lib/maddy"; + group = "maddy"; + extraGroups = [ "nginx" ]; + }; + + age.secrets.restic-maddy.file = ../../secrets/osterei/restic/maddy.age; + + restic-backups.maddy = { + user = "maddy"; + passwordFile = config.age.secrets.restic-maddy.path; + paths = [ "/var/lib/maddy" ]; + }; + + security.acme.certs."osterei.ctu.cx".reloadServices = [ "maddy.service" ]; + + networking.firewall.allowedTCPPorts = [ + 25 + 143 + 465 + 587 + 993 + ]; + + services.maddy = { + enable = true; + user = "maddy"; + group = "maddy"; + hostname = "osterei.ctu.cx"; + primaryDomain = "ctu.cx"; + localDomains = [ + "$(hostname)" + "$(primary_domain)" + "antifa.jetzt" + "thein.ovh" + "ctucx.de" + "trans-agenda.de" + ]; + + config = '' + log syslog + + tls file /var/lib/acme/osterei.ctu.cx/fullchain.pem /var/lib/acme/osterei.ctu.cx/key.pem + + # ---------------------------------------------------------------------------- + # Local storage & authentication + + # pass_table provides local hashed passwords storage for authentication of + # users. It can be configured to use any "table" module, in default + # configuration a table in SQLite DB is used. + # Table can be replaced to use e.g. a file for passwords. Or pass_table module + # can be replaced altogether to use some external source of credentials (e.g. + # PAM, /etc/shadow file). + # + # If table module supports it (sql_table does) - credentials can be managed + # using 'maddyctl creds' command. + + auth.pass_table local_authdb { + table sql_table { + driver sqlite3 + dsn credentials.db + table_name passwords + } + } + + # imapsql module stores all indexes and metadata necessary for IMAP using a + # relational database. It is used by IMAP endpoint for mailbox access and + # also by SMTP & Submission endpoints for delivery of local messages. + # + # IMAP accounts, mailboxes and all message metadata can be inspected using + # imap-* subcommands of maddyctl utility. + + storage.imapsql local_mailboxes { + driver sqlite3 + dsn imapsql.db + } + + # ---------------------------------------------------------------------------- + # SMTP endpoints + message routing + + msgpipeline local_routing { + dmarc yes + check { + require_mx_record + dkim + spf { + permerr_action ignore + } + } + + # Insert handling for special-purpose local domains here. + # e.g. + # destination lists.example.org { + # deliver_to lmtp tcp://127.0.0.1:8024 + # } + + destination postmaster $(local_domains) { + modify { + replace_rcpt static { + entry postmaster postmaster@$(primary_domain) + entry leon@thein.ovh leah@ctu.cx + entry leah@thein.ovh leah@ctu.cx + entry leah@antifa.jetzt leah@ctu.cx + } + + # Implement plus-address notation. + replace_rcpt regexp "(.+)\+(.+)@(.+)" "$1@$3" + + replace_rcpt regexp "(.+)@ctucx.de" "leah@ctu.cx" + replace_rcpt regexp "(.+)@ctu.cx" "leah@ctu.cx" + } + + deliver_to &local_mailboxes + } + + default_destination { + reject 550 5.1.1 "User doesn't exist" + } + } + + smtp tcp://0.0.0.0:25 { + limits { + # Up to 20 msgs/sec across max. 10 SMTP connections. + all rate 20 1s + all concurrency 10 + } + + source $(local_domains) { + reject 501 5.1.8 "Use Submission for outgoing SMTP" + } + + default_source { + destination postmaster $(local_domains) { + deliver_to &local_routing + } + + default_destination { + reject 550 5.1.1 "User doesn't exist" + } + } + } + + submission tls://0.0.0.0:465 tcp://0.0.0.0:587 { + limits { + # Up to 50 msgs/sec across any amount of SMTP connections. + all rate 50 1s + } + + auth &local_authdb + + source $(local_domains) { + destination postmaster $(local_domains) { + deliver_to &local_routing + } + + default_destination { + modify { + dkim $(primary_domain) $(local_domains) default { + newkey_algo ed25519 + } + } + deliver_to &remote_queue + } + } + + default_source { + reject 501 5.1.8 "Non-local sender domain" + } + } + + target.remote outbound_delivery { + limits { + # Up to 20 msgs/sec across max. 10 SMTP connections + # for each recipient domain. + destination rate 20 1s + destination concurrency 10 + } + + mx_auth { + dane + + mtasts { + cache fs + fs_dir mtasts_cache/ + } + + local_policy { + min_tls_level encrypted + min_mx_level none + } + } + } + + target.queue remote_queue { + target &outbound_delivery + max_parallelism 16 + max_tries 4 + + autogenerated_msg_domain $(primary_domain) + + bounce { + destination postmaster $(local_domains) { + deliver_to &local_routing + } + + default_destination { + reject 550 5.0.0 "Refusing to send DSNs to non-local addresses" + } + } + } + + # ---------------------------------------------------------------------------- + # IMAP endpoints + + imap tls://0.0.0.0:993 tcp://0.0.0.0:143 { + auth &local_authdb + storage &local_mailboxes + } + ''; + }; + +}
diff --git a/machines/osterei/maddy/default.nix b/machines/osterei/maddy/default.nix @@ -1,102 +0,0 @@ -{ config, lib, pkgs, ... }: - -let - maddyConfig = ./maddy.conf; - -in { - - users.groups.maddy = {}; - users.users.maddy = { - isSystemUser = true; - home = "/var/lib/maddy"; - group = "maddy"; - extraGroups = [ "nginx" ]; - }; - - age.secrets.restic-maddy.file = ../../../secrets/osterei/restic/maddy.age; - - restic-backups.maddy = { - user = "maddy"; - passwordFile = config.age.secrets.restic-maddy.path; - paths = [ "/var/lib/maddy" ]; - }; - - security.acme.certs."osterei.ctu.cx".reloadServices = [ "maddy.service" ]; - - systemd.services.maddy = { - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - serviceConfig = { - Type = "notify"; - NotifyAccess = "main"; - - User = "maddy"; - Group = "maddy"; - - WorkingDirectory = "/var/lib/maddy"; - ConfigurationDirectory = "maddy"; - RuntimeDirectory = "maddy"; - StateDirectory = "maddy"; - LogsDirectory = "maddy"; - ReadWritePaths = "/var/lib/maddy"; - - PrivateTmp = true; - ProtectHome = true; - ProtectSystem = "strict"; - ProtectKernelTunables = true; - ProtectHostname = true; - ProtectClock = true; - ProtectControlGroups = true; - RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; - - # Additional sandboxing. You need to disable all of these options - # for privileged helper binaries (for system auth) to work correctly. - NoNewPrivileges = true; - PrivateDevices = true; - RestrictSUIDSGID = true; - ProtectKernelModules = true; - MemoryDenyWriteExecute = true; - RestrictNamespaces = true; - RestrictRealtime = true; - LockPersonality = true; - - # Graceful shutdown with a reasonable timeout. - TimeoutStopSec = "7s"; - KillMode = "mixed"; - KillSignal = "SIGTERM"; - - # Required to bind on ports lower than 1024. - AmbientCapabilities = "CAP_NET_BIND_SERVICE"; - CapabilityBoundingSet = "CAP_NET_BIND_SERVICE"; - - # Force all files created by maddy to be only readable by it. - UMask = 0027; - - # Bump FD limitations. Even idle mail server can have a lot of FDs open (think - # of idle IMAP connections, especially ones abandoned on the other end and - # slowly timing out). - LimitNOFILE = 131072; - - # Limit processes count to something reasonable to - # prevent resources exhausting due to big amounts of helper - # processes launched. - LimitNPROC = 512; - - # Restart server on any problem. - Restart = "on-failure"; - # ... Unless it is a configuration problem. - RestartPreventExitStatus = 2; - - ExecStart = "${pkgs.maddy}/bin/maddy -config ${maddyConfig}"; - }; - }; - - networking.firewall.allowedTCPPorts = [ - 25 - 143 - 465 - 587 - 993 - ]; - -}
diff --git a/machines/osterei/maddy/maddy.conf b/machines/osterei/maddy/maddy.conf @@ -1,186 +0,0 @@ -## maddy 0.4 - default configuration file - -log syslog - -# ---------------------------------------------------------------------------- -# Base variables -$(hostname) = osterei.ctu.cx -$(primary_domain) = ctu.cx -$(local_domains) = $(hostname) $(primary_domain) antifa.jetzt thein.ovh ctucx.de trans-agenda.de - -tls file /var/lib/acme/osterei.ctu.cx/fullchain.pem /var/lib/acme/osterei.ctu.cx/key.pem - -# ---------------------------------------------------------------------------- -# Local storage & authentication - -# pass_table provides local hashed passwords storage for authentication of -# users. It can be configured to use any "table" module, in default -# configuration a table in SQLite DB is used. -# Table can be replaced to use e.g. a file for passwords. Or pass_table module -# can be replaced altogether to use some external source of credentials (e.g. -# PAM, /etc/shadow file). -# -# If table module supports it (sql_table does) - credentials can be managed -# using 'maddyctl creds' command. - -auth.pass_table local_authdb { - table sql_table { - driver sqlite3 - dsn credentials.db - table_name passwords - } -} - -# imapsql module stores all indexes and metadata necessary for IMAP using a -# relational database. It is used by IMAP endpoint for mailbox access and -# also by SMTP & Submission endpoints for delivery of local messages. -# -# IMAP accounts, mailboxes and all message metadata can be inspected using -# imap-* subcommands of maddyctl utility. - -storage.imapsql local_mailboxes { - driver sqlite3 - dsn imapsql.db -} - -# ---------------------------------------------------------------------------- -# SMTP endpoints + message routing - -hostname $(hostname) - -msgpipeline local_routing { - dmarc yes - check { - require_mx_record - dkim - spf - } - - # Insert handling for special-purpose local domains here. - # e.g. - # destination lists.example.org { - # deliver_to lmtp tcp://127.0.0.1:8024 - # } - - destination postmaster $(local_domains) { - modify { - replace_rcpt static { - entry postmaster postmaster@$(primary_domain) - entry leon@thein.ovh leah@ctu.cx - entry leah@thein.ovh leah@ctu.cx - entry leah@antifa.jetzt leah@ctu.cx - } - - # Implement plus-address notation. - replace_rcpt regexp "(.+)\+(.+)@(.+)" "$1@$3" - - replace_rcpt regexp "(.+)@ctucx.de" "leah@ctu.cx" - replace_rcpt regexp "(.+)@ctu.cx" "leah@ctu.cx" - } - - deliver_to &local_mailboxes - } - - default_destination { - reject 550 5.1.1 "User doesn't exist" - } -} - -smtp tcp://0.0.0.0:25 { - limits { - # Up to 20 msgs/sec across max. 10 SMTP connections. - all rate 20 1s - all concurrency 10 - } - - source $(local_domains) { - reject 501 5.1.8 "Use Submission for outgoing SMTP" - } - - default_source { - destination postmaster $(local_domains) { - deliver_to &local_routing - } - - default_destination { - reject 550 5.1.1 "User doesn't exist" - } - } -} - -submission tls://0.0.0.0:465 tcp://0.0.0.0:587 { - limits { - # Up to 50 msgs/sec across any amount of SMTP connections. - all rate 50 1s - } - - auth &local_authdb - - source $(local_domains) { - destination postmaster $(local_domains) { - deliver_to &local_routing - } - - default_destination { - modify { - dkim $(primary_domain) $(local_domains) default { - newkey_algo ed25519 - } - } - deliver_to &remote_queue - } - } - - default_source { - reject 501 5.1.8 "Non-local sender domain" - } -} - -target.remote outbound_delivery { - limits { - # Up to 20 msgs/sec across max. 10 SMTP connections - # for each recipient domain. - destination rate 20 1s - destination concurrency 10 - } - - mx_auth { - dane - - mtasts { - cache fs - fs_dir mtasts_cache/ - } - - local_policy { - min_tls_level encrypted - min_mx_level none - } - } -} - -target.queue remote_queue { - target &outbound_delivery - max_parallelism 16 - max_tries 4 - - autogenerated_msg_domain $(primary_domain) - - bounce { - destination postmaster $(local_domains) { - deliver_to &local_routing - } - - default_destination { - reject 550 5.0.0 "Refusing to send DSNs to non-local addresses" - } - } -} - -# ---------------------------------------------------------------------------- -# IMAP endpoints - -imap tls://0.0.0.0:993 tcp://0.0.0.0:143 { - auth &local_authdb - storage &local_mailboxes -}