===== Requisits ===== ==== Firsts remarks ==== - By initial choice, user mail directories are composed like this : /data/vmail/domainname/username/ - You must have a valid FQDN with the corresponding reverse DNS. - You must have SSL/TLS certificates. - Postfix configuration here is not suited to high traffic servers (ISP), for this target, see : hash_queue_depth and http://www.postfix.org/TUNING_README.html ==== Variables ==== RQ : change the 3 usernames and their passwords, the mail domain and the server hostname # for postfixadmin export PFADBNAME="db_pfadmin" export PFADBUSER="pfadmin" export PFADBPW="PASS1_CHANGEME" export PFARODBNAME="db_pfadmin" export PFARODBUSER="pfa_ro" export PFARODBPW="PASS2_CHANGEME" export PFARWDBNAME="db_pfadmin" export PFARWDBUSER="pfa_rw" export PFARWDBPW="PASS3_CHANGEME" export DEFAULT_MAIL_DOMAIN="" export MAIL_SERVER_HOSTNAME="" export MAIL_SERVER_FQDN="${MAIL_SERVER_HOSTNAME}.${DEFAULT_MAIL_DOMAIN}" ==== Begin safely ==== Server update and resolvconf installation : apt-get update apt-get upgrade apt-get install resolvconf ==== Network interfaces :==== vi /etc/network/interfaces Verify/add : "dns-nameservers 127.0.0.1 " vi /etc/hosts 127.0.0.1 localhost ==== DNS cache ==== apt-get install bind9 cp -a /etc/bind/named.conf.local /etc/bind/named.conf.local_ sed -i "s/\/\/include \"\/etc\/bind\/zones\.rfc1918\"\;/include \"\/etc\/bind\/zones\.rfc1918\"\;/g" /etc/bind/named.conf.local /etc/init.d/bind9 stop /etc/init.d/bind9 start IF NO IPV6 (RQ bug on jessie : https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=767798) cp -a /etc/default/bind9 /etc/default/bind9_ sed -i "s/RESOLVCONF=no/RESOLVCONF=yes/g" /etc/default/bind9 sed -i "s/OPTIONS=\"-u bind\"/OPTIONS=\"-4 -u bind\"/g" /etc/default/bind9 /etc/init.d/bind9 stop /etc/init.d/bind9 start sleep 3 rndc flush ==== Network restart ==== /etc/init.d/networking stop ; /etc/init.d/networking start Rq : if the FQDN was changed, restart the server. ==== mysql-server installation ==== apt-get install mysql-server # New mysql superuser password : enter and keep safely somwhere (ex : keepass) apt-get install dbconfig-common ===== postfixadmin / postfix / dovecot installation ===== ==== DBs configuration ==== DBs and users creation for postfixadmin echo "create database $PFADBNAME;" > /opt/create_db_pfa echo "grant usage on *.* to $PFADBUSER@localhost identified by '$PFADBPW';" >> /opt/create_db_pfa echo "grant all privileges on $PFADBNAME.* to $PFADBUSER@localhost ;" >> /opt/create_db_pfa echo "grant usage on *.* to $PFARODBUSER@localhost identified by '$PFARODBPW';" >> /opt/create_db_pfa echo "GRANT SELECT ON $PFARODBNAME.* TO $PFARODBUSER@localhost;" >> /opt/create_db_pfa echo "grant usage on *.* to $PFARWDBUSER@localhost identified by '$PFARWDBPW';" >> /opt/create_db_pfa echo "GRANT SELECT,UPDATE,INSERT ON $PFARWDBNAME.* TO $PFARWDBUSER@localhost;" >> /opt/create_db_pfa cat /opt/create_db_pfa | mysql --defaults-extra-file=/etc/mysql/debian.cnf rm /opt/create_db_pfa dbconfig preconfiguration for postfixadmin : cat << 'EOF' > /etc/dbconfig-common/postfixadmin.conf dbc_install='true' dbc_upgrade='true' dbc_remove='' dbc_dbtype='mysql' dbc_dbuser='' dbc_dbpass='' dbc_dbserver='' dbc_dbport='' dbc_dbname='' dbc_dbadmin='root' dbc_basepath='' dbc_ssl='' dbc_authmethod_admin='' dbc_authmethod_user='' EOF sed -i "s/dbc_dbname='.*$/dbc_dbname='$PFADBNAME'/g" /etc/dbconfig-common/postfixadmin.conf sed -i "s/dbc_dbuser='.*$/dbc_dbuser='$PFADBUSER'/g" /etc/dbconfig-common/postfixadmin.conf sed -i "s/dbc_dbpass='.*$/dbc_dbpass='$PFADBPW'/g" /etc/dbconfig-common/postfixadmin.conf ==== postfixadmin installation ==== apt-get install postfixadmin # auto reconfigure : apache2 # reconfigure postfixadmin with dbconfig-common ? yes # DB server to use with postfixadmin : mysql # DB admin password : enter mysql superadmin password # choose to install the package maintainer configuration file ==== postfix installation ==== if [ -e /var/log/exim4/paniclog ]; then rm /var/log/exim4/paniclog; fi apt-get install postfix postfix-mysql dovecot-common # mail server conf type : internet site # mailserver name : entrer the public FQDN of the mailserver apt-get remove --purge exim4 exim4-base exim4-config exim4-daemon-heavy exim4-daemon-light exim4-config-2 exim4-localscanapi-1.0 exim4-localscanapi-1.1 rm -rf /etc/exim4 ==== dovecot installation ==== apt-get install dovecot-mysql dovecot-sieve dovecot-imapd dovecot-lmtpd dovecot-managesieved ==== Apache initial configuration ==== see corresponding howto ==== postfixadmin configuration ==== cp -a /etc/apache2/conf-available/postfixadmin.conf /etc/apache2/conf-available/postfixadmin.conf_ sed -i "s/Alias \/postfixadmin .*$/Alias \/admin_pfa \/usr\/share\/postfixadmin/g" /etc/apache2/conf-available/postfixadmin.conf cp -a /etc/postfixadmin/dbconfig.inc.php /etc/postfixadmin/dbconfig.inc.php_ sed -i "s|\$dbtype=.*|\$dbtype='mysqli';|g" /etc/postfixadmin/dbconfig.inc.php /etc/init.d/apache2 stop /etc/init.d/apache2 start # verify that the webserver is responding : http://fqdn/admin_pfa vi /etc/postfixadmin/config.inc.php # change these fields : XXX #$CONF['postfix_admin_url'] = '/postfixadmin'; $CONF['postfix_admin_url'] = '/admin_pfa'; $CONF['default_language'] = 'fr'; $CONF['admin_email'] = 'postmaster@'; $CONF['default_aliases'] = array ( 'abuse' => 'admin@', 'hostmaster' => 'admin@', 'postmaster' => 'admin@', 'webmaster' => 'admin@', 'admin' => 'admin@' ); $CONF['aliases'] = '0'; $CONF['mailboxes'] = '0'; $CONF['maxquota'] = '1000'; $CONF['domain_path'] = 'YES'; $CONF['domain_in_mailbox'] = 'NO'; ** Todo by hand :** * RQ : if you need to use hook scripts, you have to configure a sudoer : "wwwrun ALL = (courier) NOPASSWD: /usr/local/bin/postfixadmin-mailbox-postcreation.sh" * go to postfixadmin web interface : http://fqdn/admin_pfa/setup.php * generate a new admin password, and keep it safely somewhere, click on "generate passwork hash" * the web interface proposes to modify the conf file : /etc/postfixadmin/config.inc.php - modify line : $CONF['setup_password'] = 'changeme'; * the web interface proposes to create a new superadmin, do it and keep safely password somewhere * verify the installation by going to : http://fqdn/admin_pfa/ ==== postfix configuration ==== service postfix stop === virtual mappings with mysql=== # initial backup cd /etc/postfix mkdir origin cp -ar ./* origin # postfixadmin compatible mysql queries for postfix # RQ : we need exported variables we created before for mysql configuration mkdir /etc/postfix/sql export PFXSQLCONFDIR=/etc/postfix/sql echo "# mysql_virtual_alias_maps user = $PFARODBUSER password = $PFARODBPW hosts = localhost dbname = $PFARODBNAME query = SELECT goto FROM alias WHERE address='%s' AND active = '1' #expansion_limit = 100 " > $PFXSQLCONFDIR/mysql_virtual_alias_maps.cf echo "# mysql_virtual_alias_domain_maps user = $PFARODBUSER password = $PFARODBPW hosts = localhost dbname = $PFARODBNAME 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' " > $PFXSQLCONFDIR/mysql_virtual_alias_domain_maps.cf echo "# mysql_virtual_alias_domain_catchall_maps # handles catch-all settings of target-domain user = $PFARODBUSER password = $PFARODBPW hosts = localhost dbname = $PFARODBNAME 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' " > $PFXSQLCONFDIR/mysql_virtual_alias_domain_catchall_maps.cf echo "# mysql_virtual_domains_maps user = $PFARODBUSER password = $PFARODBPW hosts = localhost dbname = $PFARODBNAME 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 " > $PFXSQLCONFDIR/mysql_virtual_domains_maps.cf echo "# mysql_virtual_mailbox_maps user = $PFARODBUSER password = $PFARODBPW hosts = localhost dbname = $PFARODBNAME query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1' #expansion_limit = 100 " > $PFXSQLCONFDIR/mysql_virtual_mailbox_maps.cf echo "# mysql_virtual_alias_domain_mailbox_maps user = $PFARODBUSER password = $PFARODBPW hosts = localhost dbname = $PFARODBNAME 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' " > $PFXSQLCONFDIR/mysql_virtual_alias_domain_mailbox_maps.cf echo "# mysql_virtual_mailbox_limit_maps user = $PFARODBUSER password = $PFARODBPW hosts = localhost dbname = $PFARODBNAME query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1' " > $PFXSQLCONFDIR/mysql_virtual_mailbox_limit_maps.cf echo "# mysql_virtual_sasl-sender-check user = $PFARODBUSER password = $PFARODBPW hosts = localhost dbname = $PFARODBNAME query = SELECT goto FROM alias WHERE address='%s' AND active="1" " > $PFXSQLCONFDIR/mysql_virtual_sasl-sender-check.cf chown -R root:postfix /etc/postfix/sql chmod -R 640 /etc/postfix/sql chmod 750 /etc/postfix/sql === Remove mail sender IP === cat << '__EOF__' >> /etc/postfix/postfix_header-checks.cf /^received: / IGNORE /^X-Sender: / IGNORE __EOF__ chown root:postfix /etc/postfix/sql chmod 640 /etc/postfix/postfix_header-checks.cf === Custom error messages - french === cat << '__EOF__' >> /etc/postfix/bounce.cf.fr # The failure template is used when mail is returned to the sender; # either the destination rejected the message, or the destination # could not be reached before the message expired in the queue. failure_template = < Cleanup the safe run postfix environment : rm /var/lib/postfix/* === main.cf file === vi /etc/postfix/main.cf # See /usr/share/postfix/main.cf.dist for a commented, more complete version ################################################# # Main domain & conf # myhostname = _MAIL_SERVER_FQDN_ mydomain = _DEFAULT_MAIL_DOMAIN_ myorigin = /etc/mailname mydestination = _MAIL_SERVER_FQDN_, localhost._DEFAULT_MAIL_DOMAIN_, localhost relayhost = inet_interfaces = all mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases # Recipient delimiter : + is often refused, _ is more accepted recipient_delimiter = _ # Strict address format in addresses strict_rfc821_envelopes = yes # Maximum postmaster notifications notify_classes = bounce, 2bounce, delay, policy, protocol, resource, software # Mail maximum size in Bytes message_size_limit = 67108864 mailbox_size_limit = 0 ################################################################################ # SSL/TLS # TLS parameters smtpd_tls_cert_file=/etc/ssl/certs/ smtpd_tls_key_file=/etc/ssl/private/ smtpd_use_tls=yes smtpd_tls_auth_only = yes ################################################################################ # Sender restrictions # Only registered users can send emails smtpd_sender_login_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_sasl-sender-check.cf smtpd_reject_unlisted_sender = yes # Have a look : http://www.postfix.org/SMTPD_ACCESS_README.html smtpd_client_restrictions = smtpd_sender_restrictions = permit_sasl_authenticated smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unverified_recipient reject_non_fqdn_recipient ## reject_non_fqdn_sender reject_non_fqdn_helo_hostname reject_invalid_helo_hostname ## reject_unknown_sender_domain reject_unknown_recipient_domain reject_unlisted_recipient reject_unlisted_sender reject_unauth_destination reject_unlisted_sender reject_unauth_destination reject_rbl_client bl.spamcop.net reject_rbl_client zen.spamhaus.org permit smtpd_data_restrictions = reject_unauth_pipelining reject_multi_recipient_bounce permit # hide the sender IP header_checks = regexp:/etc/postfix/postfix_header-checks.cf ################################################################################ # SASL Auth smtpd_sasl_auth_enable = yes smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_security_options = noanonymous smtpd_sasl_local_domain = smtpd_sasl_authenticated_header = yes broken_sasl_auth_clients = yes ################################################################################ # mail delivery #mailbox_transport = dovecot #mailbox_command = procmail -a "$EXTENSION" #mailbox_command = /usr/lib/dovecot/deliver -n -m "$EXTENSION" #mailbox_size_limit = 0 #dovecot_destination_recipient_limit = 1 virtual_transport = lmtp:unix:private/dovecot-lmtp ################################################ # Virtual mailboxes virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf virtual_alias_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf ################################################################################ # misc config # No local user, no need to notify them. biff = no # Appending .domain is the MUA's job. append_dot_mydomain = no # messages d'erreur (bounces) en français : bounce_template_file = /etc/postfix/bounce.cf.fr # warn the user of non distributed mail after 24h of tries (but keep trying during 5 days) delay_warning_time = 24h # No need for documentation readme_directory = no # HELO Stuff smtpd_banner = $myhostname ESMTP $mail_name smtpd_helo_required = yes ################################################ # Proxy # Proxy service feeding (important because of the chrooted environment in Debian) proxy_read_maps = $local_recipient_maps $mydestination $mynetworks $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $smtpd_sender_login_maps proxy_write_maps = $smtp_sasl_auth_cache_name $smtp_tls_session_cache_database $smtpd_tls_session_cache_database $lmtp_sasl_auth_cache_name $address_verify_map $postscreen_cache_map smtp_sasl_auth_cache_name = proxy:btree:${data_directory}/smtp_sasl_auth_cache_name smtp_tls_session_cache_database = proxy:btree:${data_directory}/smtp_tls_session_cache_database smtpd_tls_session_cache_database = proxy:btree:${data_directory}/smtpd_tls_session_cache_database lmtp_sasl_auth_cache_name = proxy:btree:${data_directory}/lmtp_sasl_auth_cache_name address_verify_map = proxy:btree:${data_directory}/address_verify_map postscreen_cache_map = proxy:btree:${data_directory}/postscreen_cache_map sed -i "s/_DEFAULT_MAIL_DOMAIN_/${DEFAULT_MAIL_DOMAIN}/g" /etc/postfix/main.cf sed -i "s/_MAIL_SERVER_HOSTNAME_/${MAIL_SERVER_HOSTNAME}/g" /etc/postfix/main.cf sed -i "s/_MAIL_SERVER_FQDN_/${MAIL_SERVER_FQDN}/g" /etc/postfix/main.cf === master.cf file === vi /etc/postfix/master.cf add : submission inet n - n - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_sasl_security_options=noanonymous -o smtpd_sasl_local_domain=$myhostname -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_sender_restrictions=reject_sender_login_mismatch -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject ==== dovecot configuration ==== === mysql / postfixadmin === cd /etc/dovecot mkdir origin cp -aR ./* origin echo " # postfixadmin database queries driver = mysql connect = host=localhost dbname=$PFARODBNAME user=$PFARODBUSER password=$PFARODBPW default_pass_scheme = MD5-CRYPT user_query = SELECT concat('/data/vmail/', maildir) AS home, 500 AS uid, 500 AS gid FROM mailbox WHERE username = '%u' password_query = SELECT username as user, password, concat('/data/vmail/', maildir) as userdb_home, 500 as userdb_uid, 500 as userdb_gid, CONCAT('dirsize:storage=', ROUND(quota / 1024) ) AS quota FROM mailbox WHERE username = '%u' AND active=1 " >> /etc/dovecot/dovecot-sql.conf.ext sed -i "s/#disable_plaintext_auth = yes/disable_plaintext_auth = yes/g" /etc/dovecot/conf.d/10-auth.conf sed -i "s/\!include auth-system.conf.ext/#\!include auth-system.conf.ext/g" /etc/dovecot/conf.d/10-auth.conf sed -i "s/#\!include auth-sql.conf.ext/\!include auth-sql.conf.ext/g" /etc/dovecot/conf.d/10-auth.conf sed -i "s/mail_location =.*$/mail_location = maildir:%h/g" /etc/dovecot/conf.d/10-mail.conf sed -i "s/#mail_privileged_group =/mail_privileged_group = mail/g" /etc/dovecot/conf.d/10-mail.conf #sed -i "s/#port = 993/port = 993/g" /etc/dovecot/conf.d/10-master.conf sed -i "s/unix_listener lmtp {/unix_listener \/var\/spool\/postfix\/private\/dovecot-lmtp {\n user = postfix\n group = postfix\n mode = 0600/g" /etc/dovecot/conf.d/10-master.conf sed -i "s/unix_listener auth-userdb {/unix_listener auth-userdb {\n user = vmail/g" /etc/dovecot/conf.d/10-master.conf sed -i "s/# Postfix smtp-auth/# Postfix smtp-auth\n unix_listener \/var\/spool\/postfix\/private\/auth {\n mode = 0666\n }/g" /etc/dovecot/conf.d/10-master.conf sed -i "s/service auth-worker {/service auth-worker {\n user = \$default_internal_user/g" /etc/dovecot/conf.d/10-master.conf sed -i "s/ssl = no/ssl=required/g" /etc/dovecot/conf.d/10-ssl.conf sed -i 's/#ssl_protocols = !SSLv2/ssl_protocols = !SSLv2/g' /etc/dovecot/conf.d/10-ssl.conf sed -i 's/#ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL/ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL/g' /etc/dovecot/conf.d/10-ssl.conf #sed -i "s/#postmaster_address =/postmaster_address = postmaster@/g" /etc/dovecot/conf.d/15-lda.conf #sed -i "s/#recipient_delimiter = +/#recipient_delimiter = +\nrecipient_delimiter = _/g" /etc/dovecot/conf.d/15-lda.conf sed -i "s/protocol lmtp {/protocol lmtp {\n postmaster_address = postmaster@\n mail_plugins = \$mail_plugins quota sieve /g" /etc/dovecot/conf.d/20-lmtp.conf sed -i "s/#recipient_delimiter = +/#recipient_delimiter = +\n recipient_delimiter = _/g" /etc/dovecot/conf.d/90-sieve.conf mkdir -p /data/vmail chmod 770 /data/vmail groupadd --gid 500 vmail useradd --system --uid 500 --gid 500 --home-dir /data/vmail --shell /sbin/nologin --comment "Virtual mailbox" vmail chown vmail:vmail /data/vmail ===== At the end... ===== **Do by hand :** * Edit /etc/postfix/main.cf and change certificates files paths * Edit /etc/dovecot/conf.d/10-ssl.conf and change certificates files paths * Edit /etc/dovecot/conf.d/15-lda.conf and /etc/dovecot/conf.d/20-lmtp.conf in order to change postmaster address # (re)start services tail -f /var/log/syslog & service dovecot stop service dovecot start service postfix start fg Add www-data alias echo "www-data: root" >> /etc/aliases echo "root: admin_@" >> /etc/aliases newaliases Final verification (all the chain) # stop mail services for SERVICE_ in postfix dovecot ; do service $SERVICE_ stop; done # start mail services for SERVICE_ in dovecot postfix; do service $SERVICE_ start; done ===== Not included for the moment : ==== * quota : table quota2 dans postfixadmin + option * group mailbox * lucene/solr * logging mysql