#!/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 mkdir /{run,etc}/{opendkim,opendmarc} >/dev/null 2>&1 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" # # Logging # postconf -e "maillog_file = /var/log/postfix.log" # 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" 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" # 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 postconf -e "smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unknown_sender_domain, reject_unknown_reverse_client_hostname, reject_unknown_client_hostname" postconf -e "smtpd_helo_required = yes" 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" # 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" postconf -e "postscreen_dnsbl_sites = bl.spameatingmonkey.net*2, bl.spamcop.net, dnsbl.sorbs.net" # zen.spamhaus.org*3, 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 tee -a /etc/postfix/master.cf >/dev/null <<- master.cf # 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 policyd-spf unix - n n - - spawn user=nobody argv=/usr/bin/perl ${MYVEMAIL_POLICYD} 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 # # Logging # echo "log_path = /var/log/dovecot.log" >/etc/dovecot/conf.d/10-logging.conf # 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 = /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.conf' 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 <<- trusted.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.conf' 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 <<- 'nginx' upstream php-handler { server 127.0.0.1:9000; } server { listen {{MYVEMAIL_PORT}} default_server; 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 ############### #// #// Syslog #// ############### mkdir -p /var/log/mail/ cat >/etc/syslog.conf <<- syslog mail.info /var/log/mail/maillog mail.* /var/log/mail/maillog.debug syslog