Project

General

Profile

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> 

 * 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> 

 h3. Setup Maia Database 

 * 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> 

 h3. Setup Postfix Database 

 * Create PostfixAdmin database, login to PostgreSQL: 
 <pre> 
 sudo -u postgres psql -d template1 
 </pre> 
 #* Create a user for postfix: 
 <pre> 
 CREATE USER postfix CREATEDB; 
 ALTER ROLE postfix WITH PASSWORD 'SuperSecretPostfixPassword'; 
 </pre> 
 #* Create the postfix database & grant all privileges on database 
 <pre> 
 CREATE DATABASE postfix OWNER postfix; 
 </pre> 
 #* Quit the database session 
 <pre> 
 \q 
 </pre> 

 * Try connecting to the new database with the new user 
 <pre> 
 sudo -u postfix -H psql -d postfix 
 </pre> 
 #* Quit the database session 
 <pre> 
 \q 
 </pre> 

 * Create PostgreSQL database and user for Roundcube *, login to PostgreSQL: 
 <pre> 
 sudo -u postgres psql -d template1 
 </pre> 
 #* Create a user for roundcubeuser: 
 <pre> 
 CREATE USER roundcubeuser CREATEDB; 
 ALTER ROLE roundcubeuser WITH PASSWORD 'SuperSecretRoundcubePassword'; 
 </pre> 
 #* Create the roundcubedb database & grant all privileges on database 
 <pre> 
 CREATE DATABASE roundcubedb OWNER roundcubeuser; 
 </pre> 
 #* Quit the database session 
 <pre> 
 \q 
 </pre> 

 * Try connecting to the new database with the new user 
 <pre> 
 sudo -u roundcubeuser -H psql -d roundcubedb 
 </pre> 
 #* Quit the database session 
 <pre> 
 \q 
 </pre> 

 h3. Setup Roundcube Database 

 * Create PostgreSQL database and user for Roundcube *, login to PostgreSQL: 
 <pre> 
 sudo -u postgres psql -d template1 
 </pre> 
 #* Create a user for roundcubeuser: 
 <pre> 
 CREATE USER roundcubeuser CREATEDB; 
 ALTER ROLE roundcubeuser WITH PASSWORD 'SuperSecretRoundcubePassword'; 
 </pre> 
 #* Create the roundcubedb database & grant all privileges on database 
 <pre> 
 CREATE DATABASE roundcubedb OWNER roundcubeuser; 
 </pre> 
 #* Quit the database session 
 <pre> 
 \q 
 </pre> 

 * Try connecting to the new database with the new user 
 <pre> 
 sudo -u roundcubeuser -H psql -d roundcubedb 
 </pre> 
 #* Quit the database session 
 <pre> 
 \q 
 </pre> 

 h2. Configure Dovecot 

 * Install Dovecot Pigeonhole: 
 <pre> 
 portmaster mail/dovecot2-pigeonhole 
 </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. Auth config 

 * 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. Mail config 

 * Edit the dovecot 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. Master config 

 * 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. LDA config 

 * 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. IMAP config  

 * 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. POP3 config 

 * 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. Plugin config 

 * 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. Quota config 

 * 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. SQL config 

 * 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=SuperSecretPostfixPassword 
 ... 
 default_pass_scheme = MD5 
 ... 
 password_query = SELECT password, '*:bytes=' || quota AS userdb_quota_rule FROM "mailbox" WHERE username = '%u' AND active = TRUE 
 ... 
 user_query = SELECT '/usr/local/virtual/' || maildir as home, 110 AS uid, 110 AS gid, '*:bytes=' || quota AS quota_rule FROM mailbox WHERE username = '%u' AND active = TRUE '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 config 

 * 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. SSL config 

 * 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> 

 h3. Setup SSL key 

 * 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> 

 * Send mail.example.com.csr to a Certificate Authority to have a signed certificate created, then create the certificate file:  
 <pre> 
 vi mail.example.com.crt 
 </pre> 
 #* *NOTE*: I use StartSSL, but there are many different CAs to choose from. 

 * Once the SSL certificate has been created on the mail server, download and add the intermediate certificate to the SSL certificate: 
 <pre> 
 fetch https://www.startssl.com/certs/sub.class1.server.ca.pem 
 cat sub.class1.server.ca.pem >> mail.example.com.crt 
 </pre> 

 h3. 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> 

 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 config 

 * 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 
 smtpd_tls_cert_file = /usr/local/etc/ssl/mail.example.com.crt 
 smtpd_tls_CAfile = /usr/local/etc/ssl/postfix/mail.example.com.crt 
 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 
 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 
 virtual_mailbox_limit = 51200000 
 virtual_mailbox_maps = proxy:pgsql:/usr/local/etc/postfix/pgsql_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_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 
 ... 
 mydomain = example.com 
 ... 
 mydestination = localhost.$mydomain, localhost 
 ... 
 relay_domains = proxy:pgsql:/usr/local/etc/postfix/pgsql_relay_domains_maps.cf 
 ... 
 relay_recipient_maps = proxy:pgsql:/usr/local/etc/postfix/pgsql_virtual_mailbox_maps.cf 
 ... 
 # TRANSPORT MAP 
  # 
  # See the discussion in the ADDRESS_REWRITING_README document. 
 dovecot_destination_recipient_limit = 1 
 ... 
 </pre> 

 h3. Master config 

 * 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. Virtual alias map 

 * Create the 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 = SuperSecretPostfixPassword 
 hosts = pg.example.com 
 dbname = postfix 
 query = SELECT goto FROM alias WHERE address='%s' AND active = '1' 
 </pre> 

 h3. Virtual domain map 

 * Create the 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 = SuperSecretPostfixPassword 
 hosts = pg.example.com 
 dbname = postfix 
 query = SELECT domain FROM domain WHERE domain='%s' and backupmx = '0' and active = '1' 
 </pre> 

 h3. Virtual mailbox map 

 * Create the 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 = SuperSecretPostfixPassword 
 hosts = pg.example.com 
 dbname = postfix 
 query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1' 
 </pre> 

 h3. Virtual mailbox limit map 

 * Create the postgresql virtual mailbox limit map file: 
 <pre> 
 vi /usr/local/etc/postfix/pgsql_virtual_mailbox_limit_maps.cf 
 </pre> 
 #* And add the following: 
 <pre> 
 user = postfix 
 password = SuperSecretPostfixPassword 
 hosts = pg.example.com 
 dbname = postfix 
 query = SELECT quota FROM mailbox WHERE username='%s' 
 </pre> 

 h3. Relay domain map 

 * Create 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 = SuperSecretPostfixPassword 
 hosts = pg.example.com 
 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> 
 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. Configure PHP 

 * Install pear-MDB2_Driver_pgsql: 
 <pre> 
 portmaster databases/pear-MDB2_Driver_pgsql security/php56-openssl 
 </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 = ".:/usr/local/share/pear" 
 ;... 
 post_max_size = 25M 
 ;... 
 ; Maximum allowed size for uploaded files. 
 ; http://php.net/upload-max-filesize 
 upload_max_filesize = 25M 
 ;... 
 date.timezone = "America/Los_Angeles" 
 ;... 
 session.use_only_cookies = 0 
 ;... 
 session.save_path = "/tmp" 
 </pre> 

 * 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. Configure Postfixadmin 

 * Secure PostfixAdmin files: 
 <pre> 
 cd /usr/local/www/postfixadmin 
 find . -type f -exec chmod 640 {} \; 
 find . -type d -exec chmod 750 {} \; 
 </pre> 

 * Edit the postfixadmin config file: 
 <pre> 
 vi /usr/local/www/postfixadmin/config.inc.php 
 </pre> 
 #* And modify the following: 
 <pre> 
 ... 
 $CONF['configured'] = true; 
 ... 
 $CONF['postfix_admin_url'] = 'https://mail.example.com/postfixadmin/'; 
 ... 
 $CONF['database_type'] = 'pgsql'; 
 $CONF['database_host'] = 'pg.exmple.com'; 
 $CONF['database_user'] = 'postfix'; 
 $CONF['database_password'] = 'SuperSecretPostfixPassword'; 
 $CONF['database_name'] = 'postfix'; 
 ... 
 $CONF['admin_email'] = 'postmaster@example.com'; 
 ... 
 $CONF['default_aliases'] = array ( 
         'abuse' => 'abuse@example.com', 
         'hostmaster' => 'hostmaster@example.com', 
         'postmaster' => 'postmaster@example.com', 
         'webmaster' => 'webmaster@example.com' 
 ); 
 ... 
 $CONF['encrypt'] = 'md5'; 
 ... 
 $CONF['domain_path'] = 'YES'; 
 ... 
 $CONF['domain_in_mailbox'] = 'NO'; 
 ... 
 $CONF['aliases'] = '50'; 
 $CONF['mailboxes'] = '50'; 
 $CONF['maxquota'] = '10240'; 
 ... 
 $CONF['quota'] = 'YES'; 
 ... 
 $CONF['quota_multiplier'] = '1048576'; 
 ... 
 $CONF['vacation'] = 'YES'; 
 ... 
 $CONF['vacation_domain'] = 'autoreply.example.com'; 
 ... 
 $CONF['user_footer_link'] = 'http://mail.example.com/'; 
 ... 
 $CONF['footer_text'] = 'Return to example.com'; 
 $CONF['footer_link'] = 'http://mail.example.com/'; 
 ... 
 $CONF['welcome_text'] = <<<EOM 
 Hello, 

 Welcome to your new email account! 

 For questions or comments regarding your mail account, 
 please feel free to send an email to support@example.com. 
 Likewise, any other inqueries regarding ISP NAME or their  
 affiliates can be sent to the same address. 

 Also, don't forget to check your mail settings via Maia- 
 Mailguard located at https://mail.example.com/maia/.  
 Simply log into your account using your email address  
 and password. That's it! From Maia-Mailguard, you can  
 adjust your spam, virus, malware, whitelists, blacklists,  
 etc... This will put you in full control of your email so  
 you never miss anything important. 

 Thank you for using ISP NAME and enjoy your new email  
 account! 

 Regards, 
 ISP NAME Staff 
 support@example.com 
 EOM; 
 ?> 
 ... 
 $CONF['emailcheck_resolve_domain']='NO'; 
 ... 
 $CONF['mailbox_postdeletion_script']='sudo -u vscan /usr/local/bin/postfixadmin-mailbox-postdeletion.sh'; 
 ... 
 $CONF['domain_postdeletion_script']='sudo -u vscan /usr/local/bin/postfixadmin-domain-postdeletion.sh'; 
 ... 
 $CONF['used_quotas'] = 'YES'; 
 ... 
 $CONF['new_quota_table'] = 'YES'; 
 </pre> 

 * Install sudo: 
 <pre> 
 portmaster security/sudo 
 </pre> 

 * Edit the sudoers file: 
 <pre> 
 visudo 
 </pre> 
 #* And add the following to the bottom of the file to allow the “www” user to execute the post-deletion scripts as the “vscan” user: 
 <pre> 
 www ALL=(vscan)    NOPASSWD: /usr/local/bin/postfixadmin-mailbox-postdeletion.sh \ 
                  /usr/local/bin/postfixadmin-domain-postdeletion.sh 
 </pre> 

 * Create post-deletion directories and copy scripts: 
 <pre> 
 mkdir -p /usr/local/virtual/deleted/{mailboxes,domains} 
 chown -R vscan:vscan /usr/local/virtual/deleted 
 chmod -R 0700 /usr/local/virtual/deleted 
 cp /usr/local/www/postfixadmin/ADDITIONS/postfixadmin-*deletion.sh /usr/local/bin 
 chmod +x /usr/local/bin/postfixadmin* 
 </pre> 

 * Edit the postfixadmin-domain-postdeletion.sh file: 
 <pre> 
 vi /usr/local/bin/postfixadmin-domain-postdeletion.sh 
 </pre> 
 #* And modify the following: 
 <pre> 
 # Change this to where you keep your virtual mail users' maildirs. 
 basedir=/usr/local/virtual 

 # Change this to where you would like deleted maildirs to reside. 
 trashbase=/usr/local/virtual/deleted/domains 
 </pre> 

 * Edit the postfixadmin-mailbox-postdeletion.sh file: 
 <pre> 
 vi /usr/local/bin/postfixadmin-mailbox-postdeletion.sh 
 </pre> 
 #* And modify the following: 
 <pre> 
 # Change this to where you keep your virtual mail users' maildirs. 
 basedir=/usr/local/virtual 

 # Change this to where you would like deleted maildirs to reside. 
 trashbase=/usr/local/virtual/deleted/mailboxes 
 </pre> 

 * Install needed Perl ports for Vacation to work: 
 <pre> 
 portmaster mail/p5-MIME-EncWords mail/p5-Email-Valid mail/p5-Mail-Sender devel/p5-Log-Log4perl devel/p5-Log-Dispatch 
 </pre> 

 * Create Vacation user and group accounts: 
 <pre> 
 pw groupadd vacation 
 pw useradd vacation -c Virtual\ Vacation -d /nonexistent -g vacation -s /sbin/nologin 
 </pre> 

 * Create, populate and secure vacation directory: 
 <pre> 
 mkdir /var/spool/vacation 
 cp /usr/local/www/postfixadmin/VIRTUAL_VACATION/vacation.pl /var/spool/vacation/ 
 chown -R vacation:vacation /var/spool/vacation/ 
 chmod 700 /var/spool/vacation/ 
 chmod 750 /var/spool/vacation/vacation.pl 
 touch /var/log/vacation.log /var/log/vacation-debug.log 
 chown vacation:vacation /var/log/vacation* 
 </pre> 

 * Edit the vacation.pl script: 
 <pre> 
 vi /var/spool/vacation/vacation.pl 
 </pre> 
 #* And modify the following: 
 <pre> 
 our $db_type = 'Pg'; 
 our $db_host = 'pg.example.com'; 
 our $db_username = 'postfix'; 
 our $db_password = 'SuperSecretPostfixPassword'; 
 our $db_name = 'postfix'; 
 our $vacation_domain = 'autoreply.example.com'; 
 our $logfile = "/var/log/vacation.log"; 
 our $log_level = 0; 
 our $log_to_file = 1; 
 ... 
 my $sender = new Mail::Sender({%smtp_connection,TLS_allowed => 0}); 
 ... 
 </pre> 

 * Edit master postfix config file for vacation filter: 
 <pre> 
 vi /usr/local/etc/postfix/master.cf 
 </pre> 
 #* And add this to the bottom of the file. 
 <pre> 
 vacation    unix    -         n         n         -         -         pipe  
   flags=DRhu user=vacation argv=/var/spool/vacation/vacation.pl -f ${sender} ${recipient} 
 </pre> 

 * Edit the main postfix config file for vacation transport: 
 <pre> 
 vi /usr/local/etc/postfix/main.cf 
 </pre> 
 #* And modify the following: 
 <pre> 
 ... 
 # TRANSPORT MAP 
 # 
 # See the discussion in the ADDRESS_REWRITING_README document. 
 transport_maps = hash:/usr/local/etc/postfix/transport 
 vacation_destination_recipient_limit = 1 
 ... 
 </pre> 

 * Add proper lines to /usr/local/etc/postfix/transport file: 
 <pre> 
 echo "autoreply.example.com vacation:" >> /usr/local/etc/postfix/transport 
 </pre> 

 * Create our transport map database for Postfix: 
 <pre> 
 postmap /usr/local/etc/postfix/transport 
 </pre> 

 * Create a postfixadmin location block in the mail.exmaple.com nginx config file: 
 <pre> 
 vi /usr/local/etc/nginx/conf.d/mail.example.com.conf 
 </pre> 
 #* Add the following: 
 <pre> 
 server { 
   listen         80; 
   server_name    mail.example.com; 
   root           /usr/local/www; 
   access_log     /var/log/mail.example.com-access.log; 
   error_log      /var/log/mail.example.com-error.log; 

   location /postfixadmin { 
     root     /usr/local/www; 
     index    index.php index.html index.htm; 
   } 

   # For all PHP requests, pass them on to PHP-FPM via FastCGI 
   location ~ \.php$ { 
     fastcgi_pass unix:/var/run/php-fpm.sock; 
     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
     fastcgi_param PATH_INFO $fastcgi_script_name; 
     include fastcgi_params; # include extra FCGI params 
   } 
 } 
 </pre> 

 * Change ownership of Postfixadmin web directory: 
 <pre> 
 chown -R www:www /usr/local/www/postfixadmin 
 </pre> 

 * Restart nginx configuration: 
 <pre> 
 service nginx configtest 
 service nginx restart 
 </pre> 

 * Run the dovecot and postfix startup scripts: 
 <pre> 
 service dovecot start 
 service postfix start 
 </pre> 

 *NOTE*: Check your /var/log/maillog and /var/log/messages to make sure there are no errors. 

 *NOTE*: If you are receiving errors in your logs about $mydestination, be sure that _ANY_ ‘virtual’ domain you are hosting is _NOT_ listed in your /etc/hosts file. 

 * Visit https://mailadmin.example.com/setup.php and generate the password hash at the bottom of the page.  
 *# Copy the password hash into your /usr/local/www/postfixadmin/config.inc.php file on the $setup_password line.  
 *# Next, create a Super Admin Account using the password which created your password hash to submit the information. The username MUST be in email address format (but should not actually exist) and the password for the Super Admin account DOES NOT need to be the same password which generated your password hash.  

 This guide uses superadmin@example.com as the newly created email user. 

 h2. Setup SpamAssassin 

 * Edit the spamassassin config file: 
 <pre> 
 vi /usr/local/etc/mail/spamassassin/local.cf 
 </pre> 
 #* And add the following to the bottom of the file: 
 <pre> 
 ifplugin Mail::SpamAssassin::BayesStore::PgSQL 
 bayes_sql_dsn DBI:pgsql:maiadb:pg.example.com:5432 
 bayes_sql_username maiauser 
 bayes_sql_password SuperSecretPassword 
 auto_whitelist_factory 
 endif 

 ifplugin Mail::SpamAssassin::SQLBasedAddrList 
 user_awl_dsn DBI:pgsql:maiadb:pg.example.com:5432 
 user_awl_sql_username maiauser 
 user_awl_sql_password SuperSecretPassword 
 bayes_auto_expire 0 
 endif 

 # Change the below to reflect your correct internal and external networks. 
 internal_networks 192.168.1.0/24 
 trusted_networks 192.168.1.0/24 123.456.789.0/24 
 </pre> 

 * Configure RAZOR for reporting: 
 <pre> 
 su - vscan 
 razor-admin -discover 
 razor-admin -create 
 razor-admin -register -l -user=username@example.com -pass=some_password 
 exit 
 </pre> 
 *NOTE*: The above user should be an actual email address you check. The password can be any password you'd like. It's only needed by razor2 to identify and report spam. 

 h2. Setup FuzzyOCR 

 * Install Tesseract via ports: 
 <pre> 
 portmaster graphics/tesseract devel/p5-IO-All-LWP 
 </pre> 

 * Copy FuzzyOcr files to SpamAssassin configuration directory: 
 <pre> 
 cp /usr/local/share/examples/FuzzyOcr/FuzzyOcr.* /usr/local/etc/mail/spamassassin 
 </pre> 

 h2. Setup ClamAV 

 * Enable ClamAV at boot time: 
 <pre> 
 echo 'clamav_freshclam_enable="YES"' >> /etc/rc.conf 
 echo 'clamav_clamd_enable="YES"' >> /etc/rc.conf 
 </pre> 

 * Create the db, log and socket directories: 
 <pre> 
 mkdir -p /var/{log,run,db}/clamav 
 chown -R vscan:vscan /var/{log,run,db}/clamav 
 </pre> 

 * Start FreshClam as well as the ClamAV daemon: 
 <pre> 
 service clamav-freshclam start 
 service clamav-clamd start 
 </pre> 
 *NOTE*: It may take a little while for “freshclam” to download the files. So, if you see a message like “Missing /var/db/clamav/*.cvd or *.cld files. You must run freshclam first” you may not be able to start the clamd daemon (clamav-clamd) until that finishes. 

 h2. Setup Maia Mailguard 

 * Populate the database: 
 <pre> 
 cd /usr/local/share/doc/maia 
 psql -h pg.example.com -U maiauser -W maiadb < maia-pgsql.sql 
 </pre> 

 * Edit the maia config file: 
 <pre> 
 vi /usr/local/etc/maia/maia.conf 
 </pre> 
 #* And modify the following: 
 <pre> 
 ... 
 # Configure your Maia database DSN here 
 $dsn = 'DBI:Pg:dbname=maiadb;host=pg.example.com;port=5432'; 

 # Your Maia database user's login name 
 $username = 'maiauser'; 

 # Your Maia database user's password 
 $password = 'SuperSecretPassword'; 
 ... 
 # Address rewriting type [0..5] (see config.php) 
 $address_rewriting_type = 4; 
 ... 
 # Authentication method (see config.php) 
 $auth_method = 'sql'; 
 ... 
 # Base URL to Maia's PHP scripts 
 $base_url = "https://mail.example.com/maia/"; 
 </pre> 

 * Run configtest.pl executable: 
 <pre> 
 perl /usr/local/share/maia/scripts/configtest.pl 
 </pre> 

 * Load SpamAssassin rules: 
 <pre> 
 sa-update 
 su - vscan 
 perl/usr/local/share/maia/scripts/load-sa-rules.pl --debug 
 exit 
 </pre> 

 * Edit maia config file: 
 <pre> 
 vi /usr/local/www/maia/config.php 
 </pre> 
 #* And modify the following 
 <pre> 
 ... 
 date_default_timezone_set("America/Los_Angeles"); 
 ... 
 $maia_sql_dsn = "pgsql://maiauser:SuperSecretPassword@tcp(pg.example.com:5432)/maiadb"; 
 ... 
 $purifier_cache = '/usr/local/www/maia/web'; 
 ... 
 $address_rewriting_type = 4; 
 ... 
 $auth_method = "pop3"; 
 ... 
 </pre> 

 * Create a maia location block in the mail.example.com nginx config file: 
 <pre> 
 vi /usr/local/etc/nginx/conf.d/mail.example.com.conf 
 </pre> 
 #* Add the following: 
 <pre> 
 server { 
   listen         80; 
   server_name    mail.example.com; 
   root           /usr/local/www; 
   access_log     /var/log/maia.example.com-access.log; 
   error_log      /var/log/maia.example.com-error.log; 

   location /postfixadmin { 
     root     /usr/local/www; 
     index    index.php index.html index.htm; 
   } 

   location /maia { 
     root     /usr/local/www; 
     index    index.php index.html index.htm; 
   } 

   # For all PHP requests, pass them on to PHP-FPM via FastCGI 
   location ~ \.php$ { 
     fastcgi_pass unix:/var/run/php-fpm.sock; 
     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
     fastcgi_param PATH_INFO $fastcgi_script_name; 
     include fastcgi_params; # include extra FCGI params 
   } 
 } 
 </pre> 

 * Restart nginx and php-fpm: 
 <pre> 
 service nginx restart 
 service php-fpm restart 
 </pre> 

 * Visit https://mail.example.com/maia/admin/configtest.php and verify everything is working. 

 * Create maia run directory: 
 <pre> 
 mkdir /var/run/maia 
 chown vscan:vscan /var/run/maia 
 </pre> 

 * Create maia log directory: 
 <pre> 
 mkdir /var/log/maia 
 chown vscan:vscan /var/log/maia 
 </pre> 

 * Edit maia daemon config file: 
 <pre> 
 vi /usr/local/etc/maia/maiad.conf 
 </pre> 
 #* And modify the following: 
 <pre> 
 ... 
 $lock_file = "/var/run/maia/maiad.lock"; "$MYHOME/maiad.lock"; 
 $pid_file = "/var/run/maia/maiad.pid"; "$MYHOME/maiad.pid"; 
 ... 
 $mydomain = 'example.com'; 
 ... 
 $myhostname = 'mail.example.com'; 
 ... 
 @lookup_sql_dsn = ( ['DBI:Pg:maiadb:pg.example.com', 'vscan', 'SuperSecretPassword'] ); 
 ... 
 $unrar = ['rar', 'unrar']; 
 ... 
 ### http://www.clamav.net/ 
 ['ClamAV-clamd', 
    \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd.sock"], 
    qr/\bOK$/, qr/\bFOUND$/, 
    qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ], 
 ... 
 </pre> 

 * Set Maia-Mailguard to start at boot and start it now: 
 <pre> 
 echo 'maiad_enable="YES"' >> /etc/rc.conf 
 service maiad start 
 </pre> 

 * Visit https://mail.example.com/maia/ 
 #* You should be greeted with a login screen. If so, great! Let’s log in and acquire admin privileges… 

 *NOTE*: If your images do not load, you’ll need to edit the /usr/local/www/maia/smarty.php file and delete the leading slash from the “/themes” bit on line 102. So, it should look like this:  
 <pre> 
 $this->assign('template_dir', 'themes/'.$theme.'/'); 
 </pre> 

 * Instead of https://mail.example.com/maia/login.php (The default), visit https://maia.example.com/maia/login.php?super=register 
 #* And and log in with any currently existing virtual user. user (Most likely the user you added with Postfixadmin earlier). Be sure to use a full email address to log into Maia-Mailguard. This guide uses superadmin@example.com. IE: username@example.com. That user will now have admin privs via Maia (So, be careful which user you choose). 

 * Once logged into Maia-Mailguard as an administrator, click the “Admin” link at the top of the page (Key-shaped icon). From the “Administration Menu” click “System Configuration“. Each mail server will want different settings for their setup. However, there are some things you should be aware of: 
 *# Make sure that *ANY* file name (With the exception of the logo image) listed for any option is listed with it’s *FULL PATH*. 
 *# The “Mail size limit” setting should not be higher than what you set your MySQL’s max_allowed_packet in /var/db/mysql/my.cnf. 

 *IMPORTANT*: For each domain you create using Postfixadmin or any other way you may create it, Maia needs to know about it in order to create users. This might seem like a redundant issue, but it really makes a difference and here’s why. When Maia recieves mail for a user that doesn’t exist, it uses the default domain’s (@.) settings. This is fine. However, if it considers that mail to be spam when it is not, the user cannot retrieve that message later being as the default settings don’t house mail for a non-existant user.  

 *+So, be sure to add any domain you add via PostfixAdmin to Maia-Mailguard as well.+* 

 * Edit main postfix file: 
 <pre> 
 vi /usr/local/etc/postfix/main.cf 
 </pre> 
 #* And modify the following: 
 <pre> 
 ... 
 # Maia-Mailguard 
 # 
 content_filter=smtp-amavis:[127.0.0.1]:10024 

 # LOCAL PATHNAME INFORMATION 
 # 
 # The queue_directory specifies the location of the Postfix queue. 
 # This is also the root directory of Postfix daemons that run chrooted. 
 # See the files in examples/chroot-setup for setting up Postfix chroot 
 # environments on different UNIX systems. 
 # 
 queue_directory = /var/spool/postfix 
 ... 
 </pre> 

 * Edit the master postfix file: 
 <pre> 
 vi /usr/local/etc/postfix/master.cf 
 </pre> 
 #* And modify the following: 
 <pre> 
 smtp-amavis unix - - n - 2 smtp 
   -o smtp_data_done_timeout=2400 
   -o smtp_send_xforward_command=yes 
   -o disable_dns_lookups=yes 
   -o max_use=20 
 127.0.0.1:10025 inet n - n - - smtpd 
   -o content_filter= 
   -o local_recipient_maps= 
   -o relay_recipient_maps= 
   -o smtpd_restriction_classes= 
   -o smtpd_delay_reject=no 
   -o smtpd_client_restrictions=permit_mynetworks,reject 
   -o smtpd_helo_restrictions= 
   -o smtpd_sender_restrictions= 
   -o smtpd_recipient_restrictions=permit_mynetworks,reject 
   -o mynetworks_style=host 
   -o mynetworks=127.0.0.0/8 
   -o strict_rfc821_envelopes=yes 
   -o smtpd_error_sleep_time=0 
   -o smtpd_soft_error_limit=1001 
   -o smtpd_hard_error_limit=1000 
   -o smtpd_client_connection_count_limit=0 
   -o smtpd_client_connection_rate_limit=0 
   -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings 
 </pre> 

 * Reload Postfix: 
 <pre> 
 postfix reload 
 </pre> 

 * Edit the “vscan” user’s cron jobs: 
 <pre> 
 crontab -u vscan -e 
 </pre> 
 #* And add the following to the vscan users’s crontab. 
 <pre> 
 #Load new rules and store into Maia database. 
 30 4 * * * /usr/local/share/maia/scripts/load-sa-rules.pl > /dev/null 

 #Train Spam Assassin. 
 0 * * * * /usr/local/share/maia/scripts/process-quarantine.pl --learn --report > /dev/null 

 #Take a snapshot of the stats at the start of every hour. 
 0 * * * * /usr/local/share/maia/scripts/stats-snapshot.pl > /dev/null 

 #Purge mail that has not been confirmed. 
 0 23 * * * /usr/local/share/maia/scripts/expire-quarantine-cache.pl > /dev/null 

 #Send quarantine reminders. 
 0 15 * * * /usr/local/share/maia/scripts/send-quarantine-reminders.pl > /dev/null 

 #Send quarantine digests. 
 0 15 * * * /usr/local/share/maia/scripts/send-quarantine-digests.pl > /dev/null 

 #Force bayesian auto-expiry during off-peak hours. 
 25 2 * * * /usr/local/bin/sa-learn --sync --force-expire > /dev/null 
 </pre> 

 * Remove BATCH setting from make.conf /etc/make.conf file: 
 <pre> 
 cd /etc 
 sed -i.orig -e '/^BATCH=yes/d' /etc/make.conf make.conf 
 </pre> 

 h2. Install Roundcube 

 * Install Roundcube via ports: 
 <pre> 
 portmaster mail/roundcube 
 </pre> 
 #* 

 *NOTE*: Make sure *[X]PSPELL* and *[X]PGSQL* are selected from the menu. 

 * Install PHP FileInfo and Exif: FileInfo: 
 <pre> 
 portmaster sysutils/php56-fileinfo graphics/php56-exif 
 </pre> 

 * Populate the Roundcube database: 
 <pre> 
 cd /usr/local/www/roundcube/SQL 
 psql -h pg.example.com -U roundcubeuser -W roundcubedb < postgres.initial.sql 
 </pre> 

 * Copy Roundcube configuration files and set permissions: 
 <pre> 
 cd /usr/local/www/roundcube/config 
 cp config.inc.php.sample config.inc.php 
 cd /usr/local/www/roundcube/plugins/managesieve 
 cp config.inc.php.dist config.inc.php 
 cd /usr/local/www/roundcube/plugins/password 
 cp config.inc.php.dist config.inc.php 
 cd /usr/local/www/roundcube 
 find . -type f -name "config.inc.php" -exec chmod 0600 {} \; -exec chown www {} \; 
 </pre> 

 * Edit the roundcube config file: 
 <pre> 
 vi /usr/local/www/roundcube/config/config.inc.php 
 </pre> 
 #* And modify the following: 
 <pre> 
 ... 
 $config['db_dsnw'] = 'pgsql://roundcubeuser:SuperSecretRoundcubePassword@pg.example.com/roundcubedb'; 
 ... 
 $config['smtp_server'] = 'localhost'; 
 ... 
 $config['smtp_user'] = '%u'; 
 ... 
 $config['smtp_pass'] = '%p'; 
 ... 
 $config['support_url'] = 'support@example.com'; 
 ... 
  $config['plugins'] = array( 
      'archive', 
      'zipdownload', 
      'managesieve', 
      'password', 
  ); 
 ... 
 ;(Add the following lines) 
 $config['spellcheck_engine'] = 'pspell'; 
 $config['preview_pane'] = true; 
 $config['mime_types'] = '/usr/local/etc/nginx/mime.types'; 
 $config['enable_installer'] = false; 
 ... 
 </pre> 

 * Edit the roundcube managesieve plugin config file: 
 <pre> 
 vi /usr/local/www/roundcube/plugins/managesieve/config.inc.php 
 </pre> 
 #* And modify the following: 
 <pre> 
 ... 
 $config['managesieve_default'] = '/usr/local/virtual/home/default.sieve'; 
 ... 
 </pre> 

 * Edit roundcube password plugin config file: 
 <pre> 
 vi /usr/local/www/roundcube/plugins/password/config.inc.php 
 </pre> 
 #* And modify the following: 
 <pre> 
 ... 
 $config['password_minimum_length'] = 8; 
 ... 
 $config['password_db_dsn'] = 'pgsql://postfix:SuperSecretPostfixPassword@pg.example.com/postfix'; 
 ... 
 $config["password_query"] = "UPDATE mailbox SET password=%c WHERE username=%u"; 
 ... 
 </pre> 

 * Secure Roundcube configuration files: 
 <pre> 
 chmod 600 /usr/local/www/roundcube/config/* 
 chown www /usr/local/www/roundcube/config/* 
 </pre> 

 * Create a roundcube location block in the mail.example.com nginx config file: 
 <pre> 
 vi /usr/local/etc/nginx/conf.d/mail.example.com.conf 
 </pre> 
 #* Add the following: 
 <pre> 
 server { 
   listen         80; 
   server_name    mail.example.com; 
   root           /usr/local/www; 
   access_log     /var/log/mail.example.com-access.log; 
   error_log      /var/log/mail.example.com-error.log; 

   location /postfixadmin { 
     root     /usr/local/www; 
     index    index.php index.html index.htm; 
   } 

   location /maia { 
     root     /usr/local/www; 
     index    index.php index.html index.htm; 
   } 

   location /roundcube { 
     root     /usr/local/www; 
     index    index.php index.html index.htm; 
   } 

   # For all PHP requests, pass them on to PHP-FPM via FastCGI 
   location ~ \.php$ { 
     fastcgi_pass unix:/var/run/php-fpm.sock; 
     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
     fastcgi_param PATH_INFO $fastcgi_script_name; 
     include fastcgi_params; # include extra FCGI params 
   } 

 } 
 </pre> 

 * Restart nginx and php-fpm: 
 <pre> 
 service nginx restart 
 service php-fpm restart 
 </pre> 

 * Visit https://mail.example.com/roundcube/ 
 #* Login to roundcube using your full email address and password. You should now be able to use Roundcube as a webmail client.  

 *NOTE*: If you're having any problems, be sure to check your Roundcube logs located in /usr/local/www/roundcube/logs. 

 h2. Resources 

 * http://www.purplehat.org/?page_id=4 
 * http://www.maiamailguard.com/maia/wiki/Install 
 * https://forums.freebsd.org/threads/postgresql-postfix-nginx-php-roundcube-dovecot-spamassassin-clamav-spamd.10728/ 
 * https://wiki.gentoo.org/wiki/Complete_Virtual_Mail_Server/Postfix_to_Database 
 * http://www.iredmail.org/docs/store.spamassassin.bayes.in.sql.html 
 * https://spamassassin.apache.org/full/3.0.x/dist/doc/Mail_SpamAssassin_Conf.html 
 * https://github.com/technion/maia_mailguard/issues/20

Back