From a2c85e365fdeea31bed4dd5d137e5ff8352509e9 Mon Sep 17 00:00:00 2001 From: Magic_RB Date: Tue, 13 Jun 2023 23:05:53 +0200 Subject: [PATCH] Add the email containers Signed-off-by: Magic_RB --- flake.nix | 3 + nixng/containers/email/dovecot.nix | 87 ++++++++++++ nixng/containers/email/getmail/default.nix | 79 +++++++++++ nixng/containers/email/postfix/default.nix | 128 ++++++++++++++++++ .../email/postfix/master_config.nix | 27 ++++ 5 files changed, 324 insertions(+) create mode 100644 nixng/containers/email/dovecot.nix create mode 100644 nixng/containers/email/getmail/default.nix create mode 100644 nixng/containers/email/postfix/default.nix create mode 100644 nixng/containers/email/postfix/master_config.nix diff --git a/flake.nix b/flake.nix index 09ae101..057f126 100644 --- a/flake.nix +++ b/flake.nix @@ -53,6 +53,9 @@ nixng/containers/matrix/heisenbridge nixng/containers/matrix/synapse nixng/containers/website + nixng/containers/email/getmail + nixng/containers/email/dovecot.nix + nixng/containers/email/postfix nixng/containers/ds3os overlays/udp-over-tcp.nix overlays/emacsclient-remote diff --git a/nixng/containers/email/dovecot.nix b/nixng/containers/email/dovecot.nix new file mode 100644 index 0000000..419e42e --- /dev/null +++ b/nixng/containers/email/dovecot.nix @@ -0,0 +1,87 @@ +{ inputs, ... }: +{ + flake.nixngConfigurations.dovecot = inputs.nixng.nglib.makeSystem { + system = "x86_64-linux"; + name = "ra-systems-dovecot"; + inherit (inputs) nixpkgs; + config = + { pkgs, ... }: + { + config = { + dumb-init = { + enable = true; + type.services = {}; + }; + + services.dovecot = { + enable = true; + package = pkgs.dovecot; + config = { + protocols = "imap lmtp"; + + # auth + ssl = "no"; + disable_plaintext_auth = "no"; + auth_mechanisms = "plain login"; + + mail_location = "maildir:/maildir/%u"; + + protocol."imap" = { }; + protocol."lmtp" = { + mail_plugins = [ "sieve" ]; + }; + + plugin."" = { + sieve = "/mail-configuration/entry.sieve"; + }; + + mail_plugin_dir = pkgs.symlinkJoin { + name = "dovecot-modules"; + paths = map (pkg: "${pkg}/lib/dovecot") ([ pkgs.dovecot pkgs.dovecot_pigeonhole ]); + }; + + # Optimizations: + # dotlock_use_excl = true; + maildir_copy_with_hardlinks = true; + + lda_mailbox_autocreate = "yes"; + lmtp_save_to_detail_mailbox = "yes"; + service."lmtp" = { + inet_listener."lmtp" = { + address = [ "127.0.0.1" ]; + port = 24; + }; + }; + + service."imap-login" = { + inet_listener."imap" = { + port = 143; + }; + + # inet_listener."imaps" = { + # port = 993; + # ssl = "yes"; + # }; + }; + + # Authentication configuration: + auth_debug = true; + log_path = "/proc/self/fd/1"; + info_log_path = "/proc/self/fd/1"; + debug_log_path = "/proc/self/fd/1"; + + passdb."" = { + driver = "passwd-file"; + args = "scheme=plain username_format=%u /secrets/passwd.dovecot"; + }; + userdb."" = { + driver = "passwd-file"; + args = "username_format=%u /secrets/passwd.dovecot"; + default_fields = "uid=vmail gid=vmail home=/maildir/%u"; + }; + }; + }; + }; + }; + }; +} diff --git a/nixng/containers/email/getmail/default.nix b/nixng/containers/email/getmail/default.nix new file mode 100644 index 0000000..8569a1a --- /dev/null +++ b/nixng/containers/email/getmail/default.nix @@ -0,0 +1,79 @@ +{ inputs, config, ... }: +let + config' = config; +in +{ + flake.nixngConfigurations.getmail = inputs.nixng.nglib.makeSystem { + system = "x86_64-linux"; + name = "ra-systems-getmail"; + inherit (inputs) + nixpkgs; + config = + { pkgs, config, ... }: + { + config = { + dumb-init = { + enable = true; + type.services = {}; + }; + + users.users."vmail" = { + uid = config.ids.uids.vmail; + description = "vmail user."; + group = "vmail"; + shell = "${pkgs.bash}/bin/bash"; + }; + users.groups."vmail" = { + gid = config.ids.gids.vmail; + }; + + init.services.getmail = { + shutdownOnExit = true; + script = + let + pkgs' = pkgs.appendOverlays (with config'.flake.overlays; [ + courier-unicode + getmail6 + maildrop + ]); + PATH = with pkgs'; lib.makeBinPath [ + jq + busybox + runit + bash + getmail6 + maildrop + ]; + in + pkgs.writeShellScript "getmail-run" '' + export PATH=${PATH}:${pkgs.opensmtpd}/libexec/opensmtpd:$PATH + + set -m + + for rcfile in /mail-configuration/getmail.d/*.rc + do + filename="$(basename "''${rcfile}")" + email="''${filename%".rc"}" + + mkdir -p "/getmail.d/''${email}" + chown vmail:vmail -R "/getmail.d/''${email}" + + ( + while true + do + chpst -u vmail:vmail getmail -i INBOX -n -r "$rcfile" --getmaildir "/mail-configuration/getmail.d/''${email}" + sleep 10 + done + ) & + done + + wait + ''; + enabled = true; + }; + }; + }; + }; +} + + # /usr/lib/sendmail -i -oem -f %F %T diff --git a/nixng/containers/email/postfix/default.nix b/nixng/containers/email/postfix/default.nix new file mode 100644 index 0000000..545b7cc --- /dev/null +++ b/nixng/containers/email/postfix/default.nix @@ -0,0 +1,128 @@ +{ inputs, ... }: +{ + flake.nixngConfigurations.postfix = inputs.nixng.nglib.makeSystem { + system = "x86_64-linux"; + name = "nixng-postfix"; + inherit (inputs) + nixpkgs; + config = + { pkgs, config, ... }: + { + config = { + dumb-init = { + enable = true; + type.services = {}; + }; + init.services.postfix = { + shutdownOnExit = true; + }; + services.postfix = { + enable = true; + + masterConfig = import ./master_config.nix; + mainConfig = { + smptd_banner = [ "$myhostname" "ESMTP" "$mail_name" "(Ubuntu)" ]; + biff = "no"; + + # delay_warning_time = "4h"; + + append_dot_mydomain = "no"; + + readme_directory = "no"; + + compatibility_level = 2; + + smtpd_tls_cert_file = "/etc/letsencrypt/live/example.com/fullchain.pem"; + smtpd_tls_key_file = "/etc/letsencrypt/live/example.com/privkey.pem"; + smtpd_use_tls = "yes"; + smtpd_tls_auth_only = "yes"; + smtp_tls_security_level = "may"; + smtpd_tls_security_level = "may"; + smtpd_sasl_security_options = [ "noanonymous" "noplaintext" ]; + smtpd_sasl_tls_security_options = "noanonymous"; + + smtpd_sasl_type = "dovecot"; + smtpd_sasl_path = "private/auth"; + smtpd_sals_auth_enable = "yes"; + + smtpd_helo_restrictions = [ + "permit_mynetworks" + "permit_sals_authenticated" + "reject_invalid_helo_hostname" + "reject_non_fqdn_helo_hostname" + ]; + smtpd_recipient_restrictions = [ + "permit_mynetworks" + "permit_sasl_authenticated" + "reject_non_fqdn_recipient" + "reject_unknown_recipient_domain" + "reject_unlisted_recipient" + "reject_unauth_destination" + ]; + smtpd_sender_restrictions = [ + "permit_mynetworks" + "permit_sasl_authenticated" + "reject_non_fqdn_sender" + "reject_unknown_sender_domain" + ]; + smtpd_relay_restrictions = [ + "permit_mynetworks" + "permit_sasl_authenticated" + "defer_unauth_destination" + ]; + + myhostname = "example.org"; + alias_maps = "hash:/etc/aliases"; + alias_database = "hash:/etc/aliases"; + mydoamin = "example.org"; + myorigin = "$mydomain"; + mydestination = "localhost"; + relayhost = ""; + mynetworks = [ + "127.0.0.0/8" + "[::ffff:127.0.0.0]/104" + "[::1]/128" + ]; + mailbox_size_limit = 0; + recipient_delimiter = "+"; + inet_interfaces = "all"; + inet_protocols = "all"; + + virtual_transport = "lmtp:unix:private/dovecot-lmtp"; + + virtual_mailbox_domains = "mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf"; + virtual_mailbox_maps = "mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf"; + virtual_alias_maps = [ + "mysql:/etc/postfix/mysql-virtual-alias-maps.cf" + "mysql:/etc/postfix/mysql-virtual-email2email.cf" + ]; + + disable_vrfy_command = "yes"; + strict_rfc821_envelopes = "yes"; + # smtpd_etrn_restrictions = "yes"; + # smtpd_reject_unlisted_sender = "yes"; + # smtpd_reject_unlisted_recipient = "yes"; + smtpd_delay_reject = "yes"; + smtpd_helo_required = "yes"; + smtp_always_send_ehlo = "yes"; + # smtpd_hard_error_limit = 1; + smtpd_timeout = "30s"; + smtp_helo_timeout = "15s"; + smtp_rcpt_timeout = "15s"; + smtpd_recipient_limit = "15s"; + minimal_backoff_time = "180s"; + maximal_backoff_time = "3h"; + + invalid_hostname_reject_code = 550; + non_fqdn_reject_code = 550; + unknown_address_reject_code = 550; + unknown_client_reject_code = 550; + unknown_hostname_reject_code = 550; + unverified_recipent_reject_code = 550; + unverified_sender_reject_code = 550; + }; + }; + }; + }; + }; +} diff --git a/nixng/containers/email/postfix/master_config.nix b/nixng/containers/email/postfix/master_config.nix new file mode 100644 index 0000000..ab5b53e --- /dev/null +++ b/nixng/containers/email/postfix/master_config.nix @@ -0,0 +1,27 @@ +{ + pickup = { type = "unix"; private = "n"; chroot = "n"; wakeup = "60"; maxproc = 1; command = "pickup"; }; + cleanup = { type = "unix"; private = "n"; chroot = "n"; maxproc = 0; command = "cleanup"; }; + qmgr = { type = "unix"; private = "n"; chroot = "n"; wakeup = "300"; maxproc = 1; command = "qmgr"; }; + tlsmgr = { type = "unix"; wakeup = "1000?"; maxproc = 1; command = "tlsmgr"; }; + rewrite = { type = "unix"; chroot = "n"; command = "trivial-rewrite"; }; + bounce = { type = "unix"; chroot = "n"; maxproc = 0; command = "bounce"; }; + defer = { type = "unix"; chroot = "n"; maxproc = 0; command = "bounce"; }; + trace = { type = "unix"; chroot = "n"; maxproc = 0; command = "bounce"; }; + verify = { type = "unix"; chroot = "n"; maxproc = 1; command = "verify"; }; + flush = { type = "unix"; chroot = "n"; wakeup = "1000?"; maxproc = 0; command = "flush"; }; + proxymap = { type = "unix"; chroot = "n"; command = "proxymap"; }; + proxywrite = { type = "unix"; chroot = "n"; maxproc = 1; command = "proxymap"; }; + smtp = [ { type = "unix"; chroot = "n"; command = "smtp"; } + { type = "inet"; private = "n"; chroot = "n"; command = "smtpd"; } ]; + relay = { type = "unix"; chroot = "n"; command = "smtp -o syslog_name=postfix/$service_name"; }; # -o smtp_helo_timeout=5 -o smtp_connect_timeout=5 + showq = { type = "unix"; private = "n"; chroot = "n"; command = "showq"; }; + error = { type = "unix"; chroot = "n"; command = "error"; }; + retry = { type = "unix"; chroot = "n"; command = "error"; }; + discard = { type = "unix"; chroot = "n"; command = "discard"; }; + local = { type = "unix"; unpriv = "n"; chroot = "n"; command = "local"; }; + virtual = { type = "unix"; unpriv = "n"; chroot = "n"; command = "virtual"; }; + lmtp = { type = "unix"; chroot = "n"; command = "lmtp"; }; + anvil = { type = "unix"; chroot = "n"; maxproc = 1; command = "anvil"; }; + scache = { type = "unix"; chroot = "n"; maxproc = 1; command = "scache"; }; + postlog = { type = "unix-dgram"; private = "n"; chroot = "n"; maxproc = 1; command = "postlogd"; }; +}