<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alpinelinux.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ppalonen</id>
	<title>Alpine Linux - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alpinelinux.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ppalonen"/>
	<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/wiki/Special:Contributions/Ppalonen"/>
	<updated>2026-04-25T18:10:54Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4537</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4537"/>
		<updated>2010-10-22T08:16:09Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: /* Enable Plug-ins */  Create Trash, Sent, Spam folders&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain login&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 broken_sasl_auth_clients = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.13&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
#user = root&lt;br /&gt;
#}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Verify that you have at least the following in /etc/postfix/main.cf. Unless you have followed the Relay for Authenticated Users section above, set &#039;&#039;&#039;smtpd_tls_auth_only = no&#039;&#039;&#039;, otherwise leave it set to &#039;&#039;&#039;yes&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# SASL - this allows senders to authenticiate themselves&lt;br /&gt;
# This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
smtpd_sasl_type = dovecot&lt;br /&gt;
smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
smtpd_sasl_auth_enable = yes&lt;br /&gt;
smtpd_sasl_authenticated_header = yes&lt;br /&gt;
# Set the next line to no if TLS auth is not configured &lt;br /&gt;
smtpd_tls_auth_only = no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
socket listen {&lt;br /&gt;
               client {&lt;br /&gt;
                       path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                       mode    = 0660&lt;br /&gt;
                       user    = postfix&lt;br /&gt;
                       group   = postfix&lt;br /&gt;
                       }&lt;br /&gt;
               }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart the relevant services:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/init.d/postfix restart&lt;br /&gt;
/etc/init.d/dovecot restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   &#039;&#039;&#039;&#039;&#039;[Question to experts: Is this error message normal at this point? &amp;quot;could not save history to file &amp;quot;/var/lib/postgresql/.psql_history&amp;quot;: Permission denied&amp;quot;]&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to https://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 2 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at https://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;create_default_folders&#039;&#039; for RoundCube&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;create_default_folders&#039;] = TRUE;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Question to experts: Is this normal to have in this script &amp;quot;WARNING:  nonstandard use of \\ in a string literal&amp;quot;?&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don&#039;t want it...&lt;br /&gt;
#TLSCipherSuite HIGH&lt;br /&gt;
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
#TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
#TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL. In case you uncommented TLS lines in slapd.conf use this string: OPTS=&amp;quot;-h &#039;ldaps:// ldap://&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldap://&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldap://host.example.com&lt;br /&gt;
&lt;br /&gt;
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don&#039;t want it...&lt;br /&gt;
#TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
#TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
#TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4532</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4532"/>
		<updated>2010-10-22T03:30:36Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: /* OpenLDAP based Address Book */  disable LDAPs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain login&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 broken_sasl_auth_clients = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.13&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
#user = root&lt;br /&gt;
#}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Verify that you have at least the following in /etc/postfix/main.cf. Unless you have followed the Relay for Authenticated Users section above, set &#039;&#039;&#039;smtpd_tls_auth_only = no&#039;&#039;&#039;, otherwise leave it set to &#039;&#039;&#039;yes&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# SASL - this allows senders to authenticiate themselves&lt;br /&gt;
# This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
smtpd_sasl_type = dovecot&lt;br /&gt;
smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
smtpd_sasl_auth_enable = yes&lt;br /&gt;
smtpd_sasl_authenticated_header = yes&lt;br /&gt;
# Set the next line to no if TLS auth is not configured &lt;br /&gt;
smtpd_tls_auth_only = no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
socket listen {&lt;br /&gt;
               client {&lt;br /&gt;
                       path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                       mode    = 0660&lt;br /&gt;
                       user    = postfix&lt;br /&gt;
                       group   = postfix&lt;br /&gt;
                       }&lt;br /&gt;
               }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart the relevant services:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/init.d/postfix restart&lt;br /&gt;
/etc/init.d/dovecot restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   &#039;&#039;&#039;&#039;&#039;[Question to experts: Is this error message normal at this point? &amp;quot;could not save history to file &amp;quot;/var/lib/postgresql/.psql_history&amp;quot;: Permission denied&amp;quot;]&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to https://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 2 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at https://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Question to experts: Is this normal to have in this script &amp;quot;WARNING:  nonstandard use of \\ in a string literal&amp;quot;?&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don&#039;t want it...&lt;br /&gt;
#TLSCipherSuite HIGH&lt;br /&gt;
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
#TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
#TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL. In case you uncommented TLS lines in slapd.conf use this string: OPTS=&amp;quot;-h &#039;ldaps:// ldap://&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldap://&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldap://host.example.com&lt;br /&gt;
&lt;br /&gt;
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don&#039;t want it...&lt;br /&gt;
#TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
#TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
#TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4507</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4507"/>
		<updated>2010-10-15T02:32:55Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: /* OpenLDAP based Address Book */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain login&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 broken_sasl_auth_clients = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.13&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
#user = root&lt;br /&gt;
#}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Verify that you have at least the following in /etc/postfix/main.cf. Unless you have followed the Relay for Authenticated Users section above, set &#039;&#039;&#039;smtpd_tls_auth_only = no&#039;&#039;&#039;, otherwise leave it set to &#039;&#039;&#039;yes&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# SASL - this allows senders to authenticiate themselves&lt;br /&gt;
# This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
smtpd_sasl_type = dovecot&lt;br /&gt;
smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
smtpd_sasl_auth_enable = yes&lt;br /&gt;
smtpd_sasl_authenticated_header = yes&lt;br /&gt;
# Set the next line to no if TLS auth is not configured &lt;br /&gt;
smtpd_tls_auth_only = no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
socket listen {&lt;br /&gt;
               client {&lt;br /&gt;
                       path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                       mode    = 0660&lt;br /&gt;
                       user    = postfix&lt;br /&gt;
                       group   = postfix&lt;br /&gt;
                       }&lt;br /&gt;
               }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart the relevant services:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/init.d/postfix restart&lt;br /&gt;
/etc/init.d/dovecot restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   &#039;&#039;&#039;&#039;&#039;[Question to experts: Is this error message normal at this point? &amp;quot;could not save history to file &amp;quot;/var/lib/postgresql/.psql_history&amp;quot;: Permission denied&amp;quot;]&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to https://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 2 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at https://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Question to experts: Is this normal to have in this script &amp;quot;WARNING:  nonstandard use of \\ in a string literal&amp;quot;?&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
TLSCipherSuite HIGH&lt;br /&gt;
TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldaps:// ldap://127.0.0.1&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldaps://host.example.com&lt;br /&gt;
&lt;br /&gt;
TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4503</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4503"/>
		<updated>2010-10-14T08:49:21Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: /* WebMail (RoundCube) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain login&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 broken_sasl_auth_clients = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.13&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
#user = root&lt;br /&gt;
#}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Verify that you have at least the following in /etc/postfix/main.cf. Unless you have followed the Relay for Authenticated Users section above, set &#039;&#039;&#039;smtpd_tls_auth_only = no&#039;&#039;&#039;, otherwise leave it set to &#039;&#039;&#039;yes&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# SASL - this allows senders to authenticiate themselves&lt;br /&gt;
# This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
smtpd_sasl_type = dovecot&lt;br /&gt;
smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
smtpd_sasl_auth_enable = yes&lt;br /&gt;
smtpd_sasl_authenticated_header = yes&lt;br /&gt;
# Set the next line to no if TLS auth is not configured &lt;br /&gt;
smtpd_tls_auth_only = no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
socket listen {&lt;br /&gt;
               client {&lt;br /&gt;
                       path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                       mode    = 0660&lt;br /&gt;
                       user    = postfix&lt;br /&gt;
                       group   = postfix&lt;br /&gt;
                       }&lt;br /&gt;
               }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart the relevant services:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/init.d/postfix restart&lt;br /&gt;
/etc/init.d/dovecot restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   &#039;&#039;&#039;&#039;&#039;[Question to experts: Is this error message normal at this point? &amp;quot;could not save history to file &amp;quot;/var/lib/postgresql/.psql_history&amp;quot;: Permission denied&amp;quot;]&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to https://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 2 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at https://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
TLSCipherSuite HIGH&lt;br /&gt;
TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldaps:// ldap://127.0.0.1&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldaps://host.example.com&lt;br /&gt;
&lt;br /&gt;
TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4502</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4502"/>
		<updated>2010-10-14T08:39:03Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: /* WebMail (RoundCube) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain login&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 broken_sasl_auth_clients = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.13&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
#user = root&lt;br /&gt;
#}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Verify that you have at least the following in /etc/postfix/main.cf. Unless you have followed the Relay for Authenticated Users section above, set &#039;&#039;&#039;smtpd_tls_auth_only = no&#039;&#039;&#039;, otherwise leave it set to &#039;&#039;&#039;yes&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# SASL - this allows senders to authenticiate themselves&lt;br /&gt;
# This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
smtpd_sasl_type = dovecot&lt;br /&gt;
smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
smtpd_sasl_auth_enable = yes&lt;br /&gt;
smtpd_sasl_authenticated_header = yes&lt;br /&gt;
# Set the next line to no if TLS auth is not configured &lt;br /&gt;
smtpd_tls_auth_only = no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
socket listen {&lt;br /&gt;
               client {&lt;br /&gt;
                       path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                       mode    = 0660&lt;br /&gt;
                       user    = postfix&lt;br /&gt;
                       group   = postfix&lt;br /&gt;
                       }&lt;br /&gt;
               }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart the relevant services:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/init.d/postfix restart&lt;br /&gt;
/etc/init.d/dovecot restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   &#039;&#039;&#039;&#039;&#039;[Question to experts: Is this error message normal at this point? &amp;quot;could not save history to file &amp;quot;/var/lib/postgresql/.psql_history&amp;quot;: Permission denied&amp;quot;]&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to https://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 3 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at http://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
TLSCipherSuite HIGH&lt;br /&gt;
TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldaps:// ldap://127.0.0.1&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldaps://host.example.com&lt;br /&gt;
&lt;br /&gt;
TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4501</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4501"/>
		<updated>2010-10-14T07:05:37Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: Is this error message ok?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain login&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 broken_sasl_auth_clients = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.13&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
#user = root&lt;br /&gt;
#}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Verify that you have at least the following in /etc/postfix/main.cf. Unless you have followed the Relay for Authenticated Users section above, set &#039;&#039;&#039;smtpd_tls_auth_only = no&#039;&#039;&#039;, otherwise leave it set to &#039;&#039;&#039;yes&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# SASL - this allows senders to authenticiate themselves&lt;br /&gt;
# This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
smtpd_sasl_type = dovecot&lt;br /&gt;
smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
smtpd_sasl_auth_enable = yes&lt;br /&gt;
smtpd_sasl_authenticated_header = yes&lt;br /&gt;
# Set the next line to no if TLS auth is not configured &lt;br /&gt;
smtpd_tls_auth_only = no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
socket listen {&lt;br /&gt;
               client {&lt;br /&gt;
                       path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                       mode    = 0660&lt;br /&gt;
                       user    = postfix&lt;br /&gt;
                       group   = postfix&lt;br /&gt;
                       }&lt;br /&gt;
               }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart the relevant services:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/init.d/postfix restart&lt;br /&gt;
/etc/init.d/dovecot restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   &#039;&#039;&#039;&#039;&#039;[Question to experts: Is this error message normal at this point? &amp;quot;could not save history to file &amp;quot;/var/lib/postgresql/.psql_history&amp;quot;: Permission denied&amp;quot;]&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to http://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 3 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at http://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
TLSCipherSuite HIGH&lt;br /&gt;
TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldaps:// ldap://127.0.0.1&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldaps://host.example.com&lt;br /&gt;
&lt;br /&gt;
TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4500</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4500"/>
		<updated>2010-10-14T07:02:56Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain login&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 broken_sasl_auth_clients = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.13&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
#user = root&lt;br /&gt;
#}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Verify that you have at least the following in /etc/postfix/main.cf. Unless you have followed the Relay for Authenticated Users section above, set &#039;&#039;&#039;smtpd_tls_auth_only = no&#039;&#039;&#039;, otherwise leave it set to &#039;&#039;&#039;yes&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# SASL - this allows senders to authenticiate themselves&lt;br /&gt;
# This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
smtpd_sasl_type = dovecot&lt;br /&gt;
smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
smtpd_sasl_auth_enable = yes&lt;br /&gt;
smtpd_sasl_authenticated_header = yes&lt;br /&gt;
# Set the next line to no if TLS auth is not configured &lt;br /&gt;
smtpd_tls_auth_only = no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
socket listen {&lt;br /&gt;
               client {&lt;br /&gt;
                       path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                       mode    = 0660&lt;br /&gt;
                       user    = postfix&lt;br /&gt;
                       group   = postfix&lt;br /&gt;
                       }&lt;br /&gt;
               }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart the relevant services:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/init.d/postfix restart&lt;br /&gt;
/etc/init.d/dovecot restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
   &#039;&#039;&#039;&#039;&#039;[Question to experts: Is this error message normal at this point? &amp;quot;could not save history to file &amp;quot;/var/lib/postgresql/.psql_history&amp;quot;: Permission denied&amp;quot;]&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to http://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 3 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at http://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
TLSCipherSuite HIGH&lt;br /&gt;
TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldaps:// ldap://127.0.0.1&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldaps://host.example.com&lt;br /&gt;
&lt;br /&gt;
TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4498</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4498"/>
		<updated>2010-10-13T07:59:31Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: version change for Dovecot; updated /etc/dovecot/dovecot.conf&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain login&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 broken_sasl_auth_clients = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.13&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
#user = root&lt;br /&gt;
#}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Verify that you have at least the following in /etc/postfix/main.cf. Unless you have followed the Relay for Authenticated Users section above, set &#039;&#039;&#039;smtpd_tls_auth_only = no&#039;&#039;&#039;, otherwise leave it set to &#039;&#039;&#039;yes&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# SASL - this allows senders to authenticiate themselves&lt;br /&gt;
# This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
smtpd_sasl_type = dovecot&lt;br /&gt;
smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
smtpd_sasl_auth_enable = yes&lt;br /&gt;
smtpd_sasl_authenticated_header = yes&lt;br /&gt;
# Set the next line to no if TLS auth is not configured &lt;br /&gt;
smtpd_tls_auth_only = no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
socket listen {&lt;br /&gt;
               client {&lt;br /&gt;
                       path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                       mode    = 0660&lt;br /&gt;
                       user    = postfix&lt;br /&gt;
                       group   = postfix&lt;br /&gt;
                       }&lt;br /&gt;
               }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Restart the relevant services:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/init.d/postfix restart&lt;br /&gt;
/etc/init.d/dovecot restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to http://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 3 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at http://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
TLSCipherSuite HIGH&lt;br /&gt;
TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldaps:// ldap://127.0.0.1&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldaps://host.example.com&lt;br /&gt;
&lt;br /&gt;
TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4345</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4345"/>
		<updated>2010-08-27T03:24:10Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to https://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.11&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to http://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 3 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at http://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
TLSCipherSuite HIGH&lt;br /&gt;
TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldaps:// ldap://127.0.0.1&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldaps://host.example.com&lt;br /&gt;
&lt;br /&gt;
TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4344</id>
		<title>ISP Mail Server HowTo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&amp;diff=4344"/>
		<updated>2010-08-27T02:05:08Z</updated>

		<summary type="html">&lt;p&gt;Ppalonen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:mail]]&lt;br /&gt;
== A Full Service Mail Server ==&lt;br /&gt;
&lt;br /&gt;
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured &amp;quot;ISP&amp;quot; level mail server.&lt;br /&gt;
&lt;br /&gt;
The server must provide:&lt;br /&gt;
&lt;br /&gt;
* multiple virtual domains&lt;br /&gt;
* admins for each domain (to add/remove virtual accounts)&lt;br /&gt;
* Quota support per domain / account&lt;br /&gt;
* downloading email via IMAP / IMAPS / POP3 / POP3S&lt;br /&gt;
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)&lt;br /&gt;
* Standard filters (virus/spam/rbl/etc)&lt;br /&gt;
* Web mail client&lt;br /&gt;
* Value Add services&lt;br /&gt;
&lt;br /&gt;
== Set up Lighttpd + PHP ==&lt;br /&gt;
&lt;br /&gt;
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.&lt;br /&gt;
&lt;br /&gt;
  apk add lighttpd php php-pgsql php-imap&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd, and move ACF to lighttpd;  We are setting this up to be a multi-domain virtual web server (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  mkdir -p /var/www/domains/host.example.com/www&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;title&amp;gt;host.example.com Redirector&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/acf&amp;quot;&amp;gt;ACF&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/postfixadmin&amp;quot;&amp;gt;PostfixAdmin&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/roundcube&amp;quot;&amp;gt;Roundcube&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a &amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot; cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the &#039;^&#039;)&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;url&amp;quot;] =~ &amp;quot;/cgi-bin/&amp;quot; {&lt;br /&gt;
     # disable directory listings&lt;br /&gt;
     dir-listing.activate = &amp;quot;disable&amp;quot;&lt;br /&gt;
     # only allow cgi&#039;s in this directory&lt;br /&gt;
     cgi.assign = (&lt;br /&gt;
 		&amp;quot;.pl&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;.cgi&amp;quot;	=&amp;gt;	&amp;quot;/usr/bin/perl&amp;quot;,&lt;br /&gt;
 		&amp;quot;&amp;quot; =&amp;gt; &amp;quot;&amp;quot;&lt;br /&gt;
 	)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Get a web certificate, and install it.  You have two options: 1. If you want to use a self-signed cert, you can use the instructions found at [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]] to generate it. 2. Use the certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 1:&#039;&#039;&#039;&lt;br /&gt;
If you create your own self-signed certificate, you can create the &amp;quot;server-bundle.pem&amp;quot; and the &amp;quot;ca-crt.pem&amp;quot; file with these commands:&lt;br /&gt;
&lt;br /&gt;
  openssl pkcs12 -nokeys -cacerts -in certificate.pfx  -out /etc/lighttpd/ca-crt.pem&lt;br /&gt;
  openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The server certificate &#039;&#039;and&#039;&#039; key are in the server-bundle.pem file, so it is critical that the file be read-only by user &amp;quot;root&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Option 2:&#039;&#039;&#039;&lt;br /&gt;
If you prefer to just use the default certificate created with the &#039;&#039;&#039;setup-acf&#039;&#039;&#039; command, then you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
  setup-acf&lt;br /&gt;
&lt;br /&gt;
During the above process, mini_httpd will be started, if it isn&#039;t already, and a certificate will be created. Once you have completed the setup-acf steps, do the following to move the certificate files to the correct location for lighttpd to use.&lt;br /&gt;
&lt;br /&gt;
  mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chown root:root /etc/lighttpd/server-bundle.pem&lt;br /&gt;
  chmod 400 /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;host.example.com&#039;&#039; with the actual domain and &#039;&#039;ip_address_of_server&#039;&#039; with the actual IP address):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
simple-vhost.default-host  = &amp;quot;/host.example.com/&amp;quot;&lt;br /&gt;
simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:&lt;br /&gt;
&lt;br /&gt;
  $SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;ip_address_of_server:443&amp;quot; {&lt;br /&gt;
  ssl.engine    = &amp;quot;enable&amp;quot;&lt;br /&gt;
  ssl.pemfile   = &amp;quot;/etc/lighttpd/server-bundle.pem&amp;quot;&lt;br /&gt;
  ssl.ca-file   = &amp;quot;/etc/lighttpd/ca-crt.pem&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
 server.modules = (&lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
     &amp;quot;mod_simple_vhost&amp;quot;, &lt;br /&gt;
     #  other modules may be listed&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
  .&lt;br /&gt;
     include &amp;quot;mod_cgi.conf&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
     include &amp;quot;mod_fastcgi.conf&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Stop and remove mini_httpd; start lighttpd, test&lt;br /&gt;
&lt;br /&gt;
  /etc/init.d/mini_httpd stop&lt;br /&gt;
  rc-update del mini_httpd&lt;br /&gt;
  apk del mini_httpd&lt;br /&gt;
  rc-update add lighttpd&lt;br /&gt;
  /etc/init.d/lighttpd start&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10. With earlier versions there will be problems.)  https://host.example.com/acf/&lt;br /&gt;
&lt;br /&gt;
== Install Postgresql ==&lt;br /&gt;
&lt;br /&gt;
Add and configure postgresql&lt;br /&gt;
&lt;br /&gt;
  apk add acf-postgresql postgresql-client&lt;br /&gt;
  /etc/init.d/postgresql setup&lt;br /&gt;
  /etc/init.d/postgresql start&lt;br /&gt;
  rc-update add postgresql&lt;br /&gt;
&lt;br /&gt;
At this point any user can connect to the sql server with &amp;quot;trust&amp;quot; mechanism.  If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Editme: What should we recommend?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the postfix database:&lt;br /&gt;
&lt;br /&gt;
  psql -U postgres&lt;br /&gt;
   create user postfix with password &#039;******&#039;;&lt;br /&gt;
   create database postfix owner postfix;&lt;br /&gt;
   \c postfix&lt;br /&gt;
   create language plpgsql;&lt;br /&gt;
   \q&lt;br /&gt;
&lt;br /&gt;
(Of course, use your selected password where ******* is shown above.)&lt;br /&gt;
&lt;br /&gt;
== Install PostfixAdmin ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Download PostfixAdmin from Sourceforge.  When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 tar zxvf postfixadmin-2.3.2.tar.gz&lt;br /&gt;
 mkdir -p /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 mv  postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin&lt;br /&gt;
 rm -rf postfixadmin*&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and modify at least these lines (replace host.example.com with the actual domain):&lt;br /&gt;
&lt;br /&gt;
 $CONF[&#039;configured&#039;] = true;&lt;br /&gt;
 $CONF[&#039;setup_password&#039;] = &amp;quot;&amp;quot;;  &amp;lt;&amp;lt; Don&#039;t change this yet&lt;br /&gt;
 $CONF[&#039;database_type&#039;] = &#039;pgsql&#039;;&lt;br /&gt;
 $CONF[&#039;database_host&#039;] = &#039;localhost&#039;;&lt;br /&gt;
 $CONF[&#039;database_user&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_password&#039;] = &#039;*****&#039;;   &amp;lt;&amp;lt; The password you chose above&lt;br /&gt;
 $CONF[&#039;database_name&#039;] = &#039;postfix&#039;;&lt;br /&gt;
 $CONF[&#039;database_prefix&#039;] = &amp;quot;&amp;quot;;&lt;br /&gt;
 $CONF[&#039;admin_email&#039;] = &#039;you@some.email.com&#039;;  &amp;lt;&amp;lt; Your email address &lt;br /&gt;
 $CONF[&#039;encrypt&#039;] = &#039;md5crypt&#039;;&lt;br /&gt;
 $CONF[&#039;authlib_default_flavor&#039;] = &#039;md5raw&#039;;&lt;br /&gt;
 $CONF[&#039;dovecotpw&#039;] = &amp;quot;/usr/sbin/dovecotpw&amp;quot;;&lt;br /&gt;
 $CONF[&#039;domain_path&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;domain_in_mailbox&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;aliases&#039;] = &#039;10&#039;;                       &lt;br /&gt;
 $CONF[&#039;mailboxes&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;maxquota&#039;] = &#039;10&#039;;&lt;br /&gt;
 $CONF[&#039;quota&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;quota_multiplier&#039;] = &#039;1024000&#039;;&lt;br /&gt;
 $CONF[&#039;vacation&#039;] = &#039;NO&#039;; &lt;br /&gt;
 $CONF[&#039;vacation_control&#039;] =&#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;vacation_control_admin&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;alias_control_admin&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;special_alias_control&#039;] = &#039;YES&#039;;&lt;br /&gt;
 $CONF[&#039;fetchmail&#039;] = &#039;NO&#039;;&lt;br /&gt;
 $CONF[&#039;user_footer_link&#039;] = &amp;quot;http://host.example.com/postfixadmin&amp;quot;;&lt;br /&gt;
 $CONF[&#039;footer_link&#039;] = &#039;http://host.example.com/postfixadmin/main.php&#039;;&lt;br /&gt;
 $CONF[&#039;create_mailbox_subdirs_prefix&#039;]=&amp;quot;&amp;quot;;  &lt;br /&gt;
 $CONF[&#039;used_quotas&#039;] = &#039;YES&#039;;   &lt;br /&gt;
 $CONF[&#039;new_quota_table&#039;] = &#039;YES&#039;;  &lt;br /&gt;
&lt;br /&gt;
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of &amp;quot;change-this-to-your.domain.tld&amp;quot; with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):&lt;br /&gt;
&lt;br /&gt;
 sed -i -e &#039;s/change-this-to-your.domain.tld/example.com/g&#039; /var/www/domains/host.example.com/www/postfixadmin/config.inc.php&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create the password hash, add it to the config.inc.php file&lt;br /&gt;
&lt;br /&gt;
Go back to http://host.example.com/postfixadmin/setup.php&lt;br /&gt;
&lt;br /&gt;
Create superadmin account.&lt;br /&gt;
&lt;br /&gt;
== Install Postfix ==&lt;br /&gt;
&lt;br /&gt;
Create a user for the virtual mail delivery, and get its uid/gid (you&#039;ll need the numeric uid/gid for postfix)&lt;br /&gt;
&lt;br /&gt;
 adduser vmail -H -D -s /bin/false&lt;br /&gt;
 grep vmail /etc/passwd&lt;br /&gt;
&lt;br /&gt;
(In examples below, we use 1006/1006 for the uid/gid)&lt;br /&gt;
&lt;br /&gt;
Create the mail directory, and assign vmail as the owner&lt;br /&gt;
 mkdir -p /var/mail/domains&lt;br /&gt;
 chown -R vmail:vmail /var/mail/domains&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Install postfix&lt;br /&gt;
&lt;br /&gt;
 apk add acf-postfix postfix-pgsql&lt;br /&gt;
&lt;br /&gt;
Edit the /etc/postfix/main.cf file. Here&#039;s an example (don&#039;t forget to replace the uid/gid):&lt;br /&gt;
&lt;br /&gt;
 myhostname=host.example.com&lt;br /&gt;
 mydomain=example.com&lt;br /&gt;
 &lt;br /&gt;
 mydestination = localhost.$mydomain, localhost&lt;br /&gt;
 mynetworks_style = subnet&lt;br /&gt;
 mynetworks = 127.0.0.0/8&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,&lt;br /&gt;
        proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 &lt;br /&gt;
 virtual_mailbox_base = /var/mail/domains/&lt;br /&gt;
 virtual_gid_maps = static:1006&lt;br /&gt;
 virtual_uid_maps = static:1006&lt;br /&gt;
 virtual_minimum_uid = 100&lt;br /&gt;
 virtual_transport = virtual&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 # This next command means you must create a virtual&lt;br /&gt;
 # domain for the host itself - ALL mail goes through&lt;br /&gt;
 # The virtual transport&lt;br /&gt;
 &lt;br /&gt;
 mailbox_transport = virtual&lt;br /&gt;
 local_transport = virtual&lt;br /&gt;
 local_transport_maps = $virtual_mailbox_maps&lt;br /&gt;
 &lt;br /&gt;
 smtpd_helo_required = yes&lt;br /&gt;
 disable_vrfy_command = yes&lt;br /&gt;
 message_size_limit = 10240000&lt;br /&gt;
 queue_minfree = 51200000&lt;br /&gt;
 &lt;br /&gt;
 smtpd_sender_restrictions =&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        reject_non_fqdn_sender,&lt;br /&gt;
        reject_unknown_sender_domain&lt;br /&gt;
 &lt;br /&gt;
 smtpd_recipient_restrictions =&lt;br /&gt;
        reject_non_fqdn_recipient,&lt;br /&gt;
        reject_unknown_recipient_domain,&lt;br /&gt;
        permit_mynetworks,&lt;br /&gt;
        permit_sasl_authenticated,&lt;br /&gt;
        reject_unauth_destination,&lt;br /&gt;
        reject_rbl_client dnsbl.sorbs.net,&lt;br /&gt;
        reject_rbl_client zen.spamhaus.org,&lt;br /&gt;
        reject_rbl_client bl.spamcop.net&lt;br /&gt;
 &lt;br /&gt;
 smtpd_data_restrictions = reject_unauth_pipelining&lt;br /&gt;
 &lt;br /&gt;
 # we will use this later - This prevents cleartext authentication&lt;br /&gt;
 # for relaying&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here&#039;s a shell script to create the scripts.  Change PGPW to the password for the postfix user of the postfix SQL database.&lt;br /&gt;
&lt;br /&gt;
 cd /etc/postfix&lt;br /&gt;
 mkdir sql&lt;br /&gt;
 PGPW=&amp;quot;ChangeMe&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_catchall_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and alias.address = &#039;@&#039; ||  alias_domain.target_domain and alias.active = true and alias_domain.active= true &lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = &#039;%d&#039; and mailbox.username = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and mailbox.active = true and alias_domain.active&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_domain_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = select goto from alias,alias_domain where alias_domain.alias_domain=&#039;%d&#039; and alias.address = &#039;%u&#039; || &#039;@&#039; || alias_domain.target_domain and alias.active= true and alias_domain.active= true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_alias_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select goto From alias Where address=&#039;%s&#039; and active =&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_domains_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select domain from domain where domain=&#039;%s&#039; and active=&#039;1&#039;&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 cat - &amp;lt;&amp;lt;EOF &amp;gt;sql/pgsql_virtual_mailbox_maps.cf&lt;br /&gt;
 user=postfix&lt;br /&gt;
 password = $PGPW&lt;br /&gt;
 hosts = localhost&lt;br /&gt;
 dbname = postfix&lt;br /&gt;
 query = Select maildir from mailbox where username=&#039;%s&#039; and active=true&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 chown -R postfix:postfix sql&lt;br /&gt;
 chmod 640 sql/*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you should be able to start up postfix&lt;br /&gt;
 &lt;br /&gt;
 newaliases  # so postfix is happy...&lt;br /&gt;
 /etc/init.d/postfix start&lt;br /&gt;
 rc-update add postfix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Create a domain in PostfixAdmin and test ===&lt;br /&gt;
&lt;br /&gt;
Go to http://host.example.com/postfixadmin/&lt;br /&gt;
&lt;br /&gt;
Log in using the superadmin account, create a domain for the local box (e.g. example.com), and create a user mailbox (e.g. root).&lt;br /&gt;
&lt;br /&gt;
From the machine, send a test message:&lt;br /&gt;
&lt;br /&gt;
 sendmail -t root@example.com&lt;br /&gt;
 subject: test&lt;br /&gt;
 .&lt;br /&gt;
 ^d&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
== Install Dovecot ==&lt;br /&gt;
&lt;br /&gt;
Dovecot is the POP3/IMAP server to retrieve mail.&lt;br /&gt;
&lt;br /&gt;
As before, we install dovecot: &lt;br /&gt;
&lt;br /&gt;
 apk add acf-dovecot dovecot-pgsql&lt;br /&gt;
&lt;br /&gt;
edit /etc/dovecot/dovecot.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select only the protocols you wish to support - all are listed in the next line&lt;br /&gt;
protocols               =       imap imaps pop3 pop3s&lt;br /&gt;
log_path                =       /var/log/dovecot.log&lt;br /&gt;
info_log_path           =       /var/log/dovecot-info.log&lt;br /&gt;
disable_plaintext_auth  =       no&lt;br /&gt;
auth_username_format    =       %Lu&lt;br /&gt;
&lt;br /&gt;
# Authenticated IMAP&lt;br /&gt;
ssl                     =       yes&lt;br /&gt;
ssl_cert_file           =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
ssl_key_file            =       /etc/lighttpd/server-bundle.pem&lt;br /&gt;
auth_verbose            =       yes&lt;br /&gt;
auth_debug              =       no&lt;br /&gt;
mail_location           =       maildir:/var/mail/domains/%d/%n&lt;br /&gt;
auth default    {&lt;br /&gt;
       mechanisms = plain&lt;br /&gt;
       passdb sql {&lt;br /&gt;
               args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
               }&lt;br /&gt;
       userdb static {&lt;br /&gt;
               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
               }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {&lt;br /&gt;
        mail_plugins = autocreate&lt;br /&gt;
}&lt;br /&gt;
plugin {&lt;br /&gt;
        autocreate = Trash&lt;br /&gt;
        autocreate2 = Spam&lt;br /&gt;
        autocreate3 = Sent&lt;br /&gt;
        autosubscribe = Trash&lt;br /&gt;
        autosubscribe2 = Spam&lt;br /&gt;
        autosubscribe3 = Sent&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to replace the uid and gid with the appropriate values for the vmail user.&lt;br /&gt;
&lt;br /&gt;
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.  &lt;br /&gt;
&lt;br /&gt;
Create the /etc/dovecot/dovecot-sql.conf file:&lt;br /&gt;
&lt;br /&gt;
 driver = pgsql&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 password_query = select username,password from mailbox where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 default_pass_scheme =  MD5-CRYPT&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
&lt;br /&gt;
 chown root:root /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
 chmod 600 /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Start dovecot&lt;br /&gt;
 /etc/init.d/dovecot start&lt;br /&gt;
 rc-update add dovecot&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support.  &lt;br /&gt;
 &lt;br /&gt;
At this point, you should be able to:&lt;br /&gt;
 * Create a new domain and add users with PostfixAdmin&lt;br /&gt;
 * Send mail to those users via SMTP to port 25&lt;br /&gt;
 * Retrieve mail using the user&#039;s full email and password (e.g. username: user@example.com  password: ChangeMe)&lt;br /&gt;
&lt;br /&gt;
== Value Add Features ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Virus Scanning ===&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;scanned by clamav&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Install clamav and clamsmtp:&lt;br /&gt;
 apk add acf-clamav clamsmtp&lt;br /&gt;
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)&lt;br /&gt;
* Edit /etc/clamsmtpd.conf and verify the following lines&lt;br /&gt;
 OutAddress: 10026&lt;br /&gt;
 Listen: 127.0.0.1:10025                                               &lt;br /&gt;
 Header: X-Virus-Scanned: ClamAV using ClamSMTP&lt;br /&gt;
 Action: drop&lt;br /&gt;
 User: clamav                                                      &lt;br /&gt;
* Start the daemons&lt;br /&gt;
 rc-update add clamd&lt;br /&gt;
 rc-update add clamsmtpd&lt;br /&gt;
 /etc/init.d/clamd start&lt;br /&gt;
 /etc/init.d/clamsmtpd start&lt;br /&gt;
* Verify clamsmtp is listening on port 10025:&lt;br /&gt;
 netstat -anp | grep clamsmtp&lt;br /&gt;
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]&lt;br /&gt;
** edit /etc/postfix/main.cf and add:&lt;br /&gt;
 content_filter = scan:[127.0.0.1]:10025                                                      &lt;br /&gt;
** edit /etc/postfix/master.cf and add&lt;br /&gt;
 # AV scan filter (used by content_filter)&lt;br /&gt;
 scan      unix  -       -       n       -       16      smtp&lt;br /&gt;
         -o smtp_send_xforward_command=yes&lt;br /&gt;
         -o smtp_enforce_tls=no&lt;br /&gt;
 # For injecting mail back into postfix from the filter&lt;br /&gt;
 127.0.0.1:10026 inet  n -       n       -       16      smtpd&lt;br /&gt;
         -o content_filter=&lt;br /&gt;
         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks&lt;br /&gt;
         -o smtpd_helo_restrictions=&lt;br /&gt;
         -o smtpd_client_restrictions=&lt;br /&gt;
         -o smtpd_sender_restrictions=&lt;br /&gt;
         -o smtpd_recipient_restrictions=permit_mynetworks,reject&lt;br /&gt;
         -o mynetworks_style=host&lt;br /&gt;
         -o smtpd_authorized_xforward_hosts=127.0.0.0/8&lt;br /&gt;
* postfix reload&lt;br /&gt;
* Send and email into a local virtual domain - it should have the &#039;&#039;X-Virus-Scanned: ClamAV using ClamSMTP&#039;&#039; header.&lt;br /&gt;
&lt;br /&gt;
=== Relay for Authenticated Users ===&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;mynetworks&#039;&#039; configuration line in /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
This configuration change allows &#039;&#039;remote&#039;&#039; users to authenticate against the mail server and relay through it.  The rules for relaying are:&lt;br /&gt;
* Only authenticated users can relay&lt;br /&gt;
* Authentication Credentials must be encrypted with TLS or SSL&lt;br /&gt;
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)&lt;br /&gt;
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Edit /etc/dovecot/dovecot.conf and add teh following inside the &#039;&#039;auth default&#039;&#039; stanza:&lt;br /&gt;
 # this is for postfix SASL (authenticated users can relay through us)&lt;br /&gt;
 socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
* Restart dovecot&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
* Edit /etc/postfix/main.cf and add:&lt;br /&gt;
 # TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first                    &lt;br /&gt;
 &lt;br /&gt;
 smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem&lt;br /&gt;
 smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem&lt;br /&gt;
 # If tls_security_level is set to &amp;quot;encrypt&amp;quot;, then SMTP rejects &lt;br /&gt;
 # unencrypted email (e.g. normal mail) which is bad.&lt;br /&gt;
 # By setting it to &amp;quot;may&amp;quot; you get TLS encrypted mail from google, slashdot, and other &lt;br /&gt;
 # interesting places.  Check your logs to see who&lt;br /&gt;
 smtpd_tls_security_level = may&lt;br /&gt;
 # Log info about the negotiated encryption levels&lt;br /&gt;
 smtpd_tls_received_header = yes&lt;br /&gt;
 smtpd_tls_loglevel = 1&lt;br /&gt;
 &lt;br /&gt;
 # SASL - this allows senders to authenticiate themselves&lt;br /&gt;
 # This along with &amp;quot;permit_sasl_authenticated&amp;quot; in smtpd_recipient_restrictions allows relaying&lt;br /&gt;
 smtpd_sasl_type = dovecot&lt;br /&gt;
 smtpd_sasl_path = private/dovecot-auth.sock&lt;br /&gt;
 smtpd_sasl_auth_enable = yes&lt;br /&gt;
 smtpd_sasl_authenticated_header = yes&lt;br /&gt;
 smtpd_tls_auth_only = yes&lt;br /&gt;
* 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:&lt;br /&gt;
 submission inet n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
 smtps     inet  n       -       n       -       -       smtpd&lt;br /&gt;
   -o smtpd_tls_security_level=encrypt&lt;br /&gt;
   -o smtpd_tls_wrappermode=yes&lt;br /&gt;
   -o smtpd_sasl_auth_enable=yes&lt;br /&gt;
   -o smtpd_client_restrictions=permit_sasl_authenticated,reject&lt;br /&gt;
   -o milter_macro_daemon_name=ORIGINATING&lt;br /&gt;
*Verfiy submission and smtps are defined in /etc/services&lt;br /&gt;
 grep &amp;quot;submission\|ssmtp&amp;quot; /etc/services&lt;br /&gt;
 submission	587/tcp				# mail message submission&lt;br /&gt;
 submission	587/udp&lt;br /&gt;
 smtps		465/tcp		ssmtp		# smtp protocol over TLS/SSL&lt;br /&gt;
 smtps		465/udp		ssmtp&lt;br /&gt;
* Restart postfix&lt;br /&gt;
 postfix reload&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;plain&amp;quot; authentication is used because the underlying link is encrypted.  For example, in Thunderbird leave &amp;quot;secure authentication&amp;quot; unchecked, and choose STARTTLS (or TLS) for the connection security.&lt;br /&gt;
&lt;br /&gt;
=== Mailbox Quotas ===&lt;br /&gt;
&lt;br /&gt;
In the default configuration, PostfixAdmin knows about quotas, but they are not enforced.   Documentation on the web mentions the [http://vda.sourceforge.net vda patch to postfix] to enforce quotas.  The only bad thing... its a &#039;&#039;patch&#039;&#039;.   Postfix and Dovecot are both conservative systems, so if the patch isn&#039;t in the upstream source, we&#039;ll assume there&#039;s a good reason.   There is a way of using quotas without patches - and it involves using dovecot&#039;s [http://wiki.dovecot.org/LDA deliver] lda for local delivery.&lt;br /&gt;
&lt;br /&gt;
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced.  These instructions apply to:&lt;br /&gt;
* Postgresql 8.4.2 &lt;br /&gt;
* PostfixAdmin 2.3 &lt;br /&gt;
* Dovecot 1.2.11&lt;br /&gt;
* Postfix 2.6.5&lt;br /&gt;
&lt;br /&gt;
Presumably later versions will work the same, but if not, please update the documentation and versions above.&lt;br /&gt;
&lt;br /&gt;
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# old postfix &lt;br /&gt;
#       userdb static {&lt;br /&gt;
#               args =  uid=1006 gid=1006 home=/var/mail/domains/%d/%n&lt;br /&gt;
#               }&lt;br /&gt;
&lt;br /&gt;
# new quota support:&lt;br /&gt;
        userdb prefetch {&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        userdb sql {&lt;br /&gt;
                args = /etc/dovecot/dovecot-sql.conf&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
        socket listen {&lt;br /&gt;
                client {&lt;br /&gt;
                        path    = /var/spool/postfix/private/dovecot-auth.sock&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = postfix&lt;br /&gt;
                        group   = postfix&lt;br /&gt;
                        }&lt;br /&gt;
                # These lines below are for the deliver lda&lt;br /&gt;
                master {&lt;br /&gt;
                        path =  /var/run/dovecot/auth-master&lt;br /&gt;
                        mode    = 0660&lt;br /&gt;
                        user    = vmail&lt;br /&gt;
                        group   = vmail&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
protocol imap {                                                               &lt;br /&gt;
         mail_plugins = quota imap_quota                                       &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
protocol pop3 {                                                               &lt;br /&gt;
         mail_plugins = quota                                                  &lt;br /&gt;
         }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
dict {                                                                        &lt;br /&gt;
        quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf                &lt;br /&gt;
        }                                                                     &lt;br /&gt;
                                                                              &lt;br /&gt;
plugin {                                                                      &lt;br /&gt;
         quota = dict:user::proxy::quotadict                                   &lt;br /&gt;
         }                                                     &lt;br /&gt;
                                                              &lt;br /&gt;
protocol lda {                                                &lt;br /&gt;
   postmaster_address = postmaster@host.example.com&lt;br /&gt;
   mail_plugins = quota                                        &lt;br /&gt;
   auth_socket_path =  /var/run/dovecot/auth-master&lt;br /&gt;
   sendmail_path = /usr/sbin/sendmail&lt;br /&gt;
}                                                                            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You should already have a &amp;lt;tt&amp;gt;socket-&amp;gt; listen-&amp;gt; client&amp;lt;/tt&amp;gt; section, but it is listed above to show where it goes in relationship to the &amp;lt;tt&amp;gt;socket -&amp;gt; listen -&amp;gt; master&amp;lt;/tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* edit &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-sql.conf&amp;lt;/tt&amp;gt; and replace the user and password queries with the following (you may not have a user_query yet - add it):&lt;br /&gt;
&lt;br /&gt;
 password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, &#039;*:bytes=&#039; || quota as userdb_quota_rule from mailbox  where local_part = &#039;%n&#039; and domain = &#039;%d&#039;&lt;br /&gt;
 user_query = select &#039;/var/mail/domains/&#039; || maildir as home, 1006 as uid, 1006 as gid, &#039;*:bytes=&#039; || quota  as quota_rule from mailbox where local_part = &#039;%n&#039; and domain =&#039;%d&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create &amp;lt;tt&amp;gt;/etc/dovecot/dovecot-dict-quota.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 connect = host=localhost dbname=postfix user=postfix password=********&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
         pattern = priv/quota/storage&lt;br /&gt;
         table = quota2&lt;br /&gt;
         username_field =username&lt;br /&gt;
         value_field = bytes&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 map {&lt;br /&gt;
        pattern= priv/quota/messages&lt;br /&gt;
        table = quota2&lt;br /&gt;
        username_field = username&lt;br /&gt;
        value_field = messages&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Again, change the password above to your postfix user password, and protect the file from prying eyes:&lt;br /&gt;
  chown root:root /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
  chmod 600 /etc/dovecot/dovecot-dict-quota.conf&lt;br /&gt;
&lt;br /&gt;
Side note: [http://wiki.dovecot.org/Quota/Dict 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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* create a new transport for the dovecot lda.   Add the following to  /etc/postfix/master.cf:&lt;br /&gt;
 # The dovecot deliver lda&lt;br /&gt;
 dovecot   unix  -       n       n       -       -       pipe&lt;br /&gt;
   flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}&lt;br /&gt;
&lt;br /&gt;
* Edit the /etc/postfix/main.cf.  Replace &lt;br /&gt;
 virtual_transport = virtual &lt;br /&gt;
with&lt;br /&gt;
 virtual_transport = dovecot&lt;br /&gt;
 dovecot_destination_recipient_limit = 1&lt;br /&gt;
&lt;br /&gt;
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:&lt;br /&gt;
&lt;br /&gt;
 chown vmail:vmail /var/log/dovecot*&lt;br /&gt;
&lt;br /&gt;
Restart Postfix and Dovecot:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/postfix restart&lt;br /&gt;
 /etc/init.d/dovecot restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039;  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.&lt;br /&gt;
&lt;br /&gt;
=== WebMail (RoundCube) ===&lt;br /&gt;
&lt;br /&gt;
[http://roundcube.net/ RoundCube] is an &amp;quot;ajax /Web2.0&amp;quot; web-mail client.  These instructions are for the Alpine Linux 1.10 repository &lt;br /&gt;
&lt;br /&gt;
* Add the package and related php modules:&lt;br /&gt;
 apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv&lt;br /&gt;
&lt;br /&gt;
* link the roundcube application back into the docroot&lt;br /&gt;
 ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube&lt;br /&gt;
&lt;br /&gt;
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R lighttpd:lighttpd temp logs&lt;br /&gt;
 &lt;br /&gt;
 su postgres&lt;br /&gt;
 createuser roundcube&lt;br /&gt;
   Shall the new role be a superuser? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create databases? (y/n) n&lt;br /&gt;
   Shall the new role be allowed to create more new roles? (y/n) y&lt;br /&gt;
 createdb -O roundcube -E UNICODE -T template0 roundcubemail&lt;br /&gt;
 psql roundcubemail&lt;br /&gt;
   roundcubemail=# ALTER USER roundcube WITH PASSWORD &#039;the_new_password&#039;;&lt;br /&gt;
   roundcubemail=# \c - roundcube&lt;br /&gt;
   roundcubemail=&amp;gt; \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql&lt;br /&gt;
   roundcubemail=&amp;gt; \q&lt;br /&gt;
 exit&lt;br /&gt;
&lt;br /&gt;
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC&lt;br /&gt;
&lt;br /&gt;
* restart lighttpd to verify the new php libraries are used&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
* Point your browser to http://host.example.com/roundcube/installer&lt;br /&gt;
* Start installation&lt;br /&gt;
&lt;br /&gt;
For the specific configuration parameters in the install step:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Property&lt;br /&gt;
!Setting&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;enable_spellcheck&#039;&#039; ||   disabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;identities_level&#039;&#039; ||  one identity with possibility to edit all params but not email address &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;log driver&#039;&#039; || syslog &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sylog_id&#039;&#039; || roundcube &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;syslog_facility&#039;&#039; || mailsubsystem &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;db_dnsw&#039;&#039; || pgsql properties, as described above &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;imap_host&#039;&#039; || 127.0.0.1 &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;auto_create_user&#039;&#039; || enabled &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_server&#039;&#039; ||  127.0.0.1&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_port&#039;&#039; ||  25&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_user/smtp_pass&#039;&#039; ||  enable &#039;&#039;Use Current IMAP username and password for SMTP authentication&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;smtp_log&#039;&#039; ||  enable (optional, but gives additional log record)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The other items can be left at default settings, or adjusted if desired.&lt;br /&gt;
&lt;br /&gt;
* Follow the instructions in step 3 of the install to copy the files to the server&lt;br /&gt;
* You should now be able to get to roundcube at http://host.example.com/roundcube&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;one&#039;&#039;&#039; of the following:&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 rm -rf LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
or&lt;br /&gt;
 cd /usr/share/webapps/roundcube&lt;br /&gt;
 chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG  SQL installer&lt;br /&gt;
 chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL &lt;br /&gt;
 chmod 700 SQL installer&lt;br /&gt;
&lt;br /&gt;
==== Enable Plug-ins ====&lt;br /&gt;
&lt;br /&gt;
RoundCube has various useful plug-ins, which could be found in &#039;&#039;/usr/share/webapps/roundcube/plugins&#039;&#039; directory. For example you may want to enable &#039;&#039;password&#039;&#039; plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.&lt;br /&gt;
&lt;br /&gt;
* Grant limited permissions for &#039;&#039;roundcube&#039;&#039; database role &lt;br /&gt;
 psql -U postgres postfix&lt;br /&gt;
   postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT SELECT (username) ON mailbox TO roundcube;&lt;br /&gt;
   postfix=# GRANT INSERT ON log TO roundcube;&lt;br /&gt;
   postfix=# \q&lt;br /&gt;
&lt;br /&gt;
* Setup &#039;&#039;password&#039;&#039; plug-in parameters in &#039;&#039;/usr/share/webapps/roundcube/plugins/password/config.inc.php&#039;&#039;&lt;br /&gt;
 mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
 vi /usr/share/webapps/roundcube/plugins/password/config.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;password_minimum_length&#039;] = 7;&lt;br /&gt;
$rcmail_config[&#039;password_require_nonalpha&#039;] = true;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_db_dsn&#039;] = &#039;pgsql://roundcube:&amp;lt;roundcube_password&amp;gt;@localhost/postfix&#039;;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;password_query&#039;] = &amp;quot;UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || &#039; (&#039; || %h || &#039;)&#039;,%d,&#039;edit_password&#039;,%u)&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Enable &#039;&#039;password&#039;&#039; plug-in&lt;br /&gt;
 vi /usr/share/webapps/roundcube/config/main.inc.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;plugins&#039;] = array(&#039;password&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP based Address Book ===&lt;br /&gt;
&lt;br /&gt;
This OpenLDAP configuration uses the SQL backend, which represents information stored in PostgreSQL as an LDAP subtree for Address Book functionality for email lookups, user authentication or even &lt;br /&gt;
replication account information between sites. This procedure uses some metainformation to translate LDAP queries to SQL queries, leaving relational schema untouched, which allows SQL and LDAP &lt;br /&gt;
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. &lt;br /&gt;
&lt;br /&gt;
* Install OpenLDAP and ODBC&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The psqlodbc package is currently unavailable&lt;br /&gt;
&lt;br /&gt;
* Update &amp;quot;postfix&amp;quot; database (it will add &#039;id&#039; columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: These instructions are for example domain example.com. So make sure you replaced all entries of &#039;example&#039; and &#039;com&#039; according to your domain name parts.&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE domain ADD COLUMN id SERIAL; &lt;br /&gt;
ALTER TABLE mailbox ADD COLUMN id SERIAL; &lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_entry_objclasses (&lt;br /&gt;
    entry_id integer NOT NULL,&lt;br /&gt;
    oc_name character varying(64)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_oc_mappings (&lt;br /&gt;
    name character varying(64) NOT NULL,&lt;br /&gt;
    keytbl character varying(64) NOT NULL,&lt;br /&gt;
    keycol character varying(64) NOT NULL,&lt;br /&gt;
    create_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE ldap_attr_mappings (&lt;br /&gt;
    oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),&lt;br /&gt;
    name character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr character varying(255) NOT NULL,&lt;br /&gt;
    sel_expr_u character varying(255),&lt;br /&gt;
    from_tbls character varying(255) NOT NULL,&lt;br /&gt;
    join_where character varying(255),&lt;br /&gt;
    add_proc character varying(255),&lt;br /&gt;
    delete_proc character varying(255),&lt;br /&gt;
    param_order integer NOT NULL,&lt;br /&gt;
    expect_return integer NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;&lt;br /&gt;
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_dcs AS&lt;br /&gt;
    ((SELECT (domain.id + 100000) AS id,&lt;br /&gt;
            (&#039;dc=&#039;::text || replace((domain.domain)::text, &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
            1 AS oc_map_id,&lt;br /&gt;
            100000 AS parent,&lt;br /&gt;
            0 AS keyval,&lt;br /&gt;
            domain.domain&lt;br /&gt;
     FROM domain&lt;br /&gt;
     WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;)&lt;br /&gt;
      UNION&lt;br /&gt;
     (SELECT 100000 AS id,&lt;br /&gt;
           (&#039;dc=&#039; || regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS dn,&lt;br /&gt;
           1 AS oc_map_id,&lt;br /&gt;
           0 AS parent,&lt;br /&gt;
           0 AS keyval,&lt;br /&gt;
           (regexp_replace((domain.domain)::text, &#039;.*\\.&#039;, &#039;&#039;::text)) AS domain&lt;br /&gt;
      FROM domain&lt;br /&gt;
      WHERE domain.domain &amp;lt;&amp;gt; &#039;ALL&#039;&lt;br /&gt;
      LIMIT 1));&lt;br /&gt;
&lt;br /&gt;
CREATE VIEW ldap_entries AS&lt;br /&gt;
    SELECT mailbox.id,&lt;br /&gt;
    (((&#039;cn=&#039;::text || initcap(replace(split_part((mailbox.username)::text, &#039;@&#039;::text, 1), &#039;.&#039;::text, &#039; &#039;::text))) || &#039;,dc=&#039;::text) ||&lt;br /&gt;
             replace(regexp_replace((mailbox.username)::text, &#039;.*@&#039;, &#039;&#039;::text), &#039;.&#039;::text, &#039;,dc=&#039;::text)) AS dn,&lt;br /&gt;
          1 AS oc_map_id,&lt;br /&gt;
          (SELECT ldap_dcs.id&lt;br /&gt;
           FROM ldap_dcs&lt;br /&gt;
           WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,&lt;br /&gt;
           mailbox.id AS keyval&lt;br /&gt;
           FROM mailbox&lt;br /&gt;
           UNION&lt;br /&gt;
           SELECT ldap_dcs.id,&lt;br /&gt;
                  ldap_dcs.dn,&lt;br /&gt;
                  ldap_dcs.oc_map_id,&lt;br /&gt;
                  ldap_dcs.parent,&lt;br /&gt;
                  ldap_dcs.keyval&lt;br /&gt;
           FROM ldap_dcs;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Fill out LDAP tables according to following example (make sure to separate values with TABs):&lt;br /&gt;
&lt;br /&gt;
Put the following into a new file called &#039;&#039;&#039;script&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;&lt;br /&gt;
1	exampleBox	mailbox	id	\N	\N	1&lt;br /&gt;
\.&lt;br /&gt;
COPY ldap_attr_mappings (id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return) FROM stdin;&lt;br /&gt;
1	1	displayName	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
2	1	mail	mailbox.username	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
3	1	cn	mailbox.name	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
4	1	userPassword	&#039;{CRYPT}&#039;||mailbox.password	\N	mailbox	\N	\N	\N	3	0&lt;br /&gt;
\.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, execute the commands in the file with:&lt;br /&gt;
 cat script | psql -U postfix postfix&lt;br /&gt;
 rm script&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_dcs&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_dcs&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |             dn              | oc_map_id | parent | keyval |       domain       &lt;br /&gt;
--------+-----------------------------+-----------+--------+--------+--------------------&lt;br /&gt;
 100000 | dc=com                      |         1 |      0 |      0 | com&lt;br /&gt;
 100001 | dc=example,dc=com           |         1 | 100000 |      0 | example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Check that &amp;quot;ldap_entries&amp;quot; view looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;select * from ldap_entries&#039; | psql -U postgres postfix&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   id   |                          dn                           | oc_map_id | parent | keyval &lt;br /&gt;
--------+-------------------------------------------------------+-----------+--------+--------&lt;br /&gt;
    1   | cn=address1,dc=example,dc=com                         |         1 | 100001 |    1&lt;br /&gt;
...&lt;br /&gt;
   123  | cn=address123,dc=example,dc=com                       |         1 | 100001 |    1&lt;br /&gt;
 100000 | dc=com                                                |         1 |      0 |    0&lt;br /&gt;
 100001 | dc=example,dc=com                                     |         1 | 100000 |    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure ODBC parameters&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbc.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description             = Connection to Postgres&lt;br /&gt;
Driver                  = PostgreSQL&lt;br /&gt;
Trace                   = Yes&lt;br /&gt;
TraceFile               = sql.log&lt;br /&gt;
Database                = postfix&lt;br /&gt;
Servername              = 127.0.0.1&lt;br /&gt;
UserName                =&lt;br /&gt;
Password                =&lt;br /&gt;
Port                    = 5432&lt;br /&gt;
Protocol                = 6.4&lt;br /&gt;
ReadOnly                = No&lt;br /&gt;
RowVersining            = No&lt;br /&gt;
ShowSystemTables        = No&lt;br /&gt;
ShowOidColumn           = No&lt;br /&gt;
FakeOidIndex            = No&lt;br /&gt;
ConnSettings            =&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit /etc/odbcinst.ini:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[PostgreSQL]&lt;br /&gt;
Description     = PostgreSQL driver for Linux&lt;br /&gt;
Driver          = /usr/lib/psqlodbcw.so&lt;br /&gt;
Setup           = /usr/lib/libodbcpsqlS.so&lt;br /&gt;
FileUsage       = 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test ODBC connection&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;select * from domain;&amp;quot; | isql PostgreSQL postgres&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Provide permission to certificate for LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Edit LDAP schema&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/schema/example.com.schema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.3&lt;br /&gt;
	NAME ( &#039;mail&#039; &#039;rfc822Mailbox&#039; )&lt;br /&gt;
	DESC &#039;RFC1274: RFC822 Mailbox&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.16.840.1.113730.3.1.241&lt;br /&gt;
	NAME &#039;displayName&#039;&lt;br /&gt;
	DESC &#039;RFC2798: preferred name to be used when displaying entries&#039;&lt;br /&gt;
	EQUALITY caseIgnoreMatch&lt;br /&gt;
	SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15&lt;br /&gt;
	SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
objectclass   ( 2.16.840.1.113730.3.2.2&lt;br /&gt;
        NAME &#039;exampleBox&#039;&lt;br /&gt;
	DESC &#039;example.com mailbox&#039;&lt;br /&gt;
	MUST ( displayName $ mail $ userPassword )&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
# RFC 1274 + RFC 2247&lt;br /&gt;
attributetype ( 0.9.2342.19200300.100.1.25&lt;br /&gt;
        NAME ( &#039;dc&#039; &#039;domainComponent&#039; )&lt;br /&gt;
        DESC &#039;RFC1274/2247: domain component&#039;&lt;br /&gt;
        EQUALITY caseIgnoreIA5Match&lt;br /&gt;
        SUBSTR caseIgnoreIA5SubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )&lt;br /&gt;
&lt;br /&gt;
attributetype ( 2.5.4.46 NAME &#039;dnQualifier&#039;&lt;br /&gt;
        DESC &#039;RFC2256: DN qualifier&#039;&lt;br /&gt;
        EQUALITY caseIgnoreMatch&lt;br /&gt;
        ORDERING caseIgnoreOrderingMatch&lt;br /&gt;
        SUBSTR caseIgnoreSubstringsMatch&lt;br /&gt;
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP server&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/slapd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
include         /etc/openldap/schema/example.com.schema&lt;br /&gt;
pidfile         /var/run/openldap/slapd.pid&lt;br /&gt;
argsfile        /var/run/openldap/slapd.args&lt;br /&gt;
&lt;br /&gt;
TLSCipherSuite HIGH&lt;br /&gt;
TLSCACertificateFile /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLSCertificateFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLSVerifyClient never &lt;br /&gt;
&lt;br /&gt;
# This is needed for proper representation of MD5-CRYPT format stored in database&lt;br /&gt;
#  see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/&lt;br /&gt;
password-hash  {CRYPT}&lt;br /&gt;
password-crypt-salt-format &amp;quot;$1$%.8s&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loglevel        stats&lt;br /&gt;
moduleload	/usr/lib/openldap/back_sql.so&lt;br /&gt;
sizelimit 3000&lt;br /&gt;
&lt;br /&gt;
database        sql&lt;br /&gt;
&lt;br /&gt;
dbname		PostgreSQL&lt;br /&gt;
dbuser		postfix&lt;br /&gt;
dbpasswd	*****&lt;br /&gt;
&lt;br /&gt;
suffix          &amp;quot;dc=example,dc=com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
upper_func      &amp;quot;upper&amp;quot;&lt;br /&gt;
strcast_func    &amp;quot;text&amp;quot;&lt;br /&gt;
concat_pattern  &amp;quot;?||?&amp;quot;&lt;br /&gt;
has_ldapinfo_dn_ru      no&lt;br /&gt;
lastmod         off&lt;br /&gt;
&lt;br /&gt;
access to attrs=userPassword by * auth&lt;br /&gt;
&lt;br /&gt;
access to * by peername.ip=127.0.0.1 read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt;%&amp;lt;netmask&amp;gt; read&lt;br /&gt;
#           by peername.ip=&amp;lt;IP&amp;gt; read&lt;br /&gt;
	    by users read&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Set permissions for slapd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown ldap:ldap /etc/openldap/slapd.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL&lt;br /&gt;
&lt;br /&gt;
Edit /etc/conf.d/slapd:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc_need=&amp;quot;postgresql&amp;quot; &lt;br /&gt;
OPTS=&amp;quot;-h &#039;ldaps:// ldap://127.0.0.1&#039;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Start LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rc-update add slapd default&lt;br /&gt;
/etc/init.d/slapd start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure LDAP client utilities&lt;br /&gt;
&lt;br /&gt;
Edit /etc/openldap/ldap.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BASE	dc=example,dc=com&lt;br /&gt;
URI	ldaps://host.example.com&lt;br /&gt;
&lt;br /&gt;
TLS_CACERT /etc/lighttpd/ca-crt.pem&lt;br /&gt;
TLS_CERT /etc/lighttpd/server-bundle.pem&lt;br /&gt;
TLS_KEY /etc/lighttpd/server-bundle.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Test LDAP server&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ldapsearch -z 3&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com&lt;br /&gt;
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Configure RoundCube webmail for email lookups&lt;br /&gt;
&lt;br /&gt;
In order to enable php-ldap support you need to restart lighttpd server&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/lighttpd restart&lt;br /&gt;
&lt;br /&gt;
Edit /usr/share/webapps/roundcube/config/main.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$rcmail_config[&#039;ldap_debug&#039;] = false;&lt;br /&gt;
...&lt;br /&gt;
$rcmail_config[&#039;address_book_type&#039;] = &#039;sql&#039;;&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;ldap_public&#039;][&#039;example.com&#039;] = array(&lt;br /&gt;
  &#039;name&#039;          =&amp;gt; &#039;example.com&#039;,&lt;br /&gt;
  &#039;hosts&#039;         =&amp;gt; array(&#039;127.0.0.1&#039;),&lt;br /&gt;
  &#039;port&#039;          =&amp;gt; 389,&lt;br /&gt;
  &#039;use_tls&#039;         =&amp;gt; false,&lt;br /&gt;
  &#039;user_specific&#039; =&amp;gt; false,&lt;br /&gt;
  &#039;base_dn&#039;       =&amp;gt; &#039;dc=example,dc=com&#039;,&lt;br /&gt;
  &#039;bind_dn&#039;       =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;bind_pass&#039;     =&amp;gt; &#039;&#039;,&lt;br /&gt;
  &#039;writable&#039;      =&amp;gt; false,&lt;br /&gt;
  &#039;LDAP_Object_Classes&#039; =&amp;gt; array(&amp;quot;top&amp;quot;, &amp;quot;exampleBox&amp;quot;),&lt;br /&gt;
  &#039;required_fields&#039;     =&amp;gt; array(&amp;quot;cn&amp;quot;, &amp;quot;sn&amp;quot;, &amp;quot;mail&amp;quot;),&lt;br /&gt;
  &#039;LDAP_rdn&#039;      =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;ldap_version&#039;  =&amp;gt; 3,&lt;br /&gt;
  &#039;search_fields&#039; =&amp;gt; array(&#039;mail&#039;, &#039;cn&#039;, &#039;sn&#039;, &#039;givenName&#039;),&lt;br /&gt;
  &#039;name_field&#039;    =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;email_field&#039;   =&amp;gt; &#039;mail&#039;,&lt;br /&gt;
  &#039;surname_field&#039; =&amp;gt; &#039;sn&#039;,&lt;br /&gt;
  &#039;firstname_field&#039; =&amp;gt; &#039;gn&#039;,&lt;br /&gt;
  &#039;sort&#039;          =&amp;gt; &#039;cn&#039;,&lt;br /&gt;
  &#039;scope&#039;         =&amp;gt; &#039;sub&#039;,&lt;br /&gt;
  &#039;filter&#039;        =&amp;gt; &#039;(objectClass=*)&#039;, // Construct here any filter you need&lt;br /&gt;
  &#039;fuzzy_search&#039;  =&amp;gt; true);&lt;br /&gt;
&lt;br /&gt;
$rcmail_config[&#039;autocomplete_addressbooks&#039;] = array(&#039;sql&#039;,&#039;example.com&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Fix PostfixAdmin to work with the new table definition&lt;br /&gt;
&lt;br /&gt;
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With the lines:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,&lt;br /&gt;
   domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,&lt;br /&gt;
   domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== log rotation ==&lt;br /&gt;
&lt;br /&gt;
Ensure the busybox cron service is started and is configured to auto-start:&lt;br /&gt;
&lt;br /&gt;
 /etc/init.d/cron start&lt;br /&gt;
 rc-update add cron default&lt;br /&gt;
&lt;br /&gt;
Add log rotate:&lt;br /&gt;
&lt;br /&gt;
 apk add logrotate&lt;br /&gt;
&lt;br /&gt;
Edit &#039;&#039;/etc/logrotate.conf&#039;&#039; as desired, but the defaults should be sufficient for most people.&lt;br /&gt;
&lt;br /&gt;
== Optional: Configure Web Server Virtual Domains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; These steps can be done &#039;&#039;in addition to&#039;&#039; the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you provide SSL access for multiple domain site you may need to follow http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:SSL#SSL-on-multiple-domains in order to provide multi-domain certificates. If you would like to redirect hosts to their secure equivalents use the following instructions http://redmine.lighttpd.net/projects/lighttpd/wiki/HowToRedirectHttpToHttps.&lt;br /&gt;
&lt;br /&gt;
This server hosts three separate web applications, and these can be handled as three &#039;&#039;different&#039;&#039; virtual domains on the same web server. They will be distinguished by their DNS names, so you can choose domains for the three separate services (or at least the ones you want to publish):&lt;br /&gt;
&lt;br /&gt;
* ACF - Alpine Configuration Framework for managing the server&lt;br /&gt;
* PostfixAdmin - for managing the postfix installation&lt;br /&gt;
* RoundCube - for accessing individual mailboxes&lt;br /&gt;
&lt;br /&gt;
Choose three different domains (from here on known as ACF_DOMAIN, POSTFIXADMIN_DOMAIN, and ROUNDCUBE_DOMAIN) and configure DNS for all three to point to the IP address of your host. These should be DNS &#039;&#039;&#039;A&#039;&#039;&#039; records.&lt;br /&gt;
&lt;br /&gt;
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ACF_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ACF_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;POSTFIXADMIN_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/POSTFIXADMIN_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $HTTP[&amp;quot;host&amp;quot;] == &amp;quot;ROUNDCUBE_DOMAIN&amp;quot; {&lt;br /&gt;
	simple-vhost.server-root   = &amp;quot;/var/www/domains/&amp;quot;&lt;br /&gt;
	simple-vhost.default-host  = &amp;quot;/ROUNDCUBE_DOMAIN/&amp;quot;&lt;br /&gt;
	simple-vhost.document-root = &amp;quot;www/&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, then link the appropriate www directories.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  mkdir -p /var/www/domains/ACF_DOMAIN&lt;br /&gt;
  ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN&lt;br /&gt;
  ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www&lt;br /&gt;
&lt;br /&gt;
  mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN&lt;br /&gt;
  ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ppalonen</name></author>
	</entry>
</feed>