Support #653
Updated by Daniel Curtis over 9 years ago
{{>toc}} This is a guide on installing Dovecot and Postfix with Nginx, PostgreSQL, Maia Mailguard , Postfixadmin, and SpamAssassin on FreeBSD. This guide is adapted from the mail server setup at "purplehat.org":http://www.purplehat.org/?page_id=4 h2. Prepare the System * Make sure the system is up to date: <pre> pkg update && pkg upgrade </pre> * Install portmaster and screen: <pre> pkg install portmaster screen </pre> * Update the ports tree: <pre> portsnap fetch extract pkg2ng </pre> h2. Configure the Ports * This builds ClamAV to allow our “vscan” user access to it. Add ClamAV build options to @/etc/make.conf@ file: <pre> echo "CLAMAVUSER=vscan" >> /etc/make.conf echo "CLAMAVGROUP=vscan" >> /etc/make.conf </pre> * Add BATCH option to @/etc/make.conf@ file: <pre> echo "BATCH=yes" >> /etc/make.conf </pre> * Edit pear-Net_SMTP installation menu: <pre> cd /usr/ports/net/pear-Net_SMTP make config </pre> #* *NOTE*: Make sure *[X]PEAR_AUTH_SASL* is selected. * Edit pear-Auth Options installation menu: <pre> cd /usr/ports/security/pear-Auth make config </pre> #* *NOTE*: Make sure *[X]PEAR_DB* and *[X]PEAR_LOG* are selected. * Edit pear-Log installation menu: <pre> cd /usr/ports/sysutils/pear-Log make config </pre> #* *NOTE*: Make sure *[X]PEAR_DB* is selected. * Edit Dovecot installation menu: <pre> cd /usr/ports/mail/dovecot2 make config </pre> #* *NOTE*: Make sure *[X]PGSQL* is selected. * Edit Postfix installation menu: <pre> cd /usr/ports/mail/postfix make config </pre> #* *NOTE*: Make sure *[X]BDB*, *[X]PGSQL*, *[X]TLS*, *[X]VDA* and *[X]DOVECOT2* are selected. * Edit Postfixadmin installation menu: <pre> cd /usr/ports/mail/postfixadmin make config </pre> *NOTE*: Make sure *[X]PGSQL* is selected. * Edit SpamAssassin installation menu: <pre> cd /usr/ports/mail/spamassassin make config </pre> #* *NOTE*: Make sure *[X]PGSQL*, *[X]DKIM*, *[X]RAZOR*, *[X]RELAY_COUNTRY* and *[X]SPF_QUERY* are selected. * Edit Maia-Mailguard installation menu: <pre> cd /usr/ports/security/maia make config </pre> #* *NOTE*: Make sure the *[X]DOVECOT2*, *[X]FUZZYOCR*, *[X]PGSQL*, *[X]PFA*, *[X]POSTFIX* and *[X]WEBHOST* options are selected. Also make sure to unset the *[ ]MYSQL* option. Feel free to select any additional options you may want. h2. Install Maia Mailguard * Install Maia-Mailguard: <pre> portmaster security/maia </pre> * Set password for “vscan” user to *SuperSecretPassword*: <pre> passwd vscan </pre> h2. Install PostgreSQL * This environment will be setup with PostgreSQL 9.4: <pre> portmaster databases/postgresql94-server </pre> * Login to PostgreSQL: <pre> sudo -u postgres psql -d template1 </pre> * Create a user for maiauser: <pre> CREATE USER maiauser CREATEDB; ALTER ROLE maiauser WITH PASSWORD 'SuperSecretPassword'; </pre> * Create the maiadb database & grant all privileges on database <pre> CREATE DATABASE maiadb OWNER maiauser; </pre> * Quit the database session <pre> \q </pre> * Try connecting to the new database with the new user <pre> sudo -u maiauser -H psql -d maiadb </pre> * Quit the database session <pre> \q </pre> * Populate the database: <pre> cd /usr/local/share/doc/maia psql -h pg.example.com -U maiauser -W maiadb < maia-pgsql.sql </pre> h2. Configure Dovecot * Install Dovecot Pigeonhole: <pre> portmaster mail/dovecot2-pigeonhole security/bcrypt </pre> * Edit /etc/rc.conf so Dovecot starts at boot: <pre> echo 'dovecot_enable="YES"' >> /etc/rc.conf </pre> * Copy Dovecot configuration files: <pre> cd /usr/local/etc/dovecot/example-config cp -Rp * ../ </pre> h3. Dovecot auth config file * Edit the dovecot auth config file: <pre> vi /usr/local/etc/dovecot/conf.d/10-auth.conf </pre> #* And edit the following: <pre> ... disable_plaintext_auth = no ... auth_mechanisms = plain login ... #!include auth-system.conf.ext !include auth-sql.conf.ext </pre> h3. Dovecot mail config file * Edit the dovecot dovecor mail config file: <pre> vi /usr/local/etc/dovecot/conf.d/10-mail.conf </pre> #* And modify the following: <pre> ... mail_location = maildir:/usr/local/virtual/%d/%n ... namespace inbox { type = private separator = / mailbox Sent { auto = subscribe special_use = \Sent } mailbox Drafts { auto = subscribe special_use = \Drafts } mailbox Trash { auto = subscribe special_use = \Trash } mailbox Spam { auto = subscribe special_use = \Junk } ... first_valid_uid = 110 last_valid_uid = 110 ... first_valid_gid = 110 last_valid_gid = 110 ... mail_plugins = mail_log notify ... </pre> h3. Dovecot master config file * Edit the dovecot master config file: <pre> vi /usr/local/etc/dovecot/conf.d/10-master.conf </pre> #* And modify the following <pre> ... unix_listener auth-userdb { mode = 0660 user = vscan group = vscan } #Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } ... </pre> h3. Dovecot SSL config file * Edit the dovecot ssl config file: <pre> vi /usr/local/etc/dovecot/conf.d/10-ssl.conf </pre> #* And modify the following: <pre> ... ssl = yes ... ssl_cert = </usr/local/etc/ssl/mail.example.com.crt ssl_key = </usr/local/etc/ssl/mail.example.com.key ... ssl_ca = </usr/local/etc/ssl/mail.example.com.crt ... ssl_verify_client_cert = yes ... ssl_protocols = !SSLv2 !SSLv3 ... </pre> * Edit the dovecot lda config file: <pre> vi /usr/local/etc/dovecot/conf.d/15-lda.conf </pre> #* And modify the following: <pre> ... postmaster_address = postmaster@example.com ... hostname = mail.example.com ... sendmail_path = /usr/local/sbin/sendmail ... lda_mailbox_autocreate = yes ... protocol lda { # Space separated list of plugins to load (default is global mail_plugins). mail_plugins = $mail_plugins sieve ... </pre> h3. Dovecot IMAP config file * Edit the dovecot imap config file: <pre> vi /usr/local/etc/dovecot/conf.d/20-imap.conf </pre> #* And modify the following: <pre> ... protocol imap { # Space separated list of plugins to load (default is global mail_plugins). mail_plugins = $mail_plugins quota imap_quota zlib ... </pre> h3. Dovecot POP3 config file * Edit the dovecot pop3 config file: <pre> vi /usr/local/etc/dovecot/conf.d/20-pop3.conf </pre> #* And modify the following: <pre> ... pop3_client_workarounds = outlook-no-nuls oe-ns-eoh ... mail_plugins = $mail_plugins ... </pre> h3. Dovecot plugin config file * Edit the dovecot plugin config file: <pre> vi /usr/local/etc/dovecot/conf.d/90-plugin.conf </pre> #* And modify the following: <pre> ... plugin { #setting_name = value expire = Trash mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename mail_log_fields = uid box msgid size } plugin { sieve = /usr/local/virtual/home/%d/%n/.dovecot.sieve sieve_dir = /usr/local/virtual/home/%d/%n/sieve sieve_global_path = /usr/local/virtual/home/default.sieve mail_home = /usr/local/virtual/home/%d/%n } ... </pre> h3. Dovecot quota config file * Edit the dovecot quota config file: <pre> vi /usr/local/etc/dovecot/conf.d/90-quota.conf </pre> #* And modify the following: <pre> ... service quota-warning { executable = script /usr/local/bin/quota-warning.sh user = dovecot unix_listener quota-warning { user = vscan } } ... (Add to end of file...) plugin { #Where is quota applied ? quota = maildir:User quota # the default quota storage bytes, overrides are fetched from userdb [userdb_quota_ruleX] quota_rule = *:storage=1G #Storage bytes overrides quota_rule2 = Trash:storage=+30%% quota_rule3 = Sent:storage=+30%% quota_warning = storage=90%% quota-warning 90 %u quota_warning2 = storage=75%% quota-warning 75 %u #What message to send to IMAP clients (and SMTP senders) when quota is exceeded? quota_exceeded_message = Storage quota for this account has been exceeded, please try again later. } ... </pre> h3. Setup the Virtual Mail User * Create Sieve home directory: <pre> mkdir -p /usr/local/virtual/home </pre> * Create the default.sieve file: <pre> vi /usr/local/virtual/home/default.sieve </pre> #* And add the following: <pre> require ["fileinto"]; # rule:[Spam] if header :contains "X-Spam-Status" "Yes" { fileinto "Spam"; stop; } </pre> * Run the sievec command against our default sieve file: <pre> sievec /usr/local/virtual/home/default.sieve </pre> * Set proper permissions on our virtual directory: <pre> chown -R vscan:vscan /usr/local/virtual chmod 0750 /usr/local/virtual </pre> h3. Dovecot SQL config file * Edit the dovecot sql config file: <pre> vi /usr/local/etc/dovecot/dovecot-sql.conf.ext </pre> #* And modify the following: <pre> ... driver = pgsql ... connect = host=pg.example.com dbname=postfix user=postfix password=postfix_sql_password ... default_pass_scheme = BLF-CRYPT ... password_query = SELECT password, CONCAT('*:bytes=', quota) AS userdb_quota_rule FROM mailbox WHERE username = '%u' AND active = '1' ... user_query = SELECT CONCAT('/usr/local/virtual/', maildir) as home, 110 AS uid, 110 AS gid, CONCAT('*:bytes=', quota) AS quota_rule \ FROM mailbox WHERE username = '%u' AND active = '1' ... </pre> #* *NOTE*: The user_query line contains a bit in the query to allow Dovecot to return quota usage. If you don’t want or don’t need quota usage returned, you can just remove that bit from the query… h3. Main Dovecot config file * Edit the main dovecot config file: <pre> vi /usr/local/etc/dovecot/dovecot.conf </pre> #* And modify the following: <pre> ... protocols = imap pop3 sieve ... login_greeting = example.com Mail Server Ready... ... </pre> h3. Setup SSL key * Add the dovecot user to vscan group for LDA/delivery: <pre> pw usermod dovecot -G vscan </pre> * Create SSL/TLS key and CSR to have signed for a certificate for secure connections: <pre> cd /usr/local/etc/ssl openssl req -sha512 -out mail.example.com.csr -new -newkey rsa:4096 -nodes -keyout mail.example.com.key </pre> h2. Configure Postfix * Disable Sendmail and start Postfix at boot: <pre> echo 'sendmail_enable="NO"' >> /etc/rc.conf echo 'sendmail_submit_enable="NO"' >> /etc/rc.conf echo 'sendmail_outbound_enable="NO"' >> /etc/rc.conf echo 'sendmail_msp_queue_enable="NO"' >> /etc/rc.conf echo 'postfix_enable="YES"' >> /etc/rc.conf </pre> * Create and add Postfix stuffs to the /etc/periodic.conf file: <pre> echo 'daily_clean_hoststat_enable="NO"' >> /etc/periodic.conf echo 'daily_status_mail_rejects_enable="NO"' >> /etc/periodic.conf echo 'daily_status_include_submit_mailq="NO"' >> /etc/periodic.conf echo 'daily_submit_queuerun="NO"' >> /etc/periodic.conf </pre> h3. Main Postfix config file * Edit the main postfix config file: <pre> vi /usr/local/etc/postfix/main.cf </pre> #* And modify the following: <pre> ... soft_bounce = no # SASL CONFIG broken_sasl_auth_clients = yes smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_hostname, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_hostname, reject_rbl_client bl.spamcop.net, reject_rbl_client sbl-xbl.spamhaus.org, reject_rbl_client zen.spamhaus.org, reject_rbl_client dnsbl.sorbs.net, reject_rbl_client rhsbl.sorbs.net, reject_rbl_client db.wpbl.info, reject_rbl_client cbl.abuseat.org, reject_rbl_client proxies.blackholes.wirehub.net, reject_rbl_client query.bondedsender.org smtpd_sasl_auth_enable = yes smtpd_sasl_authenticated_header = yes smtpd_sasl_local_domain = $myhostname smtpd_sasl_security_options = noanonymous smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth # TLS CONFIG smtp_use_tls = yes smtpd_use_tls = yes smtp_tls_note_starttls_offer = yes smtpd_tls_key_file = /usr/local/etc/ssl/mail.example.com.key /usr/local/etc/ssl/postfix/smtpd.pem smtpd_tls_cert_file = /usr/local/etc/ssl/mail.example.com.crt /usr/local/etc/ssl/postfix/smtpd.pem smtpd_tls_CAfile = /usr/local/etc/ssl/postfix/smtpd.pem smtpd_tls_loglevel = 0 smtpd_tls_received_header = yes smtpd_tls_session_cache_timeout = 3600s smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3 tls_random_source = dev:/dev/urandom #PostgreSQL Configuration virtual_alias_maps = proxy:pgsql:/usr/local/etc/postfix/pgsql_virtual_alias_maps.cf proxy:mysql:/usr/local/etc/postfix/mysql_virtual_alias_maps.cf virtual_gid_maps = static:125 virtual_mailbox_base = /usr/local/virtual virtual_mailbox_domains = proxy:pgsql:/usr/local/etc/postfix/pgsql_virtual_domains_maps.cf proxy:mysql:/usr/local/etc/postfix/mysql_virtual_domains_maps.cf virtual_mailbox_limit = 51200000 virtual_mailbox_maps = proxy:pgsql:/usr/local/etc/postfix/pgsql_virtual_mailbox_maps.cf proxy:mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_maps.cf virtual_minimum_uid = 125 virtual_transport = dovecot virtual_uid_maps = static:125 # Additional for quota support virtual_mailbox_limit_maps = proxy:pgsql:/usr/local/etc/postfix/pgsql_virtual_mailbox_limit_maps.cf proxy:mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_limit_maps.cf proxy_read_maps = $local_recipient_maps $mydestination $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 $mynetworks $virtual_mailbox_limit_maps virtual_mailbox_limit_override = yes virtual_maildir_limit_message = Sorry, this user has overdrawn their diskspace quota. Please try again later. virtual_overquota_bounce = yes maximal_queue_lifetime = 4h bounce_queue_lifetime = 4h # Adjusted message size limit. message_size_limit = 25600000 ... myhostname = mail.example.com host.domain.tld ... mydomain = example.com domain.tld ... mydestination = localhost.$mydomain, localhost ... relay_domains = proxy:pgsql:/usr/local/etc/postfix/pgsql_relay_domains_maps.cf proxy:mysql:/usr/local/etc/postfix/mysql_relay_domains_maps.cf ... relay_recipient_maps = proxy:pgsql:/usr/local/etc/postfix/pgsql_virtual_mailbox_maps.cf proxy:mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_maps.cf ... # TRANSPORT MAP # # See the discussion in the ADDRESS_REWRITING_README document. dovecot_destination_recipient_limit = 1 ... </pre> h3. Master Postfix config file * Edit the master postfix config file: <pre> /usr/local/etc/postfix/master.cf </pre> #* And modify the following: <pre> ... submission inet n - n - - smtpd -o smtpd_enforce_tls=yes ... -o smtpd_sasl_auth_enable=yes ... -o smtpd_client_restrictions=permit_sasl_authenticated,reject ... -o smtpd_relay_restrictions=permit_sasl_authenticated,reject ... smtps inet n - n - - smtpd ... -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes ... -o smtpd_client_restrictions=permit_sasl_authenticated,reject ... -o smtpd_relay_restrictions=permit_sasl_authenticated,reject ... (At the end of the file, add) dovecot unix - n n - - pipe flags=DRhu user=vscan:vscan argv=/usr/local/libexec/dovecot/deliver -f ${sender} -d ${recipient} ... </pre> h3. PostgreSQL virtual alias map file * Create the and edit postgresql virtual alias map file: <pre> vi /usr/local/etc/postfix/pgsql_virtual_alias_maps.cf </pre> #* And add the following: <pre> user = postfix password = postfix_sql_password hosts = localhost dbname = postfix query = SELECT goto FROM alias WHERE address='%s' AND active = '1' </pre> h3. PostgreSQL virtual domain map file * Create the and edit postgresql virtual domain map file: <pre> vi /usr/local/etc/postfix/pgsql_virtual_domains_maps.cf </pre> #* And add the following: <pre> user = postfix password = postfix_sql_password hosts = localhost dbname = postfix query = SELECT domain FROM domain WHERE domain='%s' and backupmx = '0' and active = '1' </pre> h3. PostgreSQL virtual mailbox map file * Create the and edit postgresql virtual mailbox map file: <pre> vi /usr/local/etc/postfix/pgsql_virtual_mailbox_maps.cf </pre> #* And add the following: <pre> user = postfix password = postfix_sql_password hosts = localhost dbname = postfix query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1' </pre> h3. PostgreSQL virtual mailbox limit map file * Create the postgresql virtual mailbox limit map and edit file: <pre> vi /usr/local/etc/postfix/pgsql_virtual_mailbox_limit_maps.cf </pre> #* And add the following: <pre> user = postfix password = postfix_sql_password hosts = localhost dbname = postfix query = SELECT quota FROM mailbox WHERE username='%s' </pre> h3. PostgreSQL relay domain map file * Create and edit the postgresql relay domain map file: <pre> vi /usr/local/etc/postfix/pgsql_relay_domains_maps.cf </pre> #* And add the following: <pre> user = postfix password = postfix_sql_password hosts = localhost dbname = postfix query = SELECT domain FROM domain WHERE domain='%s' and backupmx = '1' </pre> h3. Finish configuring Postfix * Secure Postfix’s PostgreSQL files: <pre> chmod 640 /usr/local/etc/postfix/pgsql_* chgrp postfix /usr/local/etc/postfix/pgsql_* </pre> * Create the transport file and update the transport map database: <pre> touch /usr/local/etc/postfix/transport postmap /usr/local/etc/postfix/transport </pre> * Edit aliases file, uncomment and change “root” to an email address you want system messages to be mailed to: <pre> vi /etc/aliases </pre> #* And modify the following: <pre> root: user@example.com </pre> * Create the aliases.db file: <pre> /usr/bin/newaliases </pre> h2. Install Nginx * Install Nginx <pre> portmaster www/nginx </pre> * Start and enable nginx at boot: <pre> echo 'nginx_enable="YES"' >> /etc/rc.conf service nginx start </pre> * Create a configuration directory to make managing individual server blocks easier <pre> mkdir /usr/local/etc/nginx/conf.d </pre> * Edit the main nginx config file: <pre> vi /usr/local/etc/nginx/nginx.conf </pre> #* And strip down the config file and add the include statement at the end to make it easier to handle various server blocks: <pre> #user nobody; worker_processes 1; error_log /var/log/nginx-error.log; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; # Load config files from the /etc/nginx/conf.d directory include /usr/local/etc/nginx/conf.d/*.conf; } </pre> h2. Install PHP * Install PHP 5.6: <pre> portmaster lang/php56 </pre> * Configure the default PHP settings <pre> cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini </pre> * Edit PHP config file: <pre> vi /usr/local/etc/php.ini </pre> #* And modify the following: <pre> ... ; UNIX: "/path1:/path2" include_path = "." ... ; Maximum allowed size for uploaded files. ; http://php.net/upload-max-filesize upload_max_filesize = 25M ... date.timezone = "America/Los_Angeles" </pre> h3. Configure PHP-FPM * Edit @/usr/local/etc/php-fpm.conf@: <pre> vi /usr/local/etc/php-fpm.conf </pre> #* Make the following changes: <pre> events.mechanism = kqueue listen = /var/run/php-fpm.sock listen.owner = www listen.group = www listen.mode = 0666 </pre> * Start and enable PHP-FPM at boot: <pre> echo 'php_fpm_enable="YES"' >> /etc/rc.conf service php-fpm start </pre> * Restart nginx: <pre> service nginx restart </pre> h2. Resources * http://www.purplehat.org/?page_id=4 * http://www.maiamailguard.com/maia/wiki/Install * https://wiki.gentoo.org/wiki/Complete_Virtual_Mail_Server/Postfix_to_Database