Difference between revisions of "ISP Mail Server HowTo"

From Alpine Linux
Jump to: navigation, search
(Mailbox Quotas: update dovecot version)
m (Formatting)
Line 196: Line 196:
 
Edit the /etc/postfix/main.cf file  Here's an example:
 
Edit the /etc/postfix/main.cf file  Here's an example:
  
  myhostname=host.example.com                                                                
+
  myhostname=host.example.com
  mydomain=example.com                                                                        
+
  mydomain=example.com
 
   
 
   
  mydestination = localhost.$mydomains, localhost                                
+
  mydestination = localhost.$mydomains, localhost
  mynetworks_style = subnet                                                                  
+
  mynetworks_style = subnet
  mynetworks = 127.0.0.0/8                                                                    
+
  mynetworks = 127.0.0.0/8
 
 
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf             
 
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,                   
 
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,                         
 
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf                 
 
 
   
 
   
  virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,                
+
  virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf
         proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf                  
+
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,
 +
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,
 +
         proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf
 
   
 
   
  virtual_mailbox_base = /var/mail/domains/                                                        
+
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,
  virtual_gid_maps = static:1006                                                                    
+
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf
  virtual_uid_maps = static:1006                                                                    
+
  virtual_minimum_uid = 100                                                                        
+
  virtual_mailbox_base = /var/mail/domains/
  virtual_transport = virtual    
+
  virtual_gid_maps = static:1006
 +
  virtual_uid_maps = static:1006
 +
  virtual_minimum_uid = 100
 +
  virtual_transport = virtual
 
   
 
   
 
   
 
   
Line 223: Line 223:
 
   
 
   
 
  mailbox_transport = virtual
 
  mailbox_transport = virtual
  local_transport = virtual                                                                  
+
  local_transport = virtual
  local_transport_maps = $virtual_mailbox_maps                                                
+
  local_transport_maps = $virtual_mailbox_maps
 
   
 
   
  smtpd_helo_required = yes                                                                        
+
  smtpd_helo_required = yes
  disable_vrfy_command = yes                                                                        
+
  disable_vrfy_command = yes
  message_size_limit = 10240000                                                                    
+
  message_size_limit = 10240000
  queue_minfree = 51200000                                                                          
+
  queue_minfree = 51200000
 
   
 
   
  smtpd_sender_restrictions =                                                                      
+
  smtpd_sender_restrictions =
         permit_mynetworks,                                                                        
+
         permit_mynetworks,
         reject_non_fqdn_sender,                                                                  
+
         reject_non_fqdn_sender,
         reject_unknown_sender_domain                                                              
+
         reject_unknown_sender_domain
 
   
 
   
  smtpd_recipient_restrictions =                                                                    
+
  smtpd_recipient_restrictions =
         reject_non_fqdn_recipient,                                                                
+
         reject_non_fqdn_recipient,
         reject_unknown_recipient_domain,                                                          
+
         reject_unknown_recipient_domain,
         permit_mynetworks,                                                                        
+
         permit_mynetworks,
         permit_sasl_authenticated,                                                                
+
         permit_sasl_authenticated,
         reject_unauth_destination,                                                                
+
         reject_unauth_destination,
         reject_rbl_client dnsbl.sorbs.net,                                                        
+
         reject_rbl_client dnsbl.sorbs.net,
         reject_rbl_client zen.spamhaus.org,                                                      
+
         reject_rbl_client zen.spamhaus.org,
         reject_rbl_client bl.spamcop.net                                                          
+
         reject_rbl_client bl.spamcop.net
 
   
 
   
  smtpd_data_restrictions = reject_unauth_pipelining  
+
  smtpd_data_restrictions = reject_unauth_pipelining
 
   
 
   
 
  # we will use this later - This prevents cleartext authentication
 
  # we will use this later - This prevents cleartext authentication
 
  # for relaying
 
  # for relaying
  smtpd_tls_auth_only = yes  
+
  smtpd_tls_auth_only = yes
  
  

Revision as of 19:59, 10 February 2010

A Full Service Mail Server

The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.

The server must provide:

  • multiple virtual domains
  • admins for each domain (to add/remove virtual accounts)
  • Quota support per domain / account
  • downloading email via IMAP / IMAPS / POP3 / POP3S
  • relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)
  • Standard filters (virus/spam/rbl/etc)
  • Web mail client
  • Value Add services

Configure DNS

This server will host three separate virtual domains on the same web server. They will be distinguished by their domains, so you must choose three domains for the three separate services:

  • ACF - Alpine Configuration Framework for managing the server
  • PostfixAdmin - for managing the postfix installation
  • RoundCube - for accessing individual mailboxes

Choose three different domains (herein knows is ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host.

Set up Lighttpd + PHP

PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.

 apk add lighttpd php php-pgsql php-imap

Stop and remove mini_httpd, and move ACF to lighttpd; We are setting this up to be a multi-domain virtual web server (replace ACF_DOMAIN with the actual domain):

 mkdir -p /var/www/domains/ACF_DOMAIN
 ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www

Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler

$HTTP["url"] =~ "^/cgi-bin/" {
    # disable directory listings
    dir-listing.activate = "disable"
    # only allow cgi's in this directory
    cgi.assign = (
		".pl"	=>	"/usr/bin/perl",
		".cgi"	=>	"/usr/bin/perl",
		"" => ""
	)
}

Add these lines to /etc/lighttpd/lighttpd.conf to point to the new document root, and set it up to listen on port 443 (replace ROUNDCUBE_DOMAIN with the roundcube domain and ip_address_of_server with the actual IP address):

simple-vhost.server-root   = "/var/www/domains/"
simple-vhost.default-host  = "/ROUNDCUBE_DOMAIN/"
simple-vhost.document-root = "www/"

$SERVER["socket"] == "ip_address_of_server:443" {
ssl.engine    = "enable"
ssl.pemfile   = "/etc/lighttpd/server-bundle.pem"
ssl.ca-file   = "/etc/lighttpd/ca-crt.pem"
}

Ensure that the simple_vhosts module is loaded, as well as the cgi config scripts by uncommenting the following lines in /etc/lighttpd/lighttpd.conf

server.modules = (
    #  other modules may be listed
    "mod_simple_vhost", 
    #  other modules may be listed
 .
 .
 .
    include "mod_cgi.conf"

    include "mod_fastcgi.conf"

Get a web certificate, and install it. If you want to use a self-signed cert, you can use Generating SSL certs with ACF or Generating SSL certs with ACF 1.9. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:

 openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem
 openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem
 chown root:root /etc/lighttpd/server-bundle.pem
 chmod 400 /etc/lighttpd/server-bundle.pem


Note: The server certificate and key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".

Editme: We should probably only serve ACF to restricted hosts

Stop and remove mini_httpd; start lighttpd, test

 /etc/init.d/mini_httpd stop
 rc-update del mini_httpd
 apk del mini_httpd
 rc-update add lighttpd
 /etc/init.d/lighttpd start

At this point you should be able to see ACF being served with lighttpd: https://ACF_DOMAIN/

Install Postgresql

Add and configure postgresql

 apk add acf-postgresql postgresql-client
 /etc/init.d/postgresql setup
 /etc/init.d/postgresql start
 rc-update add postgresql

At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf


 Editme: What should we recommend?


Create the postfix database:

 psql -U postgres
  create user postfix with password '******';
  create database postfix owner postfix;
  \c postfix
  create language plpgsql;
  \q

(Of course, use your selected password where ******* is shown above.)

Install PostfixAdmin

We are going to install the postfix admin web front-end before we install the mail server. This just creates an interface to populate the SQL tables that postfix and dovecot will use.

Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace POSTFIXADMIN_DOMAIN with the actual domain):

wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz
tar zxvf postfixadmin_2.3.tar.gz
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN/www
mv postfixadmin-2.3/* /var/www/domains/POSTFIXADMIN_DOMAIN/www
rm -rf postfixadmin*

Edit /var/www/domains/POSTFIXADMIN_DOMAIN/www/config.inc.php and modify at least these lines:

$CONF['configured'] = true;
$CONF['setup_password'] = "";  << Don't change this yet
$CONF['database_type'] = 'pgsql';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = '*****';   << The password you chose above
$CONF['database_name'] = 'postfix';
$CONF['database_prefix'] = ;
$CONF['admin_email'] = 'you@some.email.com';  << Your email address 
$CONF['encrypt'] = 'md5crypt';
$CONF['authlib_default_flavor'] = 'md5raw';
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';
$CONF['aliases'] = '10';                       
$CONF['mailboxes'] = '10';
$CONF['maxquota'] = '10';
$CONF['vacation'] = 'NO'; 
$CONF['vacation_control'] ='NO';
$CONF['vacation_control_admin'] = 'NO';
$CONF['create_mailbox_subdirs_prefix']="";  
$CONF['quota'] = 'YES';
$CONF['quota_multiplier'] = '1024000';
$CONF['used_quotas'] = 'YES';   
$CONF['new_quota_table'] = 'YES';  
$CONF['alias_control'] = 'YES';
$CONF['alias_control_admin'] = 'YES';
$CONF['special_alias_control'] = 'YES';
$CONF['fetchmail'] = 'NO';
$CONF['user_footer_link'] = "http://host.example.com";
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';


Go to http://POSTFIXADMIN_DOMAIN/setup.php

Create the password hash, add it to the config.inc.php file

Go back to http://POSTFIXADMIN_DOMAIN/setup.php

Create superadmin, create a mail domain or other, as desired.

Install Postfix

Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)

adduser vmail -H -D -s /bin/false
grep vmail /etc/passwd

(In examples below, we use 1006/1006 for the uid/gid)

Create the mail directory, and assign vmail as the owner

mkdir -p /var/mail/domains
chown -R vmail:vmail /var/mail/domains

Install postfix

apk add acf-postfix postfix-pgsql

Edit the /etc/postfix/main.cf file Here's an example:

myhostname=host.example.com
mydomain=example.com

mydestination = localhost.$mydomains, localhost
mynetworks_style = subnet
mynetworks = 127.0.0.0/8

virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,
       proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,
       proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf

virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,
       proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf

virtual_mailbox_base = /var/mail/domains/
virtual_gid_maps = static:1006
virtual_uid_maps = static:1006
virtual_minimum_uid = 100
virtual_transport = virtual


# This next command means you must create a virtual
# domain for the host itself - ALL mail goes through
# The virtual transport

mailbox_transport = virtual
local_transport = virtual
local_transport_maps = $virtual_mailbox_maps

smtpd_helo_required = yes
disable_vrfy_command = yes
message_size_limit = 10240000
queue_minfree = 51200000

smtpd_sender_restrictions =
       permit_mynetworks,
       reject_non_fqdn_sender,
       reject_unknown_sender_domain

smtpd_recipient_restrictions =
       reject_non_fqdn_recipient,
       reject_unknown_recipient_domain,
       permit_mynetworks,
       permit_sasl_authenticated,
       reject_unauth_destination,
       reject_rbl_client dnsbl.sorbs.net,
       reject_rbl_client zen.spamhaus.org,
       reject_rbl_client bl.spamcop.net

smtpd_data_restrictions = reject_unauth_pipelining

# we will use this later - This prevents cleartext authentication
# for relaying
smtpd_tls_auth_only = yes


Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.

cd /etc/postfix
mkdir sql
PGPW="ChangeMe"

cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf
user=postfix
password = $PGPW
hosts = localhost
dbname = postfix
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true 
EOF

cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf
user=postfix
password = $PGPW
hosts = localhost
dbname = postfix
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active
EOF

cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf
user=postfix
password = $PGPW
hosts = localhost
dbname = postfix
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true
EOF

cat - <<EOF >sql/pgsql_virtual_alias_maps.cf
user=postfix
password = $PGPW
hosts = localhost
dbname = postfix
query = Select goto From alias Where address='%s' and active ='1'
EOF

cat - <<EOF >sql/pgsql_virtual_domains_maps.cf
user=postfix
password = $PGPW
hosts = localhost
dbname = postfix
query = Select domain from domain where domain='%s' and active='1'
EOF

cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf
user=postfix
password = $PGPW
hosts = localhost
dbname = postfix
query = Select maildir from mailbox where username='%s' and active=true
EOF

chown -R postfix:postfix sql
chmod 640 sql/*


At this point you should be able to start up postfix

newaliases  # so postfix is happy...
/etc/init.d/postfix start
rc-service add postfix


Create a domain in PostfixAdmin and test

create a domain for the local box (e.g. example.com) Create the alias accounts

From the machine, send a test message:

sendmail -t root@example.com
subject: test
.
^d


In /var/log/mail.log (or /var/log/messages, if you still have busybox syslogd running) you should see the message queued. The message should be in /var/mail/domains/example.com/root/new

Install Dovecot

Dovecot is the POP3/IMAP server to retrieve mail.

As before, we install dovecot:

apk add acf-dovecot dovecot-pgsql

edit /etc/dovecot.conf

# Select only the protocols you wish to support - all are listed in the next line
protocols               =       imap imaps pop pop3s
log_path                =       /var/log/dovecot.log
info_log_path           =       /var/log/dovecot-info.log
disable_plaintext_auth  =       no
# Authenticated IMAP
ssl                     =       yes
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem
ssl_key_file            =       /etc/lighttpd/server-bundle.pem
auth_verbose            =       yes
auth_debug              =       no
mail_location           =       maildir:/var/mail/domains/%d/%n
auth default    {
       mechanisms = plain
       passdb sql {
               args = /etc/dovecot/dovecot-sql.conf
               }
       userdb static {
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n
               }


We need a certificate for SSL/TLS authentication, so in the example above, we use the lighttpd cert. That way when the cert is renewed/replaced, Dovecot will have access to the new cert as well.

Create the /etc/dovecot/dovecot-sql.conf file:

driver = pgsql
connect = host=localhost dbname=postfix user=postfix password=********
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'
default_pass_scheme =  MD5-CRYPT

Again, change the password above to your postfix user password, and protect the file from prying eyes:

chown root:root /etc/dovecot/dovecot-sql.conf
chmod 600 /etc/dovecot/dovecot-sql.conf


Start dovecot

/etc/init.d/dovecot start
rc-update add dovecot


Testing

Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.

At this point, you should be able to:

* Create a new domain and add users with PostfixAdmin
* Send mail to those users via SMTP to port 25
* Retrieve mail using the user's full email and password (e.g. username: user@example.com  password: ChangeM

Value Add Features

If you followed the guide above, you now have a functional mail server with many interconnected parts. The features below assume that the server is already running as described above. You should be able to add any or all of these features below to further enhance the mail service.


Virus Scanning

This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.


  • Install clamav and clamsmtp:
apk add acf-clamav clamsmtp
  • Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)
  • Edit /etc/clamsmtpd.conf and verify the following lines
OutAddress: 10026
Listen: 127.0.0.1:10025                                               
Header: X-Virus-Scanned: ClamAV using ClamSMTP
Action: drop
User: clamav                                                      
  • Start the daemons
rc-update add clamd
rc-update add freshclam
rc-update add clamsmtp
/etc/init.d/clamd start
/etc/init.d/freshclam start
/etc/init.d/clamsmtp start
  • Verify clamsmtp is listening on port 10025:
netstat -anp | grep clamsmtp
content_filter = scan:[127.0.0.1]:10025                                                      
    • edit /etc/postfix/master.cf and add
# AV scan filter (used by content_filter)
scan      unix  -       -       n       -       16      smtp
        -o smtp_send_xforward_command=yes
        -o smtp_enforce_tls=no
# For injecting mail back into postfix from the filter
127.0.0.1:10026 inet  n -       n       -       16      smtpd
        -o content_filter=
        -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
        -o smtpd_helo_restrictions=
        -o smtpd_client_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o mynetworks_style=host
        -o smtpd_authorized_xforward_hosts=127.0.0.0/8
  • postfix reload
  • Send and email into a local virtual domain - it should have the X-Virus-Scanned: ClamAV using ClamSMTP header.



Relay for Authenticated Users

As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the mynetworks configuration line in /etc/postfix/main.cf

This configuration change allows remote users to authenticate against the mail server and relay through it. The rules for relaying are:

  • Only authenticated users can relay
  • Authentication Credentials must be encrypted with TLS or SSL
  • Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)

The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.


  • Edit /etc/dovecot/dovecot.conf and add:
# this is for postfix SASL (authenticated users can relay through us)
socket listen {
               client {
                       path    = /var/spool/postfix/private/dovecot-auth.sock
                       mode    = 0660
                       user    = postfix
                       group   = postfix
                       }
               }
       }
  • Restart dovecot
/etc/init.d/dovecot restart
  • Edit /etc/postfix/main.cf and add:
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    

smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem
# If tls_security_level is set to "encrypt", then SMTP rejects 
# unencrypted email (e.g. normal mail) which is bad.
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other 
# interesting places.  Check your logs to see who
smtpd_tls_security_level = may
# Log info about the negotiated encryption levels
smtpd_tls_received_header = yes
smtpd_tls_loglevel = 1

# SASL - this allows senders to authenticiate themselves
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/dovecot-auth.sock
smtpd_sasl_auth_enable = yes
smtpd_sasl_authenticated_header = yes
smtpd_tls_auth_only = yes
  • Edit /etc/postfix/master.cf and enable the submission and smtps transports. They are probably already at the top of your master.cf file, just commented out:
submission inet n       -       n       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       n       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
  • Verfiy submission and smtps are defined in /etc/services
grep "submission\|ssmtp" /etc/services
submission	587/tcp				# mail message submission
submission	587/udp
smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL
smtps		465/udp		ssmtp
  • Restart postfix
postfix reload

At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.


Mailbox Quotas

In the default configuration, PostfixAdmin knows about quotas, but they are not enforced. Documentation on the web mentions the vda patch to postifx to enforce quotas. The only bad thing... its a patch. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using the dovecot's deliver lda for local delivery.

Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:

  • Postgresql 8.4.2
  • PostfixAdmin 2.3
  • Dovecot 1.2.10
  • Postfix 2.6.5

Presumably later versions will work the same, but if not, please update the documentation and versions above.

  • Update /etc/dovecot.conf (old lines shown commented out):
# old postfix 
#       userdb static {
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n
#               }

# new quota support:
       userdb prefetch {
               }
       userdb sql {
               args = /etc/dovecot/dovecot-sql.conf
               }
       socket listen {
               client {
                       path    = /var/spool/postfix/private/dovecot-auth.sock
                       mode    = 0660
                       user    = postfix
                       group   = postfix
                       }
               # These lines below are for the deliver lda
               master {
                       path =  /var/run/dovecot/auth-master
                       mode    = 0660
                       user    = vmail
                       group   = vmail
                       }
               }

protocol imap {                                                               
        mail_plugins = quota imap_quota                                       
        }                                                                     
                                                                             
protocol pop3 {                                                               
        mail_plugins = quota                                                  
        }                                                                     
                                                                             
dict {                                                                        
       quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                
       }                                                                     
                                                                             
plugin {                                                                      
        quota = dict:user::proxy::quotadict                                   
        }                                                     
                                                             
protocol lda {                                                
  postmaster_address = postmaster@host.example.com
  mail_plugins = quota                                        
  auth_socket_path =  /var/run/dovecot/auth-master
  sendmail_path = /usr/sbin/sendmail
}                                                                            
   

You should already have a socket-> listen-> client section, but it is listed above to show where it goes in relationship to the socket -> listen -> master section


  • edit /etc/dovecot/dovecot-sql.conf and replace the user and password queries with the following (you may not have a user_query yet - add it):
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox  where local_part = '%n' and domain = '%d'
user_query = select maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota  as quota_rule from mailbox where local_part = '%n' and domain ='%d'


  • create /etc/dovecot/dovecot-dict-quota.conf
connect = host=localhost dbname=postfix user=postfix password=********

map {
        pattern = priv/quota/storage
        table = quota2
        username_field =username
        value_field = bytes
}

map {
       pattern= priv/quota/messages
       table = quota2
       username_field = username
       value_field = messages
}

Side note: The Dovecot Quota Documentation mentions the need for a trigger with pgsql. This was created in the PostfixAdmin install, which is why you instantiated the pgsql language when creating the database. If not, you will need to create the trigger, to reference the quota2 table, not the quota table mentioned in the dovecot docs.


  • create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:
# The dovecot deliver lda
dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}
  • Edit the /etc/postfix/main.cf. Replace
virtual_transport = virtual 

with

virtual_transport = dovecot
dovecot_destination_recipient_limit = 1


TODO This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.

WebMail (RoundCube)

RoundCube is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository

  • Add the package and related php modules:
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv
  • link the roundcube application back into the docroot
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube
  • follow the instructions in /usr/share/webapps/roundcube/INSTALL:
chown -R lighttpd:lighttpd temp logs

su postgres
createuser roundcube
  Shall the new role be a superuser? (y/n) n
  Shall the new role be allowed to create databases? (y/n) n
  Shall the new role be allowed to create more new roles? (y/n) y
createdb -O roundcube -E UNICODE -T template0 roundcubemail
psql roundcubemail
  roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';
  roundcubemail=# \c - roundcube
  \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql
  \q


  • restart lighttpd to verify the new php libraries are used
/etc/init.d/lighttpd restart
  • Point your browser to http://host.example.com/roundcube/installer
    • Begin installation
    • Follow the instructions in step 3 of the install to copy the files to the server
  • edit /etc/php/php.ini and edit date.timezone to your local timezone, or to UTC
  • if necessary (e.g. you had to reset the local timezone) restart lighttpd to reload php
/etc/init.d/lighttpd restart


For the specific configuration parameters in the install step:

Property Setting
enable_spellcheck disabled
identities_level one identity with possibility to edit all params but not email address
log driver syslog
sylog_id roundcube
syslog_facility mailsubsystem
db_dnsw pgsql properties, as described above
imap_host 127.0.0.1
auto_create_user enabled
smtp_server 127.0.0.1
smtp_port 25
smtp_user/smtp_pass enable Use Current IMAP username and password for SMTP authentication
smtp_log enable (optional, but gives additional log record)

The other items can be left at default settings, or adjusted if desired.


After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do one of the following:

cd /usr/share/webapps/roundcube
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer

or

cd /usr/share/webapps/roundcube
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL 
chmod 700 SQL installer

log rotation


Special thanks to DHughes for providing a 3 page email on how to set up postgres,postfix,PostfixAdmin,dovecot and roundcube. It was the clearer than all the other guides available on the Net. Thanks!