VEGAS: full mail server
This commit is contained in:
parent
6526279a5e
commit
ed80609997
12 changed files with 346 additions and 0 deletions
19
hosts/VEGAS/services/mail/default.nix
Normal file
19
hosts/VEGAS/services/mail/default.nix
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{ tools, ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./imap.nix
|
||||||
|
./opendkim.nix
|
||||||
|
./postfix.nix
|
||||||
|
./saslauthd.nix
|
||||||
|
];
|
||||||
|
services.nginx.virtualHosts."mail.${tools.meta.domain}" = {
|
||||||
|
enableACME = true;
|
||||||
|
locations."/".return = "204";
|
||||||
|
};
|
||||||
|
security.acme.certs."mail.${tools.meta.domain}".extraDomainNames = map
|
||||||
|
(x: "${x}.${tools.meta.domain}") [
|
||||||
|
"mx"
|
||||||
|
"imap"
|
||||||
|
"smtp"
|
||||||
|
];
|
||||||
|
}
|
107
hosts/VEGAS/services/mail/generic-aliases
Normal file
107
hosts/VEGAS/services/mail/generic-aliases
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#
|
||||||
|
# Aliases in this file will NOT be expanded in the header from
|
||||||
|
# Mail, but WILL be visible over networks or from /bin/mail.
|
||||||
|
#
|
||||||
|
# >>>>>>>>>> The program "newaliases" must be run after
|
||||||
|
# >> NOTE >> this file is updated for any changes to
|
||||||
|
# >>>>>>>>>> show through to sendmail.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Basic system aliases -- these MUST be present.
|
||||||
|
mailer-daemon: postmaster
|
||||||
|
postmaster: root
|
||||||
|
|
||||||
|
# General redirections for pseudo accounts.
|
||||||
|
bin: root
|
||||||
|
daemon: root
|
||||||
|
adm: root
|
||||||
|
lp: root
|
||||||
|
sync: root
|
||||||
|
shutdown: root
|
||||||
|
halt: root
|
||||||
|
mail: root
|
||||||
|
news: root
|
||||||
|
uucp: root
|
||||||
|
operator: root
|
||||||
|
games: root
|
||||||
|
gopher: root
|
||||||
|
ftp: root
|
||||||
|
nobody: root
|
||||||
|
radiusd: root
|
||||||
|
nut: root
|
||||||
|
dbus: root
|
||||||
|
vcsa: root
|
||||||
|
canna: root
|
||||||
|
wnn: root
|
||||||
|
rpm: root
|
||||||
|
nscd: root
|
||||||
|
pcap: root
|
||||||
|
apache: root
|
||||||
|
webalizer: root
|
||||||
|
dovecot: root
|
||||||
|
fax: root
|
||||||
|
quagga: root
|
||||||
|
radvd: root
|
||||||
|
pvm: root
|
||||||
|
amandabackup: root
|
||||||
|
privoxy: root
|
||||||
|
ident: root
|
||||||
|
named: root
|
||||||
|
xfs: root
|
||||||
|
gdm: root
|
||||||
|
mailnull: root
|
||||||
|
postgres: root
|
||||||
|
sshd: root
|
||||||
|
smmsp: root
|
||||||
|
postfix: root
|
||||||
|
netdump: root
|
||||||
|
ldap: root
|
||||||
|
squid: root
|
||||||
|
ntp: root
|
||||||
|
mysql: root
|
||||||
|
desktop: root
|
||||||
|
rpcuser: root
|
||||||
|
rpc: root
|
||||||
|
nfsnobody: root
|
||||||
|
pcp: root
|
||||||
|
|
||||||
|
ingres: root
|
||||||
|
system: root
|
||||||
|
toor: root
|
||||||
|
manager: root
|
||||||
|
dumper: root
|
||||||
|
abuse: root
|
||||||
|
|
||||||
|
newsadm: news
|
||||||
|
newsadmin: news
|
||||||
|
usenet: news
|
||||||
|
ftpadm: ftp
|
||||||
|
ftpadmin: ftp
|
||||||
|
ftp-adm: ftp
|
||||||
|
ftp-admin: ftp
|
||||||
|
www: webmaster
|
||||||
|
webmaster: root
|
||||||
|
noc: root
|
||||||
|
security: root
|
||||||
|
hostmaster: root
|
||||||
|
info: postmaster
|
||||||
|
marketing: postmaster
|
||||||
|
sales: postmaster
|
||||||
|
support: postmaster
|
||||||
|
|
||||||
|
|
||||||
|
# trap decode to catch security attacks
|
||||||
|
decode: root
|
||||||
|
|
||||||
|
# Person who should get root's mail
|
||||||
|
#root: marc
|
||||||
|
#
|
||||||
|
|
||||||
|
contact: admins
|
||||||
|
office: admins
|
||||||
|
root: admins
|
||||||
|
admin: admins
|
||||||
|
|
||||||
|
# TODO: unhardcode
|
||||||
|
admins: max, bone, num
|
||||||
|
|
65
hosts/VEGAS/services/mail/imap.nix
Normal file
65
hosts/VEGAS/services/mail/imap.nix
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
{ config, lib, pkgs, tools, ... }:
|
||||||
|
let
|
||||||
|
inherit (tools.identity) ldap;
|
||||||
|
inherit (tools.meta) domain;
|
||||||
|
|
||||||
|
postfixCfg = config.services.postfix;
|
||||||
|
|
||||||
|
# TODO: switch to proper certdir
|
||||||
|
certDir = config.security.acme.certs."mail.${domain}".directory;
|
||||||
|
|
||||||
|
# TODO: check how this thing does lookups, apply bind dn
|
||||||
|
ldapConfig = with ldap.accounts; pkgs.writeText "dovecot-ldap.conf.ext" ''
|
||||||
|
uris = ${ldap.server.url}
|
||||||
|
|
||||||
|
auth_bind = yes
|
||||||
|
auth_bind_userdn = ${uidAttribute}=%n,${userSearchBase}
|
||||||
|
base = ${userSearchBase}
|
||||||
|
pass_filter = (uid=%n)
|
||||||
|
pass_attrs = uid=user
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
networking.firewall.allowedTCPPorts = [ 143 993 ];
|
||||||
|
|
||||||
|
services.dovecot2 = {
|
||||||
|
enable = true;
|
||||||
|
enableLmtp = true;
|
||||||
|
enableImap = true;
|
||||||
|
enablePAM = false;
|
||||||
|
mailUser = "vmail";
|
||||||
|
mailGroup = "vmail";
|
||||||
|
sslServerCert = "${certDir}/fullchain.pem";
|
||||||
|
sslServerKey = "${certDir}/key.pem";
|
||||||
|
|
||||||
|
modules = [ pkgs.dovecot_pigeonhole ];
|
||||||
|
|
||||||
|
sieveScripts.after = ./sieve;
|
||||||
|
|
||||||
|
extraConfig = with config.services.dovecot2; ''
|
||||||
|
auth_username_format = %n
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
inbox = yes
|
||||||
|
separator = /
|
||||||
|
}
|
||||||
|
userdb {
|
||||||
|
driver = static
|
||||||
|
args = allow_all_users=yes uid=${mailUser} gid=${mailUser} home=/var/mail/virtual/%d/%n
|
||||||
|
}
|
||||||
|
passdb {
|
||||||
|
driver = ldap
|
||||||
|
args = ${ldapConfig}
|
||||||
|
}
|
||||||
|
|
||||||
|
service auth {
|
||||||
|
unix_listener auth {
|
||||||
|
mode = 0660
|
||||||
|
user = ${postfixCfg.user}
|
||||||
|
group = ${postfixCfg.group}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auth_mechanisms = plain login
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
7
hosts/VEGAS/services/mail/known-spam-domains
Normal file
7
hosts/VEGAS/services/mail/known-spam-domains
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/\.ru$/ DISCARD
|
||||||
|
/\.cf$/ DISCARD
|
||||||
|
/\.gq$/ DISCARD
|
||||||
|
/\.tk$/ DISCARD
|
||||||
|
/\.ga$/ DISCARD
|
||||||
|
/pixelsurplus.com$/ DISCARD
|
||||||
|
/mega.nz$/ DISCARD
|
15
hosts/VEGAS/services/mail/opendkim.nix
Normal file
15
hosts/VEGAS/services/mail/opendkim.nix
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{ lib, tools, ... }:
|
||||||
|
let
|
||||||
|
inherit (tools.meta) domain;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.opendkim = {
|
||||||
|
enable = true;
|
||||||
|
selector = domain;
|
||||||
|
domains = domain;
|
||||||
|
};
|
||||||
|
# ensure socket becomes group-writable
|
||||||
|
systemd.services.opendkim.serviceConfig.UMask = lib.mkForce "0007";
|
||||||
|
# TODO: figure out which one works
|
||||||
|
users.users.postfix.extraGroups = [ "opendkim" ];
|
||||||
|
}
|
93
hosts/VEGAS/services/mail/postfix.nix
Normal file
93
hosts/VEGAS/services/mail/postfix.nix
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
{ config, tools, ... }:
|
||||||
|
let
|
||||||
|
inherit (tools.meta) domain;
|
||||||
|
certDir = config.security.acme.certs."mail.${domain}".directory;
|
||||||
|
|
||||||
|
receivePolicy = [ "permit_sasl_authenticated" "permit_mynetworks" "reject_unauth_destination" ];
|
||||||
|
spamPolicy = [ "reject_sender_login_mismatch" "permit_sasl_authenticated" "pcre:${./known-spam-domains}" ];
|
||||||
|
|
||||||
|
dkimSocket = builtins.replaceStrings ["local:"] ["unix:"] config.services.opendkim.socket;
|
||||||
|
lmtpSocket = "lmtp:unix:/run/dovecot2/lmtp";
|
||||||
|
postfixLdapMailboxes = "ldap:${config.age.secrets."postfix-ldap-mailboxes.cf".path}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
age.secrets."postfix-ldap-mailboxes.cf" = {
|
||||||
|
file = ../../../../secrets/postfix-ldap-mailboxes.age;
|
||||||
|
owner = "postfix";
|
||||||
|
group = "postfix";
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 25 465 587 ];
|
||||||
|
|
||||||
|
services.postfix = {
|
||||||
|
enable = true;
|
||||||
|
enableSubmission = true;
|
||||||
|
enableSubmissions = true;
|
||||||
|
inherit domain;
|
||||||
|
origin = domain;
|
||||||
|
recipientDelimiter = "+";
|
||||||
|
|
||||||
|
# TODO: replace with proper certs
|
||||||
|
sslCert = "/var/lib/acme/mail.${domain}/fullchain.pem";
|
||||||
|
sslKey = "/var/lib/acme/mail.${domain}/key.pem";
|
||||||
|
#sslCert = "${certDir}/fullchain.pem";
|
||||||
|
#sslKey = "${certDir}/privkey.pem";
|
||||||
|
|
||||||
|
setSendmail = true;
|
||||||
|
|
||||||
|
# TODO: un-hardcode
|
||||||
|
networks = [
|
||||||
|
"localhost"
|
||||||
|
"10.1.0.1/32"
|
||||||
|
"10.10.0.0/16"
|
||||||
|
"10.100.0.0/16"
|
||||||
|
];
|
||||||
|
|
||||||
|
aliasFiles.genericAliases = ./generic-aliases;
|
||||||
|
|
||||||
|
config = {
|
||||||
|
myhostname = "mx.${domain}";
|
||||||
|
# TODO: un-hardcode + add ip address instead of $myhostname
|
||||||
|
inet_interfaces = [ "localhost" "$myhostname" "10.1.0.1" ];
|
||||||
|
|
||||||
|
disable_vrfy_command = true;
|
||||||
|
|
||||||
|
# authorization policies
|
||||||
|
smtpd_recipient_restrictions = receivePolicy;
|
||||||
|
|
||||||
|
smtpd_relay_restrictions = receivePolicy;
|
||||||
|
smtpd_sender_restrictions = spamPolicy;
|
||||||
|
|
||||||
|
smtpd_sender_login_maps = postfixLdapMailboxes;
|
||||||
|
|
||||||
|
# authentication
|
||||||
|
# TODO: review these options
|
||||||
|
smtpd_sasl_auth_enable = true;
|
||||||
|
smtpd_sasl_type = "dovecot";
|
||||||
|
smtpd_sasl_path = "/run/dovecot2/auth";
|
||||||
|
smtpd_sasl_local_domain = domain;
|
||||||
|
smtpd_sasl_security_options = "noanonymous";
|
||||||
|
smtpd_sasl_tls_security_options = "noanonymous";
|
||||||
|
smtpd_sasl_authenticated_header = true;
|
||||||
|
broken_sasl_auth_clients = false;
|
||||||
|
|
||||||
|
smtpd_milters = dkimSocket;
|
||||||
|
non_smtpd_milters = dkimSocket;
|
||||||
|
|
||||||
|
# delivery
|
||||||
|
virtual_mailbox_domains = [ domain "max.admin.${domain}" ];
|
||||||
|
virtual_transport = lmtpSocket;
|
||||||
|
mailbox_transport = lmtpSocket;
|
||||||
|
virtual_mailbox_maps = postfixLdapMailboxes;
|
||||||
|
virtual_alias_maps = [
|
||||||
|
postfixLdapMailboxes
|
||||||
|
"regexp:${./virtual-mail-domain-aliases}"
|
||||||
|
"hash:/var/lib/postfix/conf/genericAliases"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.fail2ban.jails.postfix = ''
|
||||||
|
enabled = true
|
||||||
|
'';
|
||||||
|
}
|
17
hosts/VEGAS/services/mail/saslauthd.nix
Normal file
17
hosts/VEGAS/services/mail/saslauthd.nix
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{ pkgs, tools, ... }:
|
||||||
|
let
|
||||||
|
inherit (tools.identity) ldap;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.saslauthd = {
|
||||||
|
enable = true;
|
||||||
|
mechanism = "ldap";
|
||||||
|
package = pkgs.cyrus_sasl.override { enableLdap = true; };
|
||||||
|
config = ''
|
||||||
|
ldap_servers: ${ldap.server.url}
|
||||||
|
ldap_filter: ${ldap.accounts.uidFilter}
|
||||||
|
ldap_search_base: ${ldap.accounts.userSearchBase}
|
||||||
|
ldapdb_canon_attr: ${ldap.accounts.uidAttribute}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
9
hosts/VEGAS/services/mail/sieve/plus.sieve
Normal file
9
hosts/VEGAS/services/mail/sieve/plus.sieve
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
require ["variables", "envelope", "fileinto", "subaddress", "mailbox"];
|
||||||
|
|
||||||
|
if envelope :matches :detail "to" "*" {
|
||||||
|
set :lower :upperfirst "name" "''${1}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if not string :is "''${name}" "" {
|
||||||
|
fileinto :create "Plus/''${name}";
|
||||||
|
}
|
1
hosts/VEGAS/services/mail/virtual-mail-domain-aliases
Normal file
1
hosts/VEGAS/services/mail/virtual-mail-domain-aliases
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/.*@max.admin.privatevoid.net$/ max@privatevoid.net
|
|
@ -25,6 +25,7 @@
|
||||||
./services/ipfs
|
./services/ipfs
|
||||||
./services/jokes
|
./services/jokes
|
||||||
./services/nfs
|
./services/nfs
|
||||||
|
./services/mail
|
||||||
]
|
]
|
||||||
# TODO: fix users
|
# TODO: fix users
|
||||||
# ++ (import ../../users "server").groups.admin
|
# ++ (import ../../users "server").groups.admin
|
||||||
|
|
11
secrets/postfix-ldap-mailboxes.age
Normal file
11
secrets/postfix-ldap-mailboxes.age
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
age-encryption.org/v1
|
||||||
|
-> ssh-ed25519 NO562A cnRopy2Tr4CFJGdwaaLZqFTSa7dLsNw4myqg7++hChQ
|
||||||
|
rVCyDQyP2bt6dKDYg7Xe2PhVh07nJTgUFdM0zWEUmFQ
|
||||||
|
-> ssh-ed25519 5/zT0w wxyMxiGccuneCthOkIMt8/v3Qcei6xUr3AluNLUrFQk
|
||||||
|
YvEbaZ8cFX11kL5G/Kq1UWCAa3V8FonnPk7p0QspfQI
|
||||||
|
-> ssh-ed25519 d3WGuA I0SpBd+PzikDgD4dw2H0H/kKUClinFQhIuihy3R10E8
|
||||||
|
mhzTew29HEftx80w/WjALnk8PdxFaMmyiTxD9v1TBJU
|
||||||
|
-> ':2-grease ^`%-
|
||||||
|
e9YRGhE0uUNFLHvPoLM6PskQh4ANBsBFeN8
|
||||||
|
--- mINLO9AxrnxY8TdFfrDNxwwth+lYBtNnEWP1IqUV+78
|
||||||
|
Ét‘V"o<>¦SEÈhY¹Õ è7*žZëÿâöŽV@ü|+/áÃ8Z<>–óÓ)£èrÃXðcRŪû¿]í^*ä½ =ÎZ®l/ö†³\É[ »b>-§ 'BÜeÈH=憤–è‚"$†Þ7ë4i`¥'3¾ÄìJÃ,«µ—ïá‚p‹À8Wg<57>ÅLž,ÜŠ1yV«ðušzsþ?ØßØÉòÏ-|*Èoìô§Ô>>2{
©CÐÁÐm<17>
ãXÏ‘ëCºÚbBSÊöÕ8ªæ›Ps¹†ƒÿݩÊÿÙ‚vl<16>ÙöFôÚߨ(Àq¶ÖÕçÙ,eoæXimô<6D>ÎM›æî<C3A6>ÈøP¢'4š|Bø_—q ëKû)«æF¤T(}<7D>jbÃδ´®ûa›Ý2ÇIFé<46>òà6õUŸ(k\êÊ™RÚ‡üÄ•,¼$ÜÓ<C39C>ú
|
|
@ -10,5 +10,6 @@ in with hosts;
|
||||||
"hydra-db-credentials.age".publicKeys = max ++ map systemKeys [ styx ];
|
"hydra-db-credentials.age".publicKeys = max ++ map systemKeys [ styx ];
|
||||||
"hydra-s3.age".publicKeys = max ++ map systemKeys [ styx ];
|
"hydra-s3.age".publicKeys = max ++ map systemKeys [ styx ];
|
||||||
"oauth2_proxy-secrets.age".publicKeys = max ++ map systemKeys [ VEGAS ];
|
"oauth2_proxy-secrets.age".publicKeys = max ++ map systemKeys [ VEGAS ];
|
||||||
|
"postfix-ldap-mailboxes.age".publicKeys = max ++ map systemKeys [ VEGAS ];
|
||||||
"wireguard-key-wgautobahn.age".publicKeys = max ++ map systemKeys [ VEGAS ];
|
"wireguard-key-wgautobahn.age".publicKeys = max ++ map systemKeys [ VEGAS ];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue