nix/container/Mail.nix

229 lines
5.9 KiB
Nix
Raw Normal View History

2024-06-09 23:35:53 +03:00
# Guide: https://nixos-mailserver.readthedocs.io/en/latest/setup-guide.html
2024-06-25 04:04:39 +03:00
{ container, pkgs, util, const, lib, config, ... }: with lib; let
cfg = config.container.module.mail;
domain = config.container.domain;
2024-06-09 23:35:53 +03:00
in {
2024-06-25 04:04:39 +03:00
options = {
container.module.mail = {
enable = mkEnableOption "Email server.";
address = mkOption {
default = "10.1.0.5";
type = types.str;
2024-06-09 23:35:53 +03:00
};
2024-06-25 04:04:39 +03:00
port = mkOption {
default = 80;
type = types.int;
2024-06-09 23:35:53 +03:00
};
2024-06-25 04:04:39 +03:00
domain = mkOption {
default = "mail.${config.container.domain}";
type = types.str;
2024-06-09 23:35:53 +03:00
};
2024-06-25 04:04:39 +03:00
storage = mkOption {
default = "${config.container.storage}/mail";
type = types.str;
2024-06-09 23:35:53 +03:00
};
};
2024-06-25 04:04:39 +03:00
};
config = mkIf cfg.enable {
systemd.tmpfiles.rules = container.mkContainerDir cfg [
"data"
# "data/indices"
# "data/vmail"
# "data/sieve"
# "data/dkim"
];
2024-06-09 23:35:53 +03:00
2024-06-25 04:04:39 +03:00
containers.mail = container.mkContainer cfg {
bindMounts = {
"/var/lib/dovecot/indices" = {
hostPath = "${cfg.storage}/data/indices";
isReadOnly = false;
};
"/var/vmail" = {
hostPath = "${cfg.storage}/data/vmail";
isReadOnly = false;
};
"/var/sieve" = {
hostPath = "${cfg.storage}/data/sieve";
isReadOnly = false;
};
"/var/dkim" = {
hostPath = "${cfg.storage}/data/dkim";
isReadOnly = false;
};
"/acme" = {
hostPath = "${config.container.module.proxy.storage}/letsencrypt";
isReadOnly = true;
};
};
2024-06-09 23:35:53 +03:00
2024-06-25 04:04:39 +03:00
config = { config, ... }: container.mkContainerConfig cfg {
imports = [
(builtins.fetchTarball {
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-${const.stateVersion}/nixos-mailserver-nixos-${const.stateVersion}.tar.gz";
sha256 = "sha256:0clvw4622mqzk1aqw1qn6shl9pai097q62mq1ibzscnjayhp278b";
})
];
mailserver = {
enable = true;
domains = [ domain ];
fqdn = cfg.domain;
sendingFqdn = domain;
# Use `mkpasswd -sm bcrypt`.
loginAccounts = let
defaultQuota = "1G";
in {
"admin@${domain}" = {
name = "admin";
hashedPassword = "$2b$05$1O.dxXxaVshcBNybcqDRYuTlnYt3jDBwfPZWoDtP4BjOLoL0StYsi";
quota = defaultQuota;
};
"account@${domain}" = {
name = "account";
hashedPassword = "$2b$05$sCyZHdk98KqQ1qsTIvbrUeRJlNBOwBqDgpdc1QxiSnONlEkZ8xGNO";
quota = defaultQuota;
};
"hi@${domain}" = {
name = "hi";
hashedPassword = "$2b$05$6fT5hIhzIasNfp9IQr/ds.5RuxH95VKU3QJWlX3hmrAzDF3mExanq";
quota = defaultQuota;
aliases = [ "voronind@${domain}" ];
};
"job@${domain}" = {
name = "job";
hashedPassword = "$2b$05$.sUmv2.9EWPfLwJn/oZw2e1UbR7HrpNQ2THc5jjX3ysy7CY8ZWHUC";
quota = defaultQuota;
};
"trash@${domain}" = {
name = "trash";
hashedPassword = "$2b$05$kn5ygZjN9NR3LXjnKKRw/.DXaZQNW.1XEottlCFIoKiDpIj.JGLJm";
catchAll = [ domain ];
quota = defaultQuota;
};
"noreply@${domain}" = {
name = "noreply";
hashedPassword = "$2b$05$TaKwoYmcmkAhsRRv6xG5wOkChcz50cB9BP6QPUDKNAcxMbrY6AeMK";
sendOnly = true;
quota = defaultQuota;
};
2024-06-09 23:35:53 +03:00
};
2024-06-25 04:04:39 +03:00
enableImap = true;
enableImapSsl = true;
enableSubmission = true;
enableSubmissionSsl = true;
2024-06-09 23:35:53 +03:00
2024-08-05 17:23:34 +03:00
enableManageSieve = true;
virusScanning = false;
2024-06-09 23:35:53 +03:00
2024-06-25 04:04:39 +03:00
certificateScheme = "manual";
keyFile = "/acme/live/${domain}/privkey.pem";
certificateFile = "/acme/live/${domain}/cert.pem";
2024-06-09 23:35:53 +03:00
2024-06-25 04:04:39 +03:00
indexDir = "/var/lib/dovecot/indices";
mailDirectory = "/var/vmail";
sieveDirectory = "/var/sieve";
dkimKeyDirectory = "/var/dkim";
2024-06-09 23:35:53 +03:00
2024-06-25 04:04:39 +03:00
mailboxes = {
All = {
auto = "subscribe";
specialUse = "All";
};
Archive = {
auto = "subscribe";
specialUse = "Archive";
};
2024-06-25 04:04:39 +03:00
Drafts = {
auto = "subscribe";
specialUse = "Drafts";
};
Junk = {
auto = "subscribe";
specialUse = "Junk";
2024-08-31 19:15:32 +03:00
# autoexpunge = "3d";
2024-06-25 04:04:39 +03:00
};
Sent = {
auto = "subscribe";
specialUse = "Sent";
};
Trash = {
auto = "subscribe";
specialUse = "Trash";
2024-08-31 19:15:32 +03:00
# autoexpunge = "30d";
2024-06-25 04:04:39 +03:00
};
2024-06-09 23:35:53 +03:00
};
2024-06-25 04:04:39 +03:00
dmarcReporting = {
inherit domain;
enable = true;
organizationName = "voronind";
# email = "noreply@${domain}";
2024-06-09 23:35:53 +03:00
};
2024-06-25 04:04:39 +03:00
# monitoring = {
# enable = true;
# alertAddress = "admin@${domain}";
# };
2024-06-09 23:35:53 +03:00
};
2024-08-31 19:15:32 +03:00
services = {
roundcube = {
enable = true;
dicts = with pkgs.aspellDicts; [ en ru ];
hostName = cfg.domain;
plugins = [
"managesieve"
];
extraConfig = ''
# starttls needed for authentication, so the fqdn required to match
# the certificate
# $config['smtp_server'] = "tls://${config.mailserver.fqdn}";
# $config['smtp_server'] = "tls://localhost";
$config['smtp_server'] = "localhost:25";
$config['smtp_auth_type'] = null;
$config['smtp_user'] = "";
$config['smtp_pass'] = "";
# $config['smtp_user'] = "%u";
# $config['smtp_pass'] = "%p";
'';
};
nginx = {
virtualHosts.${cfg.domain} = {
forceSSL = false;
enableACME = false;
};
};
2024-06-09 23:35:53 +03:00
};
2024-08-31 19:15:32 +03:00
systemd = {
services.autoexpunge = {
description = "Delete old mail";
serviceConfig.Type = "oneshot";
path = [ pkgs.dovecot ];
script = ''
doveadm expunge -A mailbox Junk SENTBEFORE 7d
doveadm expunge -A mailbox Trash SENTBEFORE 30d
2024-09-24 19:02:56 +03:00
doveadm expunge -u trash@voronind.com mailbox Inbox SENTBEFORE 30d
2024-08-31 19:41:46 +03:00
doveadm purge -A
2024-08-31 19:15:32 +03:00
'';
};
timers.autoexpunge = {
timerConfig = {
OnCalendar = "daily";
Persistent = true;
Unit = "autoexpunge.service";
};
wantedBy = [ "timers.target" ];
2024-06-25 04:04:39 +03:00
};
2024-06-09 23:35:53 +03:00
};
};
};
};
}