2024-08-09 12:50:33 +00:00
#!/usr/bin/env bash
###############
#//
#// Users and directories
#//
###############
# Add users to groups
adduser dovecot mail >/dev/null
adduser ${ MYVEMAIL_NGINX_USERGROUP } dovecot >/dev/null
adduser postfix opendkim >/dev/null
# Virtual mailboxes
mkdir /etc/postfix/sql
# MariaDB
install -m 1777 -d /run/mysqld
# DKIM/DMARC
2024-08-10 03:13:59 +00:00
mkdir /{ run,etc} /{ opendkim,opendmarc} >/dev/null 2>& 1
2024-08-09 12:50:33 +00:00
install -o opendkim -g postfix -d /var/spool/postfix/opendkim/
install -m 750 -o opendmarc -g postfix -d /var/spool/postfix/opendmarc/
###############
#//
#// PHP
#//
###############
sed -e '/upload_max_filesize =/c upload_max_filesize = 0' \
-e '/post_max_size =/c post_max_size = 0' \
-e '/memory_limit =/c memory_limit = 4096M' \
-i $( find /etc/php*/ -name 'php.ini' )
###############
#//
#// Postfix
#//
###############
postconf -e 'relay_domains = $mydestination'
postconf -e 'smtp_tls_security_level = may'
postconf -e 'smtp_tls_loglevel = 1'
postconf -e 'smtpd_tls_security_level = may'
postconf -e 'smtpd_tls_loglevel = 1'
postconf -e 'mailbox_size_limit = 0'
postconf -e 'message_size_limit = 0'
postconf -e " authorized_submit_users = root, ${ MYVEMAIL_NGINX_USERGROUP } "
postconf -e 'smtpd_tls_session_cache_database = lmdb:${data_directory}/smtpd_scache'
postconf -e 'smtp_tls_session_cache_database = lmdb:${data_directory}/smtp_scache'
postconf -e 'smtp_tls_note_starttls_offer = yes'
postconf -e 'smtpd_tls_received_header = yes'
postconf -e 'inet_interfaces = all'
postconf -e 'inet_protocols = ipv4'
postconf -e 'smtp_address_preference = ipv4'
postconf -e 'myorigin = $mydomain'
postconf -e 'mydestination = $myhostname, localhost.$mydomain, localhost'
postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
postconf -e "smtpd_tls_key_file = /etc/ssl/dovecot/tls.key"
postconf -e "smtpd_tls_cert_file = /etc/ssl/dovecot/tls.pem"
# Enforce TLSv1.2 or TLSv1.2
postconf -e "smtpd_tls_mandatory_protocols = >=TLSv1.2"
postconf -e "smtp_tls_mandatory_protocols = >=TLSv1.2"
postconf -e "smtpd_tls_protocols = >=TLSv1.2"
postconf -e "smtp_tls_protocols = >=TLSv1.2"
2024-08-19 01:34:00 +00:00
# # Logging
# postconf -e "maillog_file = /var/log/postfix.log"
2024-08-09 12:50:33 +00:00
# Virtual mailboxes
postconf -e "mailbox_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "smtputf8_enable = no"
postconf -e "virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/virtual_domains_maps.cf"
postconf -e "virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/virtual_mailbox_maps.cf, proxy:mysql:/etc/postfix/sql/virtual_alias_domain_mailbox_maps.cf"
postconf -e "virtual_alias_maps = proxy:mysql:/etc/postfix/sql/virtual_alias_maps.cf, proxy:mysql:/etc/postfix/sql/virtual_alias_domain_maps.cf, proxy:mysql:/etc/postfix/sql/virtual_alias_domain_catchall_maps.cf"
postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "virtual_mailbox_base = /var/vmail"
postconf -e "virtual_uid_maps = static:600"
postconf -e "virtual_gid_maps = static:600"
postconf -e "virtual_minimum_uid = 600"
postconf -e "virtual_mailbox_limit = 0"
postconf -e "smtp_header_checks = pcre:/etc/postfix/smtp_header_checks"
# SPF and DKIM checks
postconf -e "policy_time_limit = 3600"
2025-03-18 00:16:45 +00:00
postconf -e "smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, check_client_access pcre:/etc/postfix/whitelisted_domains, check_sender_access lmdb:/etc/postfix/whitelisted_emails, check_client_access pcre:/etc/postfix/blacklisted_domains, check_sender_access lmdb:/etc/postfix/blacklisted_emails, check_policy_service unix:private/policyd-spf"
2024-08-09 12:50:33 +00:00
# Milter configuration
postconf -e "milter_default_action = accept"
postconf -e "milter_protocol = 6"
postconf -e "smtpd_milters = local:opendkim/opendkim.sock, local:opendmarc/opendmarc.sock"
postconf -e 'non_smtpd_milters = $smtpd_milters'
# Blocking spam
2025-03-05 04:03:53 +00:00
postconf -e "smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unknown_sender_domain, reject_unknown_reverse_client_hostname, reject_unknown_client_hostname"
2024-08-09 12:50:33 +00:00
postconf -e "smtpd_helo_required = yes"
2025-03-05 02:13:17 +00:00
postconf -e "smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, check_helo_access pcre:/etc/postfix/helo_access, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_helo_hostname"
2024-08-09 12:50:33 +00:00
# Postscreen spambots
postconf -e "postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr cidr:/etc/postfix/postscreen_spf_whitelist.cidr"
postconf -e "postscreen_blacklist_action = drop"
postconf -e "postscreen_greet_action = enforce"
postconf -e "postscreen_dnsbl_threshold = 3"
postconf -e "postscreen_dnsbl_action = enforce"
2024-08-14 10:38:46 +00:00
postconf -e "postscreen_dnsbl_sites = bl.spameatingmonkey.net*2, bl.spamcop.net, dnsbl.sorbs.net" # zen.spamhaus.org*3,
2024-08-09 12:50:33 +00:00
postconf -e "postscreen_dnsbl_whitelist_threshold = -2"
postconf -e "header_checks = pcre:/etc/postfix/header_checks"
postconf -e "body_checks = pcre:/etc/postfix/body_checks"
# master.cf
sed -e 's/^smtp .*smtpd$/# &/' \
-e '/#smtp\|#smtpd\|#dnsblog\|#tlsproxy/ s/^#//' -i /etc/postfix/master.cf
2024-08-14 17:48:59 +00:00
tee -a /etc/postfix/master.cf >/dev/null <<- master.cf
2024-08-09 12:50:33 +00:00
# Enable submission
submission inet n - y - - smtpd
-o syslog_name = postfix/submission
-o smtpd_tls_security_level = encrypt
-o smtpd_tls_wrappermode = no
-o smtpd_sasl_auth_enable = yes
-o smtpd_relay_restrictions = permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject
-o smtpd_sasl_type = dovecot
-o smtpd_sasl_path = private/auth
# SPF Policy
2025-03-18 00:16:45 +00:00
policyd-spf unix - n n - - spawn
2025-03-04 21:16:11 +00:00
user = nobody argv = /usr/bin/perl ${ MYVEMAIL_POLICYD }
2024-08-09 12:50:33 +00:00
master.cf
# Deleting Email Headers For Outgoing Emails
echo -e ' /^X-Spam-Status:/ IGNORE
/^X-Spam-Checker-Version:/ IGNORE
/^Received:.*/ IGNORE
/^User-Agent:.*/ IGNORE' | tee /etc/postfix/smtp_header_checks >/dev/null
# Header checks
echo " /free mortgage quote/ DISCARD
/repair your credit/ DISCARD
/lose weight/ DISCARD
/To:.*<>/ DISCARD
/From:.*<>/ DISCARD" | tee -a /etc/postfix/header_checks >/dev/null
# Body checks
echo " /free mortgage quote/ DISCARD
/repair your credit/ DISCARD
/lose weight/ DISCARD" | tee -a /etc/postfix/body_checks >/dev/null
# Touch aliases db
newaliases
###############
#//
#// Dovecot
#//
###############
# dovecot.conf
tee -a /etc/dovecot/dovecot.conf >/dev/null <<- dovecot.conf
!include_try ssl-keys.conf
protocols = imap lmtp
dovecot.conf
2024-08-19 01:34:00 +00:00
# # Logging
# echo "log_path = /var/log/dovecot.log" >/etc/dovecot/conf.d/10-logging.conf
2024-08-09 12:50:33 +00:00
# 10-auth.conf
sed '/include auth-sql.conf.ext\|disable_plaintext_auth =\|auth_username_format =\|auth_mechanisms =\|auth_default_realm =\|include auth-system.conf.ext/d' \
-i /etc/dovecot/conf.d/10-auth.conf
tee -a /etc/dovecot/conf.d/10-auth.conf >/dev/null <<- '10-auth.conf'
!include auth-sql.conf.ext
disable_plaintext_auth = yes
auth_username_format = %Lu
auth_mechanisms = plain login
auth_default_realm = { { MYVEMAIL_DOMAIN} }
auth_debug = yes
auth_debug_passwords = yes
10-auth.conf
# dovecot-sql.conf.ext
tee -a /etc/dovecot/dovecot-sql.conf.ext >/dev/null <<- 'dovecot'
# Virtual mailboxes
driver = mysql
connect = host = localhost dbname = { { MYVEMAIL_POSTFIXADMIN_DBNAME} } user = { { MYVEMAIL_POSTFIXADMIN_DBUSER} } password = { { MYVEMAIL_POSTFIXADMIN_DBPASS} }
default_pass_scheme = ARGON2I
password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active = '1'
user_query = SELECT maildir, 600 AS uid, 600 AS gid FROM mailbox WHERE username = '%u' AND active = '1'
iterate_query = SELECT username AS user FROM mailbox
dovecot
# 10-mail.conf
sed '/mail_location =\|mail_home =\|mail_privileged_group =/d' \
-i /etc/dovecot/conf.d/10-mail.conf
tee -a /etc/dovecot/conf.d/10-mail.conf >/dev/null <<- '10-mail.conf'
mail_privileged_group = mail
mail_location = maildir:~/Maildir
mail_home = /var/vmail/%d/%n/
10-mail.conf
# 10-master.conf
sed -e ' s| unix_listener lmtp { | unix_listener /var/spool/postfix/private/dovecot-lmtp { \
mode = 0600\
user = postfix\
group = postfix| ' \
-e ' s| unix_listener auth-userdb { | unix_listener /var/spool/postfix/private/auth { \
mode = 0660\
user = postfix\
group = postfix| ' \
-i /etc/dovecot/conf.d/10-master.conf
# 10-ssl.conf
rm -f /etc/ssl/dovecot/*
install -m 0600 /dev/stdin /etc/dovecot/ssl-keys.conf <<- ssl-keys .conf
ssl_dh = </etc/ssl/dovecot/dh.pem
ssl_cert = </etc/ssl/dovecot/tls.pem
ssl_key = </etc/ssl/dovecot/tls.key
ssl-keys.conf
sed '/ssl_dh =\|ssl_cert =\|ssl_key\|ssl =\|ssl_prefer_server_ciphers =\|ssl_min_protocol =/d' -i /etc/dovecot/conf.d/10-ssl.conf
tee -a /etc/dovecot/conf.d/10-ssl.conf >/dev/null <<- '10-ssl.conf'
ssl = required
ssl_prefer_server_ciphers = yes
ssl_min_protocol = TLSv1.2
10-ssl.conf
# Stats service
tee -a /etc/dovecot/conf.d/10-master.conf >/dev/null <<- 10-master.conf
service stats {
unix_listener stats-reader {
user = ${ MYVEMAIL_NGINX_USERGROUP }
group = ${ MYVEMAIL_NGINX_USERGROUP }
mode = 0660
}
unix_listener stats-writer {
user = ${ MYVEMAIL_NGINX_USERGROUP }
group = ${ MYVEMAIL_NGINX_USERGROUP }
mode = 0660
}
}
10-master.conf
# Mailboxes
sed -i ' s/namespace inbox { /& \
# Archive folder\
mailbox Archive { \
special_use = \\ Archive\
} /' /etc/dovecot/conf.d/15-mailboxes.conf
sed -i ' /Sent Messages/! s/^ mailbox.*{ /& \
auto = subscribe/' /etc/dovecot/conf.d/15-mailboxes.conf
# Virtual mailboxes
install -m 0640 /dev/stdin /etc/postfix/sql/virtual_domains_maps.cf <<- eof
hosts = localhost
dbname = { { MYVEMAIL_POSTFIXADMIN_DBNAME} }
user = { { MYVEMAIL_POSTFIXADMIN_DBUSER} }
password = { { MYVEMAIL_POSTFIXADMIN_DBPASS} }
query = SELECT domain FROM domain WHERE domain = '%s' AND active = '1'
#query = SELECT domain FROM domain WHERE domain='%s'
#optional query to use when relaying for backup MX
#query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
#expansion_limit = 100
eof
install -m 0640 /dev/stdin /etc/postfix/sql/virtual_mailbox_maps.cf <<- eof
hosts = localhost
dbname = { { MYVEMAIL_POSTFIXADMIN_DBNAME} }
user = { { MYVEMAIL_POSTFIXADMIN_DBUSER} }
password = { { MYVEMAIL_POSTFIXADMIN_DBPASS} }
query = SELECT maildir FROM mailbox WHERE username = '%s' AND active = '1'
#expansion_limit = 100
eof
install -m 0640 /dev/stdin /etc/postfix/sql/virtual_alias_domain_mailbox_maps.cf <<- eof
hosts = localhost
dbname = { { MYVEMAIL_POSTFIXADMIN_DBNAME} }
user = { { MYVEMAIL_POSTFIXADMIN_DBUSER} }
password = { { MYVEMAIL_POSTFIXADMIN_DBPASS} }
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT( '%u' , '@' , alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active= '1'
eof
install -m 0640 /dev/stdin /etc/postfix/sql/virtual_alias_maps.cf <<- eof
hosts = localhost
dbname = { { MYVEMAIL_POSTFIXADMIN_DBNAME} }
user = { { MYVEMAIL_POSTFIXADMIN_DBUSER} }
password = { { MYVEMAIL_POSTFIXADMIN_DBPASS} }
query = SELECT goto FROM alias WHERE address = '%s' AND active = '1'
#expansion_limit = 100
eof
install -m 0640 /dev/stdin /etc/postfix/sql/virtual_alias_domain_maps.cf <<- eof
hosts = localhost
dbname = { { MYVEMAIL_POSTFIXADMIN_DBNAME} }
user = { { MYVEMAIL_POSTFIXADMIN_DBUSER} }
password = { { MYVEMAIL_POSTFIXADMIN_DBPASS} }
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT( '%u' , '@' , alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active= '1'
eof
install -m 0640 /dev/stdin /etc/postfix/sql/virtual_alias_domain_catchall_maps.cf <<- eof
# handles catch-all settings of target-domain
hosts = localhost
dbname = { { MYVEMAIL_POSTFIXADMIN_DBNAME} }
user = { { MYVEMAIL_POSTFIXADMIN_DBUSER} }
password = { { MYVEMAIL_POSTFIXADMIN_DBPASS} }
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT( '@' , alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active= '1'
eof
###############
#//
#// OpenDKIM
#//
###############
# sed -i 's\^SOCKET=local:$RUNDIR/opendkim.sock\SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"\' /etc/default/opendkim
sed -i "/Canonicalization\|Mode\|SubDomains\|Socket\|SoftwareHeader\|UserID\|UMask/d" ${ MYVEMAIL_OPENDKIM_CONF }
tee -a ${ MYVEMAIL_OPENDKIM_CONF } >/dev/null <<- 'opendkim.co nf'
Canonicalization relaxed/simple
Mode sv
SubDomains no
Socket local:/var/spool/postfix/opendkim/opendkim.sock
SoftwareHeader yes
UserID opendkim
UMask 007
# Map domains in "from" addresses to keys used to sign messages
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
# Hosts to ignore when verifying signatures
ExternalIgnoreList /etc/opendkim/trusted.hosts
# A set of internal hosts whose mail should be signed
InternalHosts /etc/opendkim/trusted.hosts
opendkim.conf
# trusted.hosts
cat >/etc/opendkim/trusted.hosts <<- trust ed.hosts
127.0.0.1
localhost
trusted.hosts
###############
#//
#// OpenDMARC
#//
###############
sed '/TrustedAuthservIDs\|AuthservID\|RejectFailures\|IgnoreAuthenticatedClients\|RequiredHeaders\|SPFSelfValidate\|Socket\|IgnoreHosts\|UMask\|UserID/d' \
-i ${ MYVEMAIL_OPENDMARC_CONF }
tee -a ${ MYVEMAIL_OPENDMARC_CONF } >/dev/null <<- 'opendmarc.co nf'
TrustedAuthservIDs { { HOSTNAME} }
AuthservID OpenDMARC
RejectFailures true
IgnoreAuthenticatedClients true
RequiredHeaders true
SPFSelfValidate true
Socket local:/var/spool/postfix/opendmarc/opendmarc.sock
IgnoreHosts /etc/opendmarc/ignore.hosts
UserID opendmarc
UMask 0002
opendmarc.conf
echo '127.0.0.1' | tee -a /etc/opendmarc/ignore.hosts >/dev/null
###############
#//
#// Nginx
#//
###############
# php-fpm sock
cat >$( find /etc/php* -type d \( -name "pool.d" -o -name "php-fpm.d" \) ) /zz-listen.conf <<- php -fpm.sock
listen = 127.0.0.1:9000
user = ${ MYVEMAIL_NGINX_USERGROUP }
group = ${ MYVEMAIL_NGINX_USERGROUP }
listen.owner = ${ MYVEMAIL_NGINX_USERGROUP }
listen.group = ${ MYVEMAIL_NGINX_USERGROUP }
listen.mode = 0660
php-fpm.sock
# proxy_params
tee /etc/nginx/proxy_params >/dev/null <<'PROXY'
proxy_set_header Host $http_host ;
proxy_set_header X-Real-IP $remote_addr ;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;
proxy_set_header X-Forwarded-Proto $scheme ;
PROXY
# Roundcube/Postfixadmin virtual proxy
tee $( find /etc/nginx -type f -name "default*" ) >/dev/null <<- 'ngin x'
upstream php-handler {
server 127.0.0.1:9000;
}
server {
2025-03-05 03:10:16 +00:00
listen { { MYVEMAIL_PORT} } default_server;
2024-08-09 12:50:33 +00:00
server_name _;
index index.php index.html;
error_log /var/log/nginx/roundcube_error.log;
access_log /var/log/nginx/roundcube_access.log;
root /usr/share/webapps/roundcube;
# Postfixadmin
location ^~ /admin/ {
proxy_pass http://127.0.0.1:12000/;
include proxy_params;
}
# Roundcube
location ~ \. php$ {
client_max_body_size 0;
try_files $uri = 404;
fastcgi_split_path_info ^( .+\. php) ( /.+) $;
fastcgi_pass php-handler;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root $fastcgi_script_name ;
fastcgi_param PATH_INFO $fastcgi_path_info ;
}
}
server {
listen 12000;
root /usr/share/webapps/postfixadmin/public/;
index index.php index.html;
error_log /var/log/nginx/postfixadmin_error.log;
access_log /var/log/nginx/postfixadmin_access.log;
location / {
try_files $uri $uri / /index.php;
}
location ~ ^/( .+\. php) $ {
try_files $uri = 404;
fastcgi_pass php-handler;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root $fastcgi_script_name ;
include /etc/nginx/fastcgi_params;
}
}
nginx
###############
#//
#// Postwhite
#//
###############
cd /usr/local/bin
git clone --quiet https://github.com/spf-tools/spf-tools.git
git clone --quiet https://github.com/stevejenkins/postwhite.git
cp /usr/local/bin/postwhite/postwhite.conf /etc
2024-08-19 01:49:34 +00:00
###############
#//
#// Syslog
#//
###############
2025-02-25 22:34:27 +00:00
mkdir -p /var/log/mail/
cat >/etc/syslog.conf <<- sys log
mail.info /var/log/mail/maillog
mail.* /var/log/mail/maillog.debug
syslog