https://wiki.alpinelinux.org/w/api.php?action=feedcontributions&user=Iilluzion&feedformat=atomAlpine Linux - User contributions [en]2024-03-29T02:10:27ZUser contributionsMediaWiki 1.40.0https://wiki.alpinelinux.org/w/index.php?title=Redmine&diff=8296Redmine2012-07-03T10:29:13Z<p>Iilluzion: small fixes in redmine and lighttpd sections</p>
<hr />
<div>{{Draft}}<br />
<br />
NOTE: This is a complete rewrite of our Redmine install how-to. Previously, Ruby packages needed by Redmine needed to be installed manually with rubygems. Now we have Ruby packages needed for Remine in our repository. As of writing, ruby packages are maintained in testing repository.<br />
<br />
=Some assumptions=<br />
<br />
* For this how-to we assume you are running an Hard-disk install of Alpine Linux. If you are running from RAM, please make sure you use LBU.<br />
* Alpine Linux uses Lighttpd as default web-server. Redmine will be running with FastCGI inside Lighttpd. If you like to install Redmine with any other web-server, you will need to install it manually. Which are currently: ruby-rails ruby-fcgi ruby-rmagick ruby-i18n ruby-openid rubygems<br />
* We are using MySQL as database for our Redmine install. Redmine is also able to run with PostgreSQL or SQLite.<br />
* MySQL is running on a remote location. Please follow other tutorials on how to setup MySQL. (need link).<br />
* Detailed information regarding Redmine installation can be found: http://www.redmine.org/projects/redmine/wiki/RedmineInstall<br />
<br />
<br />
=Installing Redmine=<br />
<br />
{{Cmd|apk add redmine}}<br />
<br />
On a Alpine base install this should pull in approximately 50 packages including (almost) all Ruby dependencies and Lighttpd. If you like to run a different webserver, you will need to skip redmine package and install all deps manually with apk.<br />
<br />
=Database support=<br />
Redmine supports various database backends. Here we will only cover MySQL and PostgreSQL.<br />
<br />
== Option 1 - MySQL ==<br />
For Redmine to communicate with MySQL server we will need to have the mysql ruby package. (if you want to run another db, just install the appropriate db package).<br />
<br />
{{Cmd|apk add ruby-mysql}}<br />
<br />
Now before we continue we need to prepare our database. According [http://www.redmine.org/projects/redmine/wiki/RedmineInstall Redmine website] you need to do the following:<br />
<br />
{{Cmd|create database redmine character set utf8;<br />
create user 'redmine'@'localhost' identified by 'my_password';<br />
grant all privileges on redmine.* to 'redmine'@'localhost';}}<br />
<br />
If you need mysql client, you can install it like this:<br />
<br />
{{Cmd|apk add mysql-client}}<br />
<br />
You can of course also use a tool like phpmyadmin to create the database and setup the user.<br />
<br />
== Option 2 - PostgreSQL ==<br />
{{Cmd|apk add ruby-pg postgresql}}<br />
<br />
Initialize and start database engine:<br />
{{Cmd|/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start}}<br />
<br />
Create redmine db user, replacing 'redminepw' with your own password:<br />
{{Cmd|psql -U postgres -c "CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD 'reminepw' NOINHERIT VALID UNTIL 'infinity';"}}<br />
<br />
Create the redmine database (note that you need template0 for UTF8):<br />
{{Cmd|<nowiki>psql -U postgres -c "CREATE DATABASE redmine WITH ENCODING 'UTF8' OWNER=redmine TEMPLATE = template0;"</nowiki>}}<br />
<br />
=Redmine config files=<br />
<br />
Redmine default config files are located inside /etc/redmine. For Redmine to find your database, please edit database.yml. We have removed all entries accept the default production one. For examples please check: /var/www/localhost/htdocs/redmine/config<br />
If you need to edit additional configuration files, please move them to /etc/redmine and link them back to the original location. This way apk will use config protect and not overwrite your config files on update. Don't forget to edit the other files, like your SMTP configuration in configuration.yml.<br />
<br />
First we need to generate a session store secret:<br />
<br />
su -pc "cd /var/www/localhost/htdocs/redmine; /usr/lib/ruby/gems/1.8/bin/rake generate_session_store" lighttpd<br />
<br />
Now we populate the database:<br />
<br />
su -pc "cd /var/www/localhost/htdocs/redmine; RAILS_ENV=production /usr/lib/ruby/gems/1.8/bin/rake db:migrate" lighttpd<br />
<br />
=Setup Lighttpd=<br />
<br />
Now our database is ready, we need to configure Lighttpd. We have included an example Redmine/Ligghtpd configuration based on FastCGI. You can find it in /etc/lighttpd.<br />
When you are finished setting up Ligghtpd configuation include it inside lighttpd.conf and we can start it.<br />
<br />
{{Cmd|vi /etc/lighttpd/redmine-virtual.conf}}<br />
<br />
{{Cmd|vi /etc/lighttpd/lighttpd.conf}}<br />
<br />
... <br />
include "redmine-virtual.conf"<br />
...<br />
<br />
{{Cmd|/etc/init.d/lighttpd start}}<br />
<br />
If your server does not run, you can find information in /var/log/lighttpd. If that does not provide a clue you can also run Lighttpd in foreground. It should display some more debug information.<br />
<br />
{{Cmd|/etc/init.d/lighttpd stop<br />
lighttpd -f /etc/lighttpd/lighttpd.conf -D}}<br />
<br />
= Enabling Email to Ticket =<br />
''Note:'' This configuration is not very secure in that it uses out of the box postfix configuration. It's assumed that additional configuration will be applied to postfix, but that is outside of the scope of this section.<br />
<br />
First, add postfix.<br />
{{Cmd|apk add postfix}}<br />
Add aliases to /etc/postfix/aliases (replace url with your URL and InsertKeyHere with your Redmine key):<br />
test: "|ruby /var/www/localhost/htdocs/redmine/extra/mail_handler/rdm-mailhandler.rb --url http://bugs.alpinelinux.org --key InsertKeyHere --project=test --unknown-user=accept --no-permission-check"<br />
Create aliases db<br />
newaliases<br />
Start Postfix<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=Optional: Enable Email to Ticket for Unknown Users=<br />
Note: To enable email to ticket creation from unknown users/email addresses (after allowing anonymous issue creation within Redmine UI) for the 'myproject' project in Redmine, create the following script and have your email server pipe new emails to this script:<br />
<br />
#!/usr/bin/perl<br />
# Author: Jeff Bilyk<br />
# March 2, 2011<br />
#Script to take email from stdin, then:<br />
# - Check redmine database to see if the user exists<br />
# - If user doesn't exist, create the user<br />
# - Pass the email on the redmine utility:<br />
# - echo "email contents" | rake redmine:email:read RAILS_ENV="production" project=myproject<br />
<br />
use strict;<br />
use DBI;<br />
# global variables<br />
my $DbName = 'redmine';<br />
my $DbUser = 'redmine';<br />
my $DbPassword = 'Secur3P@ass';<br />
my @fields;<br />
my @address;<br />
my $existinguser;<br />
<br />
# Get email from stdin<br />
my @email = <STDIN>;<br />
<br />
# Parse field for "for"<br />
foreach (@email)<br />
{<br />
if ($_ =~ /From/)<br />
{<br />
@fields = (split /</,$_);<br />
@address = (split />/,$fields[1]);<br />
}<br />
}<br />
<br />
my $dbh = DBI->connect('dbi:mysql:' . $DbName, $DbUser, $DbPassword, { PrintError => 0 }) or die "SQL Connect Error:" . DBI->errstr;<br />
<br />
# Find out if there're any existing users with the specified email address<br />
my $sqlStatement = "SELECT * from users where mail = '$address[0]';";<br />
<br />
my $sqlCommand = $dbh->prepare($sqlStatement);<br />
<br />
$sqlCommand->execute or die "SQL Error: " . DBI->errstr;<br />
<br />
my @sqlRecordset;<br />
$existinguser = 'maybe';<br />
<br />
@sqlRecordset = $sqlCommand->fetchrow_array;<br />
<br />
if ($sqlRecordset[0] == '') {<br />
printf "@sqlRecordset \n";<br />
$existinguser = 'no';<br />
}<br />
else {<br />
$existinguser = 'yes';<br />
}<br />
<br />
# If there isn't a user already, then create one<br />
if ($existinguser == 'no')<br />
{<br />
my @name = (split /@/,$address[0]);<br />
printf "Current variables: $name[0] $address[0] \n";<br />
$sqlStatement = "INSERT INTO users (login, firstname, lastname, mail, mail_notification, admin, status, language, type) values (\"$name[0]\", \"$name[0]\", \" \", \"$address[0]\", 0, 0, 1, \"en\", \"User\");";<br />
$sqlCommand = $dbh->prepare($sqlStatement);<br />
$sqlCommand->execute or die "SQL Error: " .DBI->errstr;<br />
printf "User created";<br />
}<br />
<br />
my $timeinsec = `date +%s`;<br />
open (MYFILE, ">>/var/tmp/$timeinsec");<br />
print MYFILE "@email";<br />
close (MYFILE);<br />
<br />
system("sed -i 's/^ //' /var/tmp/$timeinsec");<br />
system("sed -i 's/^ //' /var/tmp/$timeinsec");<br />
<br />
`cd /usr/share/webapps/redmine && rake redmine:email:read RAILS_ENV="production" project=myproject < /var/tmp/$timeinsec`;<br />
exit 0<br />
<br />
This document is a Work In Progress.<br />
<br />
[[Category:Server]]<br />
[[Category:Ruby]]<br />
[[Category:SQL]]<br />
[[Category:Programming]]</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5203ISP Mail Server 2.x HowTo2011-06-11T07:39:27Z<p>Iilluzion: /* Mailbox Quotas */</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
'''NOTE:''' Check http://sourceforge.net/tracker/index.php?func=detail&aid=2859165&group_id=191583&atid=937964 if you have bug on listing domains page.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql postfix-pcre<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
service anvil {<br />
client_limit = 2100<br />
}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/auth<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
service anvil {<br />
client_limit = 2100<br />
}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/<CA Certificate file><br />
ssl_cert = </etc/ssl/private/<Public part of certificate file><br />
ssl_key = </etc/ssl/private/<Private part of certificate file><br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd /var/log/roundcube<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5202ISP Mail Server 2.x HowTo2011-06-11T07:39:04Z<p>Iilluzion: set proper perms to auth-master socket file</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
'''NOTE:''' Check http://sourceforge.net/tracker/index.php?func=detail&aid=2859165&group_id=191583&atid=937964 if you have bug on listing domains page.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql postfix-pcre<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
service anvil {<br />
client_limit = 2100<br />
}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/auth<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/<CA Certificate file><br />
ssl_cert = </etc/ssl/private/<Public part of certificate file><br />
ssl_key = </etc/ssl/private/<Private part of certificate file><br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd /var/log/roundcube<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5201ISP Mail Server 2.x HowTo2011-06-11T07:38:14Z<p>Iilluzion: change dovecot log to standard facility - mail.log</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
'''NOTE:''' Check http://sourceforge.net/tracker/index.php?func=detail&aid=2859165&group_id=191583&atid=937964 if you have bug on listing domains page.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql postfix-pcre<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
service anvil {<br />
client_limit = 2100<br />
}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/auth<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/<CA Certificate file><br />
ssl_cert = </etc/ssl/private/<Public part of certificate file><br />
ssl_key = </etc/ssl/private/<Private part of certificate file><br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd /var/log/roundcube<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5200ISP Mail Server 2.x HowTo2011-06-11T07:36:36Z<p>Iilluzion: dovecot auth sock name corrected</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
'''NOTE:''' Check http://sourceforge.net/tracker/index.php?func=detail&aid=2859165&group_id=191583&atid=937964 if you have bug on listing domains page.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql postfix-pcre<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/auth<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/<CA Certificate file><br />
ssl_cert = </etc/ssl/private/<Public part of certificate file><br />
ssl_key = </etc/ssl/private/<Private part of certificate file><br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd /var/log/roundcube<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5199ISP Mail Server 2.x HowTo2011-06-11T06:03:18Z<p>Iilluzion: minor dovecot fixes</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
'''NOTE:''' Check http://sourceforge.net/tracker/index.php?func=detail&aid=2859165&group_id=191583&atid=937964 if you have bug on listing domains page.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql postfix-pcre<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/<CA Certificate file><br />
ssl_cert = </etc/ssl/private/<Public part of certificate file><br />
ssl_key = </etc/ssl/private/<Private part of certificate file><br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd /var/log/roundcube<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5198ISP Mail Server 2.x HowTo2011-06-10T11:02:12Z<p>Iilluzion: roundcube log directory chnaged</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
'''NOTE:''' Check http://sourceforge.net/tracker/index.php?func=detail&aid=2859165&group_id=191583&atid=937964 if you have bug on listing domains page.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql postfix-pcre<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
mail_location = maildir:/var/lib/mail/domains/%d/%n<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/<CA Certificate file><br />
ssl_cert = </etc/ssl/private/<Public part of certificate file><br />
ssl_key = </etc/ssl/private/<Private part of certificate file><br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd /var/log/roundcube<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5195ISP Mail Server 2.x HowTo2011-06-09T14:46:50Z<p>Iilluzion: /* Mailbox Quotas */</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
'''NOTE:''' Check http://sourceforge.net/tracker/index.php?func=detail&aid=2859165&group_id=191583&atid=937964 if you have bug on listing domains page.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql postfix-pcre<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
mail_location = maildir:/var/lib/mail/domains/%d/%n<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/<CA Certificate file><br />
ssl_cert = </etc/ssl/private/<Public part of certificate file><br />
ssl_key = </etc/ssl/private/<Private part of certificate file><br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5194ISP Mail Server 2.x HowTo2011-06-09T14:02:48Z<p>Iilluzion: http://sourceforge.net/tracker/index.php?func=detail&aid=2859165&group_id=191583&atid=937964</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
'''NOTE:''' Check http://sourceforge.net/tracker/index.php?func=detail&aid=2859165&group_id=191583&atid=937964 if you have bug on listing domains page.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql postfix-pcre<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
mail_location = maildir:/var/lib/mail/domains/%d/%n<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/comodo.ca.pem<br />
ssl_cert = </etc/ssl/private/srvmail.org.pem<br />
ssl_key = </etc/ssl/private/srvmail.org.pem<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=WordPress&diff=5193WordPress2011-06-09T09:03:26Z<p>Iilluzion: some fixes</p>
<hr />
<div>== Set up WordPress on Alpine Linux ==<br />
<br />
WordPress is web software you can use to create a beautiful website or blog. <br />
<br />
This document will be a quick c/p guide to setup WordPress on Alpine linux. What we will setup is the following:<br />
<br />
* Lighttpd with PHP <br />
* MySql<br />
* WordPress<br />
<br />
== Install lighttpd, PHP, and MySql ==<br />
{{:Setting Up Lighttpd With FastCGI}}<br />
Install extra packages:<br />
apk add php-mysql mysql mysql-client<br />
<br />
== Installing and configuring WordPress ==<br />
<br />
'''Install WordPress'''<br />
<br />
Make webapps folder<br />
<br />
mkdir /usr/share/webapps/ -p<br />
<br />
Download <br />
<br />
cd /usr/share/webapps/<br />
wget http://wordpress.org/latest.tar.gz<br />
<br />
Unpack <br />
<br />
tar -xzvf latest.tar.gz<br />
rm latest.tar.gz<br />
<br />
Change Folder Persmissions<br />
<br />
chown -R lighttpd /usr/share/webapps/wordpress<br />
<br />
Make symlinks to WordPress<br />
<br />
ln -s /usr/share/webapps/wordpress/ /var/www/localhost/htdocs/wordpress<br />
<br />
== Config and start MySql ==<br />
<br />
/usr/bin/mysql_install_db --user=mysql<br />
/etc/init.d/mysql start && rc-update add mysql default<br />
/usr/bin/mysqladmin -u root password 'password'<br />
<br />
'''Create the WordPress database'''<br />
<br />
mysql -u root -p<br />
<br />
CREATE DATABASE wordpress;<br />
GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'localhost' IDENTIFIED BY 'wordpress password';<br />
FLUSH PRIVILEGES;<br />
EXIT<br />
<br />
== Config your WordPress ==<br />
<br />
Browse<br />
<br />
http://WEBSERVER_IP_ADDRESS/WordPress/<br />
<br />
click on: "Create a Configuration File"<br />
click on: "Let’s go!"<br />
<br />
Database Name: wordpress<br />
User Name: wordpress<br />
Password: <wordpress password><br />
Database Host: localhost<br />
Table Prefix: wp_<br />
<br />
You may need create the wp-config.php manually, so modify define the 'DB_NAME', DB_USER and DB_PASSWORD, then copy and paste the text into it.<br />
After you've done that, click "Run the install."<br />
<br />
Enter Information needed<br />
<br />
Site Title<br />
Username<br />
Password, twice<br />
Your E-mail<br />
<br />
After you've done that, click "Install WordPress" <br />
<br />
You have WordPress working, to access go to http://WEBSERVER_IP_ADDRESS/wordpress and enjoy!</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5177ISP Mail Server 2.x HowTo2011-05-31T06:26:32Z<p>Iilluzion: pcre</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql postfix-pcre<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
mail_location = maildir:/var/lib/mail/domains/%d/%n<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/comodo.ca.pem<br />
ssl_cert = </etc/ssl/private/srvmail.org.pem<br />
ssl_key = </etc/ssl/private/srvmail.org.pem<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5173ISP Mail Server 2.x HowTo2011-05-30T08:04:29Z<p>Iilluzion: postfixadmin 2.3.3</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.3/postfixadmin-2.3.3.tar.gz<br />
tar zxvf postfixadmin-2.3.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
mail_location = maildir:/var/lib/mail/domains/%d/%n<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/comodo.ca.pem<br />
ssl_cert = </etc/ssl/private/srvmail.org.pem<br />
ssl_key = </etc/ssl/private/srvmail.org.pem<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5168ISP Mail Server 2.x HowTo2011-05-30T07:50:28Z<p>Iilluzion: "create language plpgsql;" is not needed anymore</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz<br />
tar zxvf postfixadmin-2.3.2.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
mail_location = maildir:/var/lib/mail/domains/%d/%n<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/comodo.ca.pem<br />
ssl_cert = </etc/ssl/private/srvmail.org.pem<br />
ssl_key = </etc/ssl/private/srvmail.org.pem<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Setting_up_iSCSI&diff=5167Setting up iSCSI2011-05-27T08:28:29Z<p>Iilluzion: typo</p>
<hr />
<div>trocorviboc<br />
== Introduction ==<br />
<br />
iSCSI consists of two pieces: A target (server) and an initiator (client). A target is a large pool of disk space that can be accessed over IP by the initiators. Initiators use the disk space, formatting it and mounting it the same as local disk. When an initiator connects to a target a scsi device node is created (e.g. /dev/sda, /dev/sdb, etc)<br />
<br />
== iSCSI Target ==<br />
<br />
The ''iscsitarget-X.X.apk'' package provides the target functionality. It includes the ietd service (ietd is the iSCSI Enterprise Target Daemon). The ''iscitarget-grsec'' package includes the kernel drivers for the ''grsec'' flavor of linux kernel.<br />
Install with:<br />
{{Cmd|apk add iscsitarget iscsitarget-grsec}}<br />
Once the packages are [[Alpine_package_management#Add_a_Package|installed]], you can set up a target by editing two conf files.<br />
<br />
<br />
In /etc/ietd.conf, add the following information:<br />
<br />
Target iqn.2006-01.com.example:disk2.vol1<br />
Lun 0 Path=/dev/sda1, Type=fileio<br />
<br />
The iSCSI Qualified Name is documented in [http://www.ietf.org/rfc/rfc3720.txt RFC 3720], with further examples of names in [http://www.ietf.org/rfc/rfc3721.txt RFC 3721]. Briefly, the fields are:<br />
<br />
* literal '''iqn'''<br />
* date (yyyy-mm) that the naming authority took ownership of the domain<br />
* reversed domain name of the authority (''org.alpinelinux, com.example, to.yp.cr'') <br />
* Optional ":" prefixing a storage target name specified by the naming authority.<br />
<br />
From the RFC:<br />
Naming String defined by<br />
Type Date Auth "example.com" naming authority<br />
+--++-----+ +---------+ +--------------------------------+<br />
| || | | | | | <br />
<br />
iqn.2001-04.com.example:storage:diskarrays-sn-a8675309<br />
iqn.2001-04.com.example<br />
iqn.2001-04.com.example:storage.tape1.sys1.xyz<br />
iqn.2001-04.com.example:storage.disk2.sys1.xyz<br />
<br />
<br />
The "Target" line above is an example. This line really just needs to be unique. /dev/sdx refers to the disk and partition that will be presented to the initiator. <br />
<br />
In the /etc/initiators.allow file, add the following line:<br />
<br />
iqn.2006-01.com.example:disk2.vol1 10.1.194.111<br />
<br />
The IP address in the line above will be the initiator's ip address. Now only this ip address is allowed to access this specific target. You must use IP addresses, not hostnames.<br />
<br />
If you don't care where the initiator is connecting from, you can use the keyword '''ALL'':<br />
<br />
iqn.2006-01.com.example:disk2.vol1 ALL<br />
<br />
== iSCSI Initiator ==<br />
The initator is in the ''open-iscsi'' package. Load this package on the client.<br />
<br />
To configure the iSCSI initiator, add the initiator name to the file /etc/iscsi/initiatorname.iscsi The initator name follows the same iqn naming scheme as the target; but this is iderntifing the initator (client).<br />
<br />
InitiatorName=iqn.2007-11.org.alpinelinux.client:01<br />
<br />
or <br />
InitiatorName=iqn.2007-11.com.example.me:foo:bar:baz<br />
<br />
<br />
The ''01'', ''foo:bar:baz'' are arbitrary. You can enter anything (or nothing)- as long as the intiator name is a valid iqn.<br />
<br />
<br />
Start the initiator daemon with<br />
/etc/init.d/iscsid start<br />
<br />
== Connecting the Initiator to the Target ==<br />
<br />
From the iSCSI initiator, first run this command:<br />
<br />
iscsiadm --mode discovery --type sendtargets --portal IP_OF_TARGET<br />
<br />
This command contacts the target to determine which disks are available. If all is configured correctly, the target name iqn.2006-01.com.example:disk2.vol1 (from the example above) will be returned.<br />
<br />
After the target is discovered, run this command to connect:<br />
<br />
iscsiadm --mode node --targetname NAME_OF_TARGET --portal IP_OF_TARGET --login<br />
<br />
Replacing --login with --logout will end the connection. <br />
<br />
To make this connection persistent (so that it will reconnect after reboot), run this command:<br />
<br />
iscsiadm -m node -T NAME_OF_TARGET -p IP_OF_TARGET --op update -n node.conn[0].startup -v automatic<br />
<br />
''Any references/links to where to find more details about it?''--[[User:Ncopa|Ncopa]] 16:04, 8 November 2007 (UTC)</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=5138ISP Mail Server HowTo2011-05-10T14:49:44Z<p>Iilluzion: Note about 2.x HowTo is available for try</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. <br />
<br />
'''NOTE''': You may be interested to run your server at latest Alpine Linux 2.x, see [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_2.x_HowTo ISP Mail Server 2.x HowTo]<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz<br />
tar zxvf postfixadmin-2.3.2.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop3 pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
auth_username_format = %Lu<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain login<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
<br />
}<br />
<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.13<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
#user = root<br />
#}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown root:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the ''auth default'' stanza:<br />
<br />
<pre><br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
</pre><br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
'''''[Question to experts: Is this error message normal at this point? "could not save history to file "/var/lib/postgresql/.psql_history": Permission denied"]'''''<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': The psqlodbc package is currently unavailable<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Tutorials_and_Howtos&diff=5137Tutorials and Howtos2011-05-10T14:48:40Z<p>Iilluzion: /* Network Services */</p>
<hr />
<div>[[Image:package_edutainment.svg|left|link=]]<br />
{{TOC right}}'''Welcome to Tutorials and Howtos, a place of basic and advanced configuration tasks for your Alpine Linux.'''<br />
The tutorials are hands-on and the reader is expected to try and achieve the goals described in each step, possibly with the help of a good examples. The output in one step is the starting point for the following step.<br/><br />
Howtos are smaller articles explaining how to perform a particular task with Alpine Linux. We encourage people to send in both complete articles as well as requesting topics to be covered. If you think you have the skills and knowledge to write an Alpine Linux related article please do so on this Wiki. If you want to request a topic, please add your request in this page [[Talk:Tutorials_and_Howtos|Discussion]]. <br />
<br />
== Installation ==<br />
<br />
* [[Setting up a basic vserver]]<br />
* [[Setting up Logical Volumes with LVM]]<br />
* [[Replacing non-Alpine Linux with Alpine remotely]]<br />
* [[XFCE Setup]]<br />
* [[Enable Serial Console on Boot]]<br />
* [[How to enable APK caching]]<br />
* [[Install Alpine on VirtualBox]]<br />
* [[Upgrading to Edge]]<br />
* [[Setting up a software raid1 array]]<br />
* [[Running Alpine Linux As a QEMU networked Guest ]]<br />
* [[Manually editing a existing apkovl]]<br />
<br />
== Networking ==<br />
* [[Configure Networking]]<br />
* [[Howto Configure a Network Bridge]]<br />
* [[Howto Configure static routes]]<br />
* [[Using serial modem]]<br />
* [[Using HSDPA modem]]<br />
* [[Using Alpine on Windows domain with IPSEC isolation]]<br />
* [[Setting up Satellite Internet Connection]]<br />
* [[Connecting to a wireless accesspoint]]<br />
<br />
== iSCSI ==<br />
* [[iSCSI Target and Initiator Configuration]]<br />
* [[iSCSI Raid and Clustered File Systems]]<br />
* [[High performance SCST iSCSI Target on Linux software Raid]]<br />
<br />
== Network Services ==<br />
* [[Setting Up Lighttpd With FastCGI]]<br />
* [[Setting up a OpenVPN-server with Alpine]]<br />
* [[Setting up Zaptel/Asterisk on Alpine]]<br />
* [[Setting up Transmission (bittorrent) with Clutch WebUI]]<br />
* [[Hosting services on Alpine]] ''(This applies to hosting mail, webservices and other services)''<br />
** [[Setting up postfix with virtual domains]]<br />
** [[Protecting your email server with Alpine]]<br />
** [[Hosting Web/Email services on Alpine]]<br />
* [[Setting up a ssh-server]]<br />
* [[Multiple Instances of Services]]<br />
* [[ISP Mail Server HowTo]] ''(Postfix+PostfixAdmin+DoveCot+Roundcube+ClamAV+Spamd - A full-serivce ISP mail server)''<br />
** [[ISP Mail Server Upgrade 2.x]]<br />
** [[ISP Mail Server 2.x HowTo]] ''(Beta, please test)''<br />
* [[Freepbx on Alpine Linux]]<br />
* [[Apache authentication: NTLM Single Signon]]<br />
* [[Generating SSL certs with ACF]]<br />
* [[Changing passwords for ACF]]<br />
* [[Freeradius Active Directory Integration]]<br />
* [[High Availability High Performance Web Cache]] ''uCarp + HAProxy for High Availability Services such as Squid web proxy''<br />
<br />
== Web Applications ==<br />
* [[2600hz]] ''FreeSWITCH, Asterisk GUI web acces tool.''<br />
* [[Awstats]] ''Free log file analyzer.''<br />
* [[Drupal]] ''Content Management System (CMS) written in PHP.''<br />
* [[EyeOS]] ''Cloud Computing Desktop.''<br />
* [[FreePBX_V3]] ''FreeSWITCH, Asterisk GUI web acces tool.''<br />
* [[Glpi]] ''Information Resource-Manager.''<br />
* [[MediaWiki]] ''Free web-based wiki software application''<br />
* [[Phpizabi]] ''Social Networking Platform.''<br />
* [[PhpPgAdmin]] ''Web-based administration tool for PostgreSQL.''<br />
* [[Phpmyadmin]] ''Web-based administration tool for MYSQL.''<br />
* [[Redmine]] ''Project management system ''<br />
* [[Roundcube]] ''Webmail system''<br />
* [[Statusnet]] ''Microblogging Platform.''<br />
* [[Sqstat]] ''Script to look active squid users connections.''<br />
* [[Webmin]] ''A web-based interface for Linux system.''<br />
* [[WordPress]] ''Web software to create website or blog. ''<br />
<br />
== Monitoring ==<br />
* [[Traffic monitoring]] ''(For Alpine Linux firewalls)''<br />
* [[Setting up traffic monitoring using rrdtool (and snmp)]]<br />
* [[Setting up Smokeping]] ''(Smokeping network latency monitoring)''<br />
* [[Setting up Cacti]]<br />
* [[Setting up NRPE daemon]] ''(Performs remote Nagios checks)''<br />
* [[Setting up Zabbix]]<br />
* [[Setting Up Fprobe And Ntop]] ''NetFlow collection and analysis''<br />
<br />
== Misc ==<br />
* [[Setting up lm_sensors]]<br />
* [[Formatting HD/Floppy/Other]]<br />
* [[Screen on console]]<br />
* [[Using espeak on Alpine Linux]]<br />
* [[IPTV How To]]<br />
* [[Pllua]]<br />
* [[Error message on boot: Address space collision: host bridge window conflicts with Adaptor ROM]]<br />
<br />
== Drafts ==<br />
Those are not finished yet.<br />
* [[AlpineSystem:CoLinux_Setup | Installing Alpine on CoLinux ]]<br />
* [[Using Racoon for Remote Sites]]<br />
* [[High Performance and Fault Tolerant Routing with Alpine Linux]]<br />
* [[Setting up Transparent Squid Proxy]] ''(Covers Squid proxy and URL Filtering system)''<br />
** [[Obtaining user information via SNMP]] ''(Using the Squark Squid authentication helper)''<br />
* [[Setting up Streaming an Asterisk Channel]]<br />
* [[Setting up A Network Monitoring and Inventory System]] ''((Nagios + OpenAudit and related components)''<br />
* [[Intrusion Detection using Snort]] ''Installing and configuring Snort and related applications on Alpine 2.0.x''<br />
* [[IP Accounting]] ''Installing and configuring pmacct for IP Accounting, Netflow/sFlow collector''<br />
* [[Howto Setup a Wireless Access Point]] ''Setting up Secure Wireless AP w/ WPA encryption with bridge to wired network''<br />
<br />
<br />
== Obsolete Docs ==<br />
Those are candidates for rewriting/removal.<br />
* [[Bootstrapping Alpine on Soekris net4xxx]]<br />
* [[Bootstrapping Alpine on PC Engines ALIX.3]]<br />
* [[Setting up a /var partition on software IDE raid1]]<br />
* [[Native Harddisk Install]]<br />
* [[Installing XUbuntu using Alpine boot floppy]]<br />
* [[Setting up trac wiki]]</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=5136ISP Mail Server HowTo2011-05-10T14:46:32Z<p>Iilluzion: </p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. You may be interested to run your server at latest Alpine Linux 2.x, see [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_2.x_HowTo ISP Mail Server 2.x HowTo]<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pemfile line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz<br />
tar zxvf postfixadmin-2.3.2.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop3 pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
auth_username_format = %Lu<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain login<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
<br />
}<br />
<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.13<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
#user = root<br />
#}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown root:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the ''auth default'' stanza:<br />
<br />
<pre><br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
</pre><br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
'''''[Question to experts: Is this error message normal at this point? "could not save history to file "/var/lib/postgresql/.psql_history": Permission denied"]'''''<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': The psqlodbc package is currently unavailable<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5135ISP Mail Server 2.x HowTo2011-05-10T14:44:20Z<p>Iilluzion: beta</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server. We recommend to run server at Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues. (See also previous installation on 1.10 platform: [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server 1.10 HowTo])<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz<br />
tar zxvf postfixadmin-2.3.2.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki2.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
mail_location = maildir:/var/lib/mail/domains/%d/%n<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/comodo.ca.pem<br />
ssl_cert = </etc/ssl/private/srvmail.org.pem<br />
ssl_key = </etc/ssl/private/srvmail.org.pem<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
Side note: [http://wiki2.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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 2.2 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv php-dom php-intl<br />
<br />
* Link the roundcube application back into the docroot<br />
<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* Install ''roundcubemail-install'' package<br />
<br />
apk add roundcubemail-installer<br />
<br />
* Follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* Edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* Restart lighttpd to verify the new php libraries are used<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
* Enable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
* After its working, the INSTALL file recommends removing the install directory.<br />
<br />
apk del roundcubemail-installer<br />
<br />
* Disable installer mode in /etc/roundcube/main.inc.php file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
* Change the ownership and permissions<br />
<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG <br />
<br />
* If needed customize logos such as '''watermark.gif''', '''roundcube_logo.gif''', '''favicon.ico'''<br />
<br />
* If you would like to disable displaying of standard logos update template files accordingly<br />
<br />
* Comment all entries like '''<div ... img src="/images/roundcube_logo.png"...''' in files:<br />
<br />
includes/header.html <br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
* Comment all entries like '''<img src="/images/watermark.gif"...''' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 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 applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /etc/roundcube/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre><br />
<br />
== Optional: Enable compression in Lighttpd ==<br />
<br />
* Uncomment ''mod_compress'' and ''mod_setenv'' and modify website section as follows<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")<br />
}</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5130ISP Mail Server 2.x HowTo2011-05-09T14:42:42Z<p>Iilluzion: </p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz<br />
tar zxvf postfixadmin-2.3.2.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
If you receive a warning such as "Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)" the update anvil service configuration:<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add the following:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
* Replace /etc/dovecot/dovecot.conf with the following:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
#auth_verbose = yes<br />
#auth_debug = yes<br />
#auth_debug_passwords = no<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
first_valid_gid = 1000<br />
first_valid_uid = 1000<br />
last_valid_gid = 65535<br />
last_valid_uid = 65535<br />
<br />
log_timestamp = "%Y-%m-%d %H:%M:%S "<br />
login_greeting = IMAP server ready<br />
<br />
mail_location = maildir:/var/lib/mail/domains/%d/%n<br />
<br />
protocols = imap<br />
<br />
#service anvil {<br />
# client_limit = XXXX<br />
#}<br />
<br />
service auth {<br />
unix_listener /var/spool/postfix/auth-master {<br />
group = postfix<br />
mode = 0660<br />
user = vmail<br />
}<br />
unix_listener /var/spool/postfix/private/auth {<br />
group = postfix<br />
mode = 0660<br />
user = postfix<br />
}<br />
user = root<br />
}<br />
<br />
service imap-login {<br />
inet_listener imap {<br />
address = 127.0.0.1<br />
port = 143<br />
}<br />
inet_listener imaps {<br />
address = *<br />
port = 993<br />
}<br />
process_limit = 1024<br />
}<br />
<br />
service pop3-login {<br />
process_limit = 1024<br />
}<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
}<br />
}<br />
<br />
ssl_ca = </etc/ssl/certs/comodo.ca.pem<br />
ssl_cert = </etc/ssl/private/srvmail.org.pem<br />
ssl_key = </etc/ssl/private/srvmail.org.pem<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
userdb {<br />
driver = prefetch<br />
}<br />
<br />
userdb {<br />
args = /etc/dovecot/dovecot-pgsql.conf<br />
driver = sql<br />
}<br />
<br />
plugin {<br />
quota = dict:user::proxy::quotadict<br />
<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate quota imap_quota<br />
}<br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict {<br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf<br />
}<br />
<br />
protocol lda {<br />
auth_socket_path = /var/spool/postfix/auth-master<br />
mail_plugins = quota<br />
postmaster_address = postmaster@host.example.com<br />
sendmail_path = /usr/sbin/sendmail<br />
}<br />
</pre><br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown dovecot:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have followed section ''Relay_for_Authenticated_Users''.<br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
'''''[Question to experts: Is this error message normal at this point? "could not save history to file "/var/lib/postgresql/.psql_history": Permission denied"]'''''<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': The psqlodbc package is currently unavailable<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Upgrading_Alpine_-_v1.9.x&diff=5125Upgrading Alpine - v1.9.x2011-05-05T05:53:38Z<p>Iilluzion: /* Upgrading to Alpine Linux 2.x from earlier versions */</p>
<hr />
<div>This document covers upgrading for Alpine Linux version 1.9 and later. Thanks to many improvements in Alpine Linux 1.9 and later, it is possible to easily upgrade in most scenarios.<br />
<br />
All examples/instructions/actions mentioned in this document should be executed on the box that you are planning to upgrade (unless you are instructed otherwise).<br />
<br />
== Upgrading an Alpine Linux Hard-disk installation ==<br />
<br />
When Alpine Linux is installed to hard drive, upgrading the installation is simple.<br />
<br />
{{Using_Internet_Repositories_for_apk-tools}}<br />
<br />
Ensure you have the latest available version of the Alpine Linux Package Manager first before upgrading anything else:<br />
{{Cmd|apk add -u apk-tools}}<br />
<br />
=== Upgrading to Alpine Linux 2.2 and later from 2.1 ===<br />
Since '''apk''' tool has been significantly changed first make sure you have upgraded ''apk-tools'' package to latest version available in 2.1 repositories:<br />
<br />
{{Cmd|apk update --update-cache<br />
apk add --upgrade apk-tools}}<br />
<br />
Change repositories:<br />
{{Cmd|vi /etc/apk/repositories}}<br />
<br />
http://nl.alpinelinux.org/alpine/v2.2/main<br />
# or any other mirror <br />
<br />
Proceed with update and upgrade:<br />
{{Cmd|apk update --update-cache<br />
apk upgrade --available --update-cache}}<br />
<br />
Reboot the system to load new kernel<br />
{{Cmd|sync<br />
reboot}}<br />
<br />
=== Upgrading to Alpine Linux 2.2 and later from 2.0 or 1.10.x ===<br />
Since '''apk''' tool has been significantly changed you need to download and install manually the latest version of ''apk-tools'' package.<br />
<br />
If current version is 1.10.x remove GNU Wget before attempting an upgrade:<br />
{{Cmd|apk del wget}}<br />
<br />
Download latest apk-tools package and install it:<br />
{{Cmd|wget http://nl.alpinelinux.org/alpine/v2.2/main/x86/apk-tools-2.1.0_rc1-r2.apk<br />
apk add apk-tools-2.1.0_rc1-r2.apk --update-cache}}<br />
<br />
Change repositories:<br />
{{Cmd|vi /etc/apk/repositories}}<br />
<br />
http://nl.alpinelinux.org/alpine/v2.2/main<br />
# or any other mirror <br />
<br />
Proceed with update and upgrade:<br />
{{Cmd|apk update --update-cache<br />
apk upgrade --available --update-cache}}<br />
<br />
Reboot the system to load new kernel<br />
{{Cmd|sync<br />
reboot}}<br />
<br />
=== Upgrading to Alpine Linux 2.0 or 2.1 from earlier versions ===<br />
For upgrading to Alpine Linux 2.0 or 2.1 from earlier versions, the following steps apply.<br />
<br />
Remove GNU Wget before attempting an upgrade:<br />
{{Cmd|apk del wget}}<br />
<br />
Upgrade all remaining packages, including the kernel. The --available switch is used to force all packages to be upgraded, even if they have the same version number, due to changes in uClibc:<br />
{{Cmd|apk upgrade --update-cache --available<br />
sync}}<br />
<br />
=== All Other Upgrades ===<br />
Upgrade all remaining packages, including the kernel if applicable:<br />
{{Cmd|apk upgrade<br />
sync}}<br />
<br />
{{Note|You will need to restart any services that have been upgraded to begin using the upgraded versions. If the kernel is upgraded, you will need to reboot to begin using the upgraded version.}}<br />
<br />
== Upgrading Separate Boot Media ==<br />
<br />
You may have an installation where the boot media being used (such as a CD, for example) is separate from the media used to store the configuration information. In this case, simply download the latest ISO, and replace the boot media contents with the contents of the latest ISO. If you are booting from a CD, this would simply mean replacing the CD with a CD made from the new image and rebooting the Alpine Linux box. <br />
<br />
If you are using [[How_to_enable_APK_caching|APK caching]] you should also upgrade to the latest packages and update the cache by following the '''Alpine Linux Hard-disk Installation''' upgrade procedures described above.<br />
<br />
== Upgrading Alpine Linux on CF/USB ==<br />
<br />
Your installation may consist of Alpine Linux running on Compact Flash or USB media. In most cases, it should be sufficient to upgrade most packages using the '''Alpine Linux Hard-disk Installation''' upgrade procedures described above. However, for new packages to survive after a reboot, you should enable [[How_to_enable_APK_caching|APK caching]].<br />
<br />
{{Warning|As the newer version of alpine may include kernel upgrades, simply pointing the Alpine Linux Package Manager to an Internet-based repository and running ''apk upgrade'' will not be enough, as kernel components are not upgraded when Alpine Linux is run from memory.}}<br />
<br />
{{Upgrading_Alpine_environmentvars}}<br />
<br />
=== Upgrade Step-by-Step ===<br />
<br />
Start by checking that you have enough space on your media.<BR><br />
You need at least 400MB available space.<br />
{{Cmd|df -h | grep "Filesystem\|$LBU_MEDIA"}}<br />
<br />
==== Download and verify new release ====<br />
<br />
Start downloading a new '.iso' and a '.sha1' file <br />
{{Cmd|cd /media/$LBU_MEDIA<br />
wget -c {{#latestalp:alpine|url}}<br />
wget {{#latestalp:alpine|url}}.sha1}}<br />
<br />
Check integrity of the downloaded files ''(it might take some time)''<br />
{{Cmd|sha1sum -c {{#latestalp:alpine|file}}.sha1}}<br />
''The output of the above command should say 'OK'.<BR>''<br />
''If says 'FAILED', delete the iso file and download it again.''<br />
<br />
==== Copy the new release ====<br />
{{Note|There is a tool, ''setup-bootable'', in alpine-1.10.4 and newer, that does the mounting and copying for you. With this tool simply do: {{Cmd|setup-bootable -u {{#latestalp:alpine|file}} /media/$LBU_MEDIA}}<br />
}}<br />
<br />
Mount the ISO.<br />
<br />
{{Cmd|mount -t iso9660 {{#latestalp:alpine|file}} /mnt}}<br />
<br />
Back up files that you have modified. For example, you might have modified ''syslinux.cfg'' to show console output on a serial port.<BR><br />
<br />
{{Cmd|cp /media/$LBU_MEDIA/syslinux.cfg /media/$LBU_MEDIA/syslinux.cfg.my}}<br />
<br />
Install the '''rsync''' package if necessary, and copy the files:<br />
<br />
{{Cmd|cd /mnt<br />
apk add rsync<br />
rsync --delete -rltv .alpine-release * /media/$LBU_MEDIA/}}<br />
<br />
Restore your backed up files ''(in case you had any)''<br />
<br />
{{Cmd|mv -f /media/$LBU_MEDIA/syslinux.cfg.my /media/$LBU_MEDIA/syslinux.cfg}}<br />
<br />
Make sure that all files are permanently saved in right place <br />
<br />
{{Cmd|sync}}<br />
<br />
==== Clean up ====<br />
Clean up the downloaded/unpacked files<br />
{{Cmd|cd ..<br />
umount /mnt<br />
rm /media/$LBU_MEDIA/{{#latestalp:alpine|file}}<br />
rm /media/$LBU_MEDIA/{{#latestalp:alpine|file}}.sha1}}<br />
<br />
=== Save changes ===<br />
Now that all upgrades are done, we should save our settings to our media (which you hopefully have backed up prior to doing this upgrade).<br />
{{Cmd|lbu ci}}<br />
<br />
=== Load new kernel ===<br />
In most cases you will need to reboot Alpine Linux (especially if there are changes in the kernel):<br />
{{Cmd|reboot}}<br />
{{Note|If you know what you are doing, you might not need to reboot. But make sure that all services affected by the upgrade are restarted.}}<br />
<br />
=== Update remaining packages from Web repository ===<br />
If you are using [[How_to_enable_APK_caching|APK caching]] you should also upgrade to the latest packages and update the cache by following the '''Alpine Linux Hard-disk Installation''' upgrade procedures described above.</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Upgrading_Alpine_-_v1.9.x&diff=5124Upgrading Alpine - v1.9.x2011-05-05T05:50:51Z<p>Iilluzion: /* Upgrading to Alpine Linux 2.2 and later from 2.1 and 1.10.x versions */</p>
<hr />
<div>This document covers upgrading for Alpine Linux version 1.9 and later. Thanks to many improvements in Alpine Linux 1.9 and later, it is possible to easily upgrade in most scenarios.<br />
<br />
All examples/instructions/actions mentioned in this document should be executed on the box that you are planning to upgrade (unless you are instructed otherwise).<br />
<br />
== Upgrading an Alpine Linux Hard-disk installation ==<br />
<br />
When Alpine Linux is installed to hard drive, upgrading the installation is simple.<br />
<br />
{{Using_Internet_Repositories_for_apk-tools}}<br />
<br />
Ensure you have the latest available version of the Alpine Linux Package Manager first before upgrading anything else:<br />
{{Cmd|apk add -u apk-tools}}<br />
<br />
=== Upgrading to Alpine Linux 2.2 and later from 2.1 ===<br />
Since '''apk''' tool has been significantly changed first make sure you have upgraded ''apk-tools'' package to latest version available in 2.1 repositories:<br />
<br />
{{Cmd|apk update --update-cache<br />
apk add --upgrade apk-tools}}<br />
<br />
Change repositories:<br />
{{Cmd|vi /etc/apk/repositories}}<br />
<br />
http://nl.alpinelinux.org/alpine/v2.2/main<br />
# or any other mirror <br />
<br />
Proceed with update and upgrade:<br />
{{Cmd|apk update --update-cache<br />
apk upgrade --available --update-cache}}<br />
<br />
Reboot the system to load new kernel<br />
{{Cmd|sync<br />
reboot}}<br />
<br />
=== Upgrading to Alpine Linux 2.2 and later from 2.0 or 1.10.x ===<br />
Since '''apk''' tool has been significantly changed you need to download and install manually the latest version of ''apk-tools'' package.<br />
<br />
If current version is 1.10.x remove GNU Wget before attempting an upgrade:<br />
{{Cmd|apk del wget}}<br />
<br />
Download latest apk-tools package and install it:<br />
{{Cmd|wget http://nl.alpinelinux.org/alpine/v2.2/main/x86/apk-tools-2.1.0_rc1-r2.apk<br />
apk add apk-tools-2.1.0_rc1-r2.apk --update-cache}}<br />
<br />
Change repositories:<br />
{{Cmd|vi /etc/apk/repositories}}<br />
<br />
http://nl.alpinelinux.org/alpine/v2.2/main<br />
# or any other mirror <br />
<br />
Proceed with update and upgrade:<br />
{{Cmd|apk update --update-cache<br />
apk upgrade --available --update-cache}}<br />
<br />
Reboot the system to load new kernel<br />
{{Cmd|sync<br />
reboot}}<br />
<br />
=== Upgrading to Alpine Linux 2.x from earlier versions ===<br />
For upgrading to Alpine Linux 2.x from earlier versions, the following steps apply.<br />
<br />
Remove GNU Wget before attempting an upgrade:<br />
{{Cmd|apk del wget}}<br />
<br />
Upgrade all remaining packages, including the kernel. The --available switch is used to force all packages to be upgraded, even if they have the same version number, due to changes in uClibc:<br />
{{Cmd|apk upgrade --update-cache --available<br />
sync}}<br />
<br />
=== All Other Upgrades ===<br />
Upgrade all remaining packages, including the kernel if applicable:<br />
{{Cmd|apk upgrade<br />
sync}}<br />
<br />
{{Note|You will need to restart any services that have been upgraded to begin using the upgraded versions. If the kernel is upgraded, you will need to reboot to begin using the upgraded version.}}<br />
<br />
== Upgrading Separate Boot Media ==<br />
<br />
You may have an installation where the boot media being used (such as a CD, for example) is separate from the media used to store the configuration information. In this case, simply download the latest ISO, and replace the boot media contents with the contents of the latest ISO. If you are booting from a CD, this would simply mean replacing the CD with a CD made from the new image and rebooting the Alpine Linux box. <br />
<br />
If you are using [[How_to_enable_APK_caching|APK caching]] you should also upgrade to the latest packages and update the cache by following the '''Alpine Linux Hard-disk Installation''' upgrade procedures described above.<br />
<br />
== Upgrading Alpine Linux on CF/USB ==<br />
<br />
Your installation may consist of Alpine Linux running on Compact Flash or USB media. In most cases, it should be sufficient to upgrade most packages using the '''Alpine Linux Hard-disk Installation''' upgrade procedures described above. However, for new packages to survive after a reboot, you should enable [[How_to_enable_APK_caching|APK caching]].<br />
<br />
{{Warning|As the newer version of alpine may include kernel upgrades, simply pointing the Alpine Linux Package Manager to an Internet-based repository and running ''apk upgrade'' will not be enough, as kernel components are not upgraded when Alpine Linux is run from memory.}}<br />
<br />
{{Upgrading_Alpine_environmentvars}}<br />
<br />
=== Upgrade Step-by-Step ===<br />
<br />
Start by checking that you have enough space on your media.<BR><br />
You need at least 400MB available space.<br />
{{Cmd|df -h | grep "Filesystem\|$LBU_MEDIA"}}<br />
<br />
==== Download and verify new release ====<br />
<br />
Start downloading a new '.iso' and a '.sha1' file <br />
{{Cmd|cd /media/$LBU_MEDIA<br />
wget -c {{#latestalp:alpine|url}}<br />
wget {{#latestalp:alpine|url}}.sha1}}<br />
<br />
Check integrity of the downloaded files ''(it might take some time)''<br />
{{Cmd|sha1sum -c {{#latestalp:alpine|file}}.sha1}}<br />
''The output of the above command should say 'OK'.<BR>''<br />
''If says 'FAILED', delete the iso file and download it again.''<br />
<br />
==== Copy the new release ====<br />
{{Note|There is a tool, ''setup-bootable'', in alpine-1.10.4 and newer, that does the mounting and copying for you. With this tool simply do: {{Cmd|setup-bootable -u {{#latestalp:alpine|file}} /media/$LBU_MEDIA}}<br />
}}<br />
<br />
Mount the ISO.<br />
<br />
{{Cmd|mount -t iso9660 {{#latestalp:alpine|file}} /mnt}}<br />
<br />
Back up files that you have modified. For example, you might have modified ''syslinux.cfg'' to show console output on a serial port.<BR><br />
<br />
{{Cmd|cp /media/$LBU_MEDIA/syslinux.cfg /media/$LBU_MEDIA/syslinux.cfg.my}}<br />
<br />
Install the '''rsync''' package if necessary, and copy the files:<br />
<br />
{{Cmd|cd /mnt<br />
apk add rsync<br />
rsync --delete -rltv .alpine-release * /media/$LBU_MEDIA/}}<br />
<br />
Restore your backed up files ''(in case you had any)''<br />
<br />
{{Cmd|mv -f /media/$LBU_MEDIA/syslinux.cfg.my /media/$LBU_MEDIA/syslinux.cfg}}<br />
<br />
Make sure that all files are permanently saved in right place <br />
<br />
{{Cmd|sync}}<br />
<br />
==== Clean up ====<br />
Clean up the downloaded/unpacked files<br />
{{Cmd|cd ..<br />
umount /mnt<br />
rm /media/$LBU_MEDIA/{{#latestalp:alpine|file}}<br />
rm /media/$LBU_MEDIA/{{#latestalp:alpine|file}}.sha1}}<br />
<br />
=== Save changes ===<br />
Now that all upgrades are done, we should save our settings to our media (which you hopefully have backed up prior to doing this upgrade).<br />
{{Cmd|lbu ci}}<br />
<br />
=== Load new kernel ===<br />
In most cases you will need to reboot Alpine Linux (especially if there are changes in the kernel):<br />
{{Cmd|reboot}}<br />
{{Note|If you know what you are doing, you might not need to reboot. But make sure that all services affected by the upgrade are restarted.}}<br />
<br />
=== Update remaining packages from Web repository ===<br />
If you are using [[How_to_enable_APK_caching|APK caching]] you should also upgrade to the latest packages and update the cache by following the '''Alpine Linux Hard-disk Installation''' upgrade procedures described above.</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Upgrading_Alpine_-_v1.9.x&diff=5123Upgrading Alpine - v1.9.x2011-05-05T05:27:27Z<p>Iilluzion: Notes how to upgrade to 2.2 and later</p>
<hr />
<div>This document covers upgrading for Alpine Linux version 1.9 and later. Thanks to many improvements in Alpine Linux 1.9 and later, it is possible to easily upgrade in most scenarios.<br />
<br />
All examples/instructions/actions mentioned in this document should be executed on the box that you are planning to upgrade (unless you are instructed otherwise).<br />
<br />
== Upgrading an Alpine Linux Hard-disk installation ==<br />
<br />
When Alpine Linux is installed to hard drive, upgrading the installation is simple.<br />
<br />
{{Using_Internet_Repositories_for_apk-tools}}<br />
<br />
Ensure you have the latest available version of the Alpine Linux Package Manager first before upgrading anything else:<br />
{{Cmd|apk add -u apk-tools}}<br />
<br />
=== Upgrading to Alpine Linux 2.2 and later from 2.1 and earlier versions ===<br />
Since '''apk''' tool has been significantly changed for upgrading to Alpine Linux 2.2 and later from earlier versions, the following steps apply.<br />
<br />
Remove GNU Wget before attempting an upgrade:<br />
{{Cmd|apk del wget}}<br />
<br />
Download latest apk-tools package and install it:<br />
{{Cmd|wget http://nl.alpinelinux.org/alpine/v2.2/main/x86/apk-tools-2.1.0_rc1-r2.apk<br />
apk add apk-tools-2.1.0_rc1-r2.apk}}<br />
<br />
Change repositories:<br />
{{Cmd|vi /etc/apk/repositories}}<br />
<br />
http://nl.alpinelinux.org/alpine/v2.2/main<br />
<br />
Proceed with update and upgrade:<br />
{{Cmd|apk update<br />
apk upgrade --available}}<br />
<br />
Reboot the system to load new kernel<br />
{{Cmd|sync<br />
reboot}}<br />
<br />
=== Upgrading to Alpine Linux 2.x from earlier versions ===<br />
For upgrading to Alpine Linux 2.x from earlier versions, the following steps apply.<br />
<br />
Remove GNU Wget before attempting an upgrade:<br />
{{Cmd|apk del wget}}<br />
<br />
Upgrade all remaining packages, including the kernel. The --available switch is used to force all packages to be upgraded, even if they have the same version number, due to changes in uClibc:<br />
{{Cmd|apk upgrade --update-cache --available<br />
sync}}<br />
<br />
=== All Other Upgrades ===<br />
Upgrade all remaining packages, including the kernel if applicable:<br />
{{Cmd|apk upgrade<br />
sync}}<br />
<br />
{{Note|You will need to restart any services that have been upgraded to begin using the upgraded versions. If the kernel is upgraded, you will need to reboot to begin using the upgraded version.}}<br />
<br />
== Upgrading Separate Boot Media ==<br />
<br />
You may have an installation where the boot media being used (such as a CD, for example) is separate from the media used to store the configuration information. In this case, simply download the latest ISO, and replace the boot media contents with the contents of the latest ISO. If you are booting from a CD, this would simply mean replacing the CD with a CD made from the new image and rebooting the Alpine Linux box. <br />
<br />
If you are using [[How_to_enable_APK_caching|APK caching]] you should also upgrade to the latest packages and update the cache by following the '''Alpine Linux Hard-disk Installation''' upgrade procedures described above.<br />
<br />
== Upgrading Alpine Linux on CF/USB ==<br />
<br />
Your installation may consist of Alpine Linux running on Compact Flash or USB media. In most cases, it should be sufficient to upgrade most packages using the '''Alpine Linux Hard-disk Installation''' upgrade procedures described above. However, for new packages to survive after a reboot, you should enable [[How_to_enable_APK_caching|APK caching]].<br />
<br />
{{Warning|As the newer version of alpine may include kernel upgrades, simply pointing the Alpine Linux Package Manager to an Internet-based repository and running ''apk upgrade'' will not be enough, as kernel components are not upgraded when Alpine Linux is run from memory.}}<br />
<br />
{{Upgrading_Alpine_environmentvars}}<br />
<br />
=== Upgrade Step-by-Step ===<br />
<br />
Start by checking that you have enough space on your media.<BR><br />
You need at least 400MB available space.<br />
{{Cmd|df -h | grep "Filesystem\|$LBU_MEDIA"}}<br />
<br />
==== Download and verify new release ====<br />
<br />
Start downloading a new '.iso' and a '.sha1' file <br />
{{Cmd|cd /media/$LBU_MEDIA<br />
wget -c {{#latestalp:alpine|url}}<br />
wget {{#latestalp:alpine|url}}.sha1}}<br />
<br />
Check integrity of the downloaded files ''(it might take some time)''<br />
{{Cmd|sha1sum -c {{#latestalp:alpine|file}}.sha1}}<br />
''The output of the above command should say 'OK'.<BR>''<br />
''If says 'FAILED', delete the iso file and download it again.''<br />
<br />
==== Copy the new release ====<br />
{{Note|There is a tool, ''setup-bootable'', in alpine-1.10.4 and newer, that does the mounting and copying for you. With this tool simply do: {{Cmd|setup-bootable -u {{#latestalp:alpine|file}} /media/$LBU_MEDIA}}<br />
}}<br />
<br />
Mount the ISO.<br />
<br />
{{Cmd|mount -t iso9660 {{#latestalp:alpine|file}} /mnt}}<br />
<br />
Back up files that you have modified. For example, you might have modified ''syslinux.cfg'' to show console output on a serial port.<BR><br />
<br />
{{Cmd|cp /media/$LBU_MEDIA/syslinux.cfg /media/$LBU_MEDIA/syslinux.cfg.my}}<br />
<br />
Install the '''rsync''' package if necessary, and copy the files:<br />
<br />
{{Cmd|cd /mnt<br />
apk add rsync<br />
rsync --delete -rltv .alpine-release * /media/$LBU_MEDIA/}}<br />
<br />
Restore your backed up files ''(in case you had any)''<br />
<br />
{{Cmd|mv -f /media/$LBU_MEDIA/syslinux.cfg.my /media/$LBU_MEDIA/syslinux.cfg}}<br />
<br />
Make sure that all files are permanently saved in right place <br />
<br />
{{Cmd|sync}}<br />
<br />
==== Clean up ====<br />
Clean up the downloaded/unpacked files<br />
{{Cmd|cd ..<br />
umount /mnt<br />
rm /media/$LBU_MEDIA/{{#latestalp:alpine|file}}<br />
rm /media/$LBU_MEDIA/{{#latestalp:alpine|file}}.sha1}}<br />
<br />
=== Save changes ===<br />
Now that all upgrades are done, we should save our settings to our media (which you hopefully have backed up prior to doing this upgrade).<br />
{{Cmd|lbu ci}}<br />
<br />
=== Load new kernel ===<br />
In most cases you will need to reboot Alpine Linux (especially if there are changes in the kernel):<br />
{{Cmd|reboot}}<br />
{{Note|If you know what you are doing, you might not need to reboot. But make sure that all services affected by the upgrade are restarted.}}<br />
<br />
=== Update remaining packages from Web repository ===<br />
If you are using [[How_to_enable_APK_caching|APK caching]] you should also upgrade to the latest packages and update the cache by following the '''Alpine Linux Hard-disk Installation''' upgrade procedures described above.</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_2.x_HowTo&diff=5120ISP Mail Server 2.x HowTo2011-05-04T12:52:19Z<p>Iilluzion: Created page with "Category:mail == A Full Service Mail Server == This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe ho..."</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server ==<br />
<br />
This document describes installation process for latest Alpine Linux 2.x platform. The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* standard filters (virus/spam/rbl/etc)<br />
* web mail client<br />
* value add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
/etc/init.d/mini_httpd stop<br />
apk del mini_httpd<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/www/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^'):<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 '''setup-acf''' command. 3. Get certificate from trusted root certification centers. <br />
<br />
'''Option 1:'''<br />
If you create your own self-signed certificate, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certificate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
'''Option 2:'''<br />
If you prefer to just use the default certificate created with the '''setup-acf''' command, then you will need to do the following:<br />
<br />
setup-acf<br />
<br />
During the above process, mini_httpd will be started, if it isn'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.<br />
<br />
mv /etc/ssl/mini_httpd/server.pem /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
'''Option 3:'''<br />
You may decide to receive a certificate from trusted root certification centers. One good choice is to request free certificate from StartSSL at page: https://www.startssl.com/?app=33.<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
}<br />
</pre><br />
<br />
If you went with Option 1 above, then add an additional line underneath the ssl.pem file line, so that the section appears as follows:<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
<br />
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:<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
include "mod_fastcgi.conf"<br />
<br />
Stop and remove mini_httpd; start lighttpd, test:<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
At this point you should be able to see ACF being served with lighttpd (Note: this will work well with alpine 1.10 and 2.x. With earlier versions there will be problems.) https://host.example.com/acf/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql:<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/9.0/data/pg_hba.conf. Since by default "trust" mechanism is for local connections only we assume using trust password-less access as safe.<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.2/postfixadmin-2.3.2.tar.gz<br />
tar zxvf postfixadmin-2.3.2.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3.2/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to https://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix):<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner:<br />
<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
Install postfix:<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database:<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
At this point you should be able to start up postfix:<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
Edit /etc/dovecot/dovecot.conf:<br />
<br />
<pre><br />
auth_mechanisms = plain login<br />
auth_username_format = %Lu<br />
auth_verbose = yes<br />
<br />
disable_plaintext_auth = no<br />
<br />
info_log_path = /var/log/dovecot-info.log<br />
log_path = /var/log/dovecot.log<br />
<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
<br />
ssl_cert = </etc/lighttpd/server-bundle.pem<br />
ssl_key = </etc/lighttpd/server-bundle.pem<br />
<br />
userdb {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
driver = static<br />
}<br />
<br />
passdb {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
driver = sql<br />
}<br />
<br />
protocol imap {<br />
mail_plugins = autocreate<br />
}<br />
<br />
plugin {<br />
autocreate = Trash<br />
autocreate2 = Spam<br />
autocreate3 = Sent<br />
autosubscribe = Trash<br />
autosubscribe2 = Spam<br />
autosubscribe3 = Sent<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
broken_sasl_auth_clients = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.13<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
#user = root<br />
#}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown root:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
Change permissions on the /var/log/dovecot* log files, so that the vmail user can write to them:<br />
<br />
chown vmail:vmail /var/log/dovecot*<br />
<br />
Restart Postfix and Dovecot:<br />
<br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* 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 '''smtpd_tls_auth_only = no''', otherwise leave it set to '''yes''':<br />
<br />
<pre><br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
# Set the next line to no if TLS auth is not configured <br />
smtpd_tls_auth_only = no<br />
</pre><br />
<br />
* Ensure you have this section in /etc/dovecot/dovecot.conf, inside the ''auth default'' stanza:<br />
<br />
<pre><br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
</pre><br />
<br />
* Restart the relevant services:<br />
<br />
<pre><br />
/etc/init.d/postfix restart<br />
/etc/init.d/dovecot restart<br />
</pre><br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
'''''[Question to experts: Is this error message normal at this point? "could not save history to file "/var/lib/postgresql/.psql_history": Permission denied"]'''''<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to https://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 2 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at https://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
* Enable ''create_default_folders'' for RoundCube<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['create_default_folders'] = TRUE;<br />
...<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': The psqlodbc package is currently unavailable<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
((SELECT (domain.id + 100000) AS id,<br />
('dc='::text || replace((domain.domain)::text, '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
100000 AS parent,<br />
0 AS keyval,<br />
domain.domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL')<br />
UNION<br />
(SELECT 100000 AS id,<br />
('dc=' || regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS dn,<br />
1 AS oc_map_id,<br />
0 AS parent,<br />
0 AS keyval,<br />
(regexp_replace((domain.domain)::text, '.*\\.', ''::text)) AS domain<br />
FROM domain<br />
WHERE domain.domain <> 'ALL'<br />
LIMIT 1));<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id,<br />
((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) ||<br />
replace(regexp_replace((mailbox.username)::text, '.*@', ''::text), '.'::text, ',dc='::text)) AS dn,<br />
1 AS oc_map_id,<br />
(SELECT ldap_dcs.id<br />
FROM ldap_dcs<br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent,<br />
mailbox.id AS keyval<br />
FROM mailbox<br />
UNION<br />
SELECT ldap_dcs.id,<br />
ldap_dcs.dn,<br />
ldap_dcs.oc_map_id,<br />
ldap_dcs.parent,<br />
ldap_dcs.keyval<br />
FROM ldap_dcs;<br />
</pre><br />
'''''Question to experts: Is this normal to have in this script "WARNING: nonstandard use of \\ in a string literal"?'''''<br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view looks something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
# Uncomment next five TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLSCipherSuite HIGH<br />
#TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
#TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
#TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
#TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* 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="-h 'ldaps:// ldap://'"<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldap://'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities. In case you uncommented TLS lines in slapd.conf replace ldap with ldaps<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldap://host.example.com<br />
<br />
# Uncomment next three TLS... lines if you want to use LDAPs (secured). Probably you don't want it...<br />
#TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
#TLS_CERT /etc/lighttpd/server-bundle.pem<br />
#TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
* Fix PostfixAdmin to work with the new table definition<br />
<br />
Edit /var/www/domains/example.com/www/postfixadmin/list-domain.php. Replace the line:<br />
<pre><br />
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
With the lines:<br />
<pre><br />
SELECT domain.domain, domain.description, domain.aliases, domain.mailboxes,<br />
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,<br />
domain.modified, domain.active, COUNT( DISTINCT mailbox.username ) AS mailbox_count<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_Upgrade_2.x&diff=5115ISP Mail Server Upgrade 2.x2011-05-03T10:33:04Z<p>Iilluzion: /* Import data to PostgeSQL */</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server Upgrade to 2.x ==<br />
<br />
It's assumed that currently your server is running under Alpine Linux 1.10.x. The goal of this document is to describe how to upgrade [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server] to run under Alpine Linux 2.x. An upgrade process involves several significant changes in application configuration and database data and schema handling. Applications that come with Alpine Linux 2.x have a lot of bug and security fixes as well as new functionality. Upgrading of some components will require changing configurations files, update database schema and export/import data.<br />
<br />
'''NOTE:''' The ISP Mail Server can be run in RAM having directories for data such as Postfix mailboxes, PostgreSQL databases to be mounted on hard drive RAID/LVM partitions.<br />
<br />
== System preparations before upgrade ==<br />
<br />
'''IMPORTANT NOTE''': Please perform full system backup including system configuration and user data. Make sure sure that backup is valid.<br />
<br />
We recommend you to stop all user services permanently until system fully upgraded and tested. While system tests are being perform block user access for all users. <br />
<br />
'''NOTE:''' One of the ways to block user access is to use firewall rules.<br />
<br />
Remove services from auto-start:<br />
<br />
rc-update del lighttpd<br />
rc-update del dovecot<br />
rc-update del postfix<br />
rc-update del freshclam<br />
rc-update del clamd<br />
rc-update del clamsmtpd<br />
rc-update del slapd<br />
rc-update del postgresql<br />
rc-update del cron<br />
<br />
Stop services except ''postfesql'':<br />
<br />
/etc/init.d/lighttpd stop<br />
/etc/init.d/slapd stop<br />
/etc/init.d/dovecot stop<br />
/etc/init.d/postfix stop<br />
/etc/init.d/clamsmtpd stop<br />
/etc/init.d/freshclam stop<br />
/etc/init.d/clamd stop<br />
/etc/init.d/cron stop<br />
<br />
== Dump PostreSQL databases ==<br />
<br />
Since version 9 has significant changes in compare to version 8 you must dump all PostgreSQL databases and later restore data after PostgreSQL is upgraded.<br />
<br />
Create a directory where data will be dumped:<br />
<br />
mkdir <Path to datadump directory><br />
chown postges <Path to datadump directory><br />
<br />
Login as ''postgres'' and dump data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
pg_dumpall > postgresql.bak.8.4.2<br />
exit<br />
<br />
Stop PostgreSQL services:<br />
<br />
/etc/init.d/postgresql stop<br />
<br />
'''IMPORTANT NOTE''': Please perform backup of dumped data and PostgeSQL data directory ''/var/lib/postgresql/8.4''. Make sure sure that backup is valid.<br />
<br />
== Upgrading Alpine Linux ==<br />
<br />
'''NOTE:''' We recommend to upgrade to Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues.<br />
<br />
Follow instructions described on page: http://wiki.alpinelinux.org/wiki/Upgrading_Alpine_-_v1.9.x. <br />
<br />
'''NOTE:''' If your server is running in RAM make sure that you have ''/media/usbdisk'' in ''/etc/fstab'' and ''/etc/lbu/lbu.conf'' files.<br />
<br />
After reboot you may check changes in new configuration files and proceed with adjustments as needed:<br />
<br />
find /etc -iname "*apk-new"<br />
<br />
== Import data to PostgeSQL ==<br />
<br />
Make sure that file ''/etc/conf.d/postgresql'' contains: <br />
<br />
PGDATA="/var/lib/postgresql/9.0/data"<br />
<br />
Check if you need any special setting in ''/var/lib/postgresql/9.0/data/pg_hba.conf'' and ''/var/lib/postgresql/9.0/data/postgresql.conf''. In most cases these files could remain unchanged.<br />
<br />
Start PostgeSQL (It will setup itself since by default AUTO_SETUP=yes)<br />
<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
Import previously dumped data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
psql -f postgresql.bak.8.4.2 postgres<br />
exit<br />
<br />
== Start other services ==<br />
<br />
Other services do not require any changes of their current configurations, you may just start them: <br />
<br />
/etc/init.d/clamd start<br />
/etc/init.d/freshclam start<br />
/etc/init.d/clamsmtp start<br />
/etc/init.d/postfix start<br />
/etc/init.d/lighttpd start<br />
/etc/init.d/slapd start<br />
/etc/init.d/cron start<br />
<br />
Add these service to boot sequence: <br />
<br />
rc-update add lighttpd<br />
rc-update add freshclam<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
rc-update add postfix<br />
rc-update add slapd<br />
rc-update add cron<br />
<br />
== Update Dovecot configuration ==<br />
<br />
Since Dovecot has many configuration settings changed since 1.x version, the best way is to parse old configuration with ''doveconf'' tool:<br />
<br />
cd /etc/dovecot<br />
doveconf -n > dovecot.conf-new<br />
mv dovecot.conf dovecot.conf-old<br />
mv dovecot.conf-new dovecot.conf<br />
/etc/init.d/dovecot start<br />
<br />
If you receive a warning such as "''Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)''" the update ''anvil'' service configuration:<br />
<br />
vi /etc/dovecot/dovecot.conf<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
/etc/init.d/dovecot restart<br />
<br />
== Update Quota Configuration ==<br />
<br />
If you setup Quota support you need to make the following modifications: <br />
<br />
vi /etc/dovecot/dovecot.conf<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
} <br />
}<br />
<br />
Change permission of ''dovecot-dict-quota.conf'' file:<br />
<br />
chown dovecot /etc/docecot/dovecot-dict-quota.conf<br />
<br />
Restart Dovecot:<br />
<br />
/etc/init.d/dovecot restart<br />
<br />
== Update Roundcube Webmail configuration ==<br />
<br />
Move Roundcube configuration files to ''/etc/roundcube'':<br />
<br />
mv /usr/share/webapps/roundcube/config/main.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/db.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/mimetypes.php /etc/roundcube<br />
<br />
Enable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
Install ''roundcubemail-install'' package:<br />
<br />
apk add roundcubemail-installer<br />
<br />
Run configuration and system checks:<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=1<br />
:'''NOTE:''' You may need to install php-dom, php-intl components and restart Lighttpd.<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=3<br />
<br />
:Replace '''imap_root'' with ''imap_ns_personal'' in /etc/roundcube/main.inc.php<br />
<br />
$rcmail_config['imap_ns_personal'] = null;<br />
<br />
:Run only commands that are superscribed with the previously installed version number from ''/usr/share/webapps/roundcube/SQL/postgres.update.sql'':<br />
<br />
cp /usr/share/webapps/roundcube/SQL/postgres.update.sql /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql<br />
<br />
:Edit ''/usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql'', remove not needed commands and run script:<br />
<br />
su - postgres<br />
psql -f /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql roundcubemail<br />
exit<br />
<br />
:Change ownership of two new tables:<br />
<br />
psql -U postgres roundcubemail<br />
roundcubemail=# ALTER TABLE contactgroups OWNER TO roundcube;<br />
roundcubemail=# ALTER TABLE contactgroupmembers OWNER TO roundcube;<br />
<br />
Due to security reason disable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
Due to security reason remove ''roundcubemail-install'' package:<br />
<br />
apk del roundcubemail-installer<br />
<br />
Makes sure you have restored all customizations such ''watermark.gif'', ''roundcube_logo.gif'', ''favicon.ico'' or custom roundcube skin. If you would like to disable displaying of standard logos update template files accordingly.<br />
<br />
Comment all entries like ''<div ... img src="/images/roundcube_logo.png"...'' in files:<br />
<br />
includes/header.html<br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
Comment all entries like ''<img src="/images/watermark.gif"...'' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
Restart Lighttpd:<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Test Roundcube Webmail site including functionality of activated plug-ins.<br />
<br />
== Optionally enable compression in Lighttpd ==<br />
<br />
Uncomment '''mod_compress''' and '''mod_setenv''' and modify website section as follows:<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_Upgrade_2.x&diff=5114ISP Mail Server Upgrade 2.x2011-05-03T10:30:52Z<p>Iilluzion: </p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server Upgrade to 2.x ==<br />
<br />
It's assumed that currently your server is running under Alpine Linux 1.10.x. The goal of this document is to describe how to upgrade [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server] to run under Alpine Linux 2.x. An upgrade process involves several significant changes in application configuration and database data and schema handling. Applications that come with Alpine Linux 2.x have a lot of bug and security fixes as well as new functionality. Upgrading of some components will require changing configurations files, update database schema and export/import data.<br />
<br />
'''NOTE:''' The ISP Mail Server can be run in RAM having directories for data such as Postfix mailboxes, PostgreSQL databases to be mounted on hard drive RAID/LVM partitions.<br />
<br />
== System preparations before upgrade ==<br />
<br />
'''IMPORTANT NOTE''': Please perform full system backup including system configuration and user data. Make sure sure that backup is valid.<br />
<br />
We recommend you to stop all user services permanently until system fully upgraded and tested. While system tests are being perform block user access for all users. <br />
<br />
'''NOTE:''' One of the ways to block user access is to use firewall rules.<br />
<br />
Remove services from auto-start:<br />
<br />
rc-update del lighttpd<br />
rc-update del dovecot<br />
rc-update del postfix<br />
rc-update del freshclam<br />
rc-update del clamd<br />
rc-update del clamsmtpd<br />
rc-update del slapd<br />
rc-update del postgresql<br />
rc-update del cron<br />
<br />
Stop services except ''postfesql'':<br />
<br />
/etc/init.d/lighttpd stop<br />
/etc/init.d/slapd stop<br />
/etc/init.d/dovecot stop<br />
/etc/init.d/postfix stop<br />
/etc/init.d/clamsmtpd stop<br />
/etc/init.d/freshclam stop<br />
/etc/init.d/clamd stop<br />
/etc/init.d/cron stop<br />
<br />
== Dump PostreSQL databases ==<br />
<br />
Since version 9 has significant changes in compare to version 8 you must dump all PostgreSQL databases and later restore data after PostgreSQL is upgraded.<br />
<br />
Create a directory where data will be dumped:<br />
<br />
mkdir <Path to datadump directory><br />
chown postges <Path to datadump directory><br />
<br />
Login as ''postgres'' and dump data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
pg_dumpall > postgresql.bak.8.4.2<br />
exit<br />
<br />
Stop PostgreSQL services:<br />
<br />
/etc/init.d/postgresql stop<br />
<br />
'''IMPORTANT NOTE''': Please perform backup of dumped data and PostgeSQL data directory ''/var/lib/postgresql/8.4''. Make sure sure that backup is valid.<br />
<br />
== Upgrading Alpine Linux ==<br />
<br />
'''NOTE:''' We recommend to upgrade to Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues.<br />
<br />
Follow instructions described on page: http://wiki.alpinelinux.org/wiki/Upgrading_Alpine_-_v1.9.x. <br />
<br />
'''NOTE:''' If your server is running in RAM make sure that you have ''/media/usbdisk'' in ''/etc/fstab'' and ''/etc/lbu/lbu.conf'' files.<br />
<br />
After reboot you may check changes in new configuration files and proceed with adjustments as needed:<br />
<br />
find /etc -iname "*apk-new"<br />
<br />
== Import data to PostgeSQL ==<br />
<br />
Make sure that file ''/etc/conf.d/psotgresql'' contains: <br />
<br />
PGDATA="/var/lib/postgresql/9.0/data"<br />
<br />
Check if you need any special setting in ''/var/lib/postgresql/9.0/data/pg_hba.conf'' and ''/var/lib/postgresql/9.0/data/postgresql.conf''. In most cases these files could remain unchanged.<br />
<br />
Start PostgeSQL (It will setup itself since by default AUTO_SETUP=yes)<br />
<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
Import previously dumped data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
psql -f postgresql.bak.8.4.2 postgres<br />
exit<br />
<br />
== Start other services ==<br />
<br />
Other services do not require any changes of their current configurations, you may just start them: <br />
<br />
/etc/init.d/clamd start<br />
/etc/init.d/freshclam start<br />
/etc/init.d/clamsmtp start<br />
/etc/init.d/postfix start<br />
/etc/init.d/lighttpd start<br />
/etc/init.d/slapd start<br />
/etc/init.d/cron start<br />
<br />
Add these service to boot sequence: <br />
<br />
rc-update add lighttpd<br />
rc-update add freshclam<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
rc-update add postfix<br />
rc-update add slapd<br />
rc-update add cron<br />
<br />
== Update Dovecot configuration ==<br />
<br />
Since Dovecot has many configuration settings changed since 1.x version, the best way is to parse old configuration with ''doveconf'' tool:<br />
<br />
cd /etc/dovecot<br />
doveconf -n > dovecot.conf-new<br />
mv dovecot.conf dovecot.conf-old<br />
mv dovecot.conf-new dovecot.conf<br />
/etc/init.d/dovecot start<br />
<br />
If you receive a warning such as "''Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)''" the update ''anvil'' service configuration:<br />
<br />
vi /etc/dovecot/dovecot.conf<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
/etc/init.d/dovecot restart<br />
<br />
== Update Quota Configuration ==<br />
<br />
If you setup Quota support you need to make the following modifications: <br />
<br />
vi /etc/dovecot/dovecot.conf<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
} <br />
}<br />
<br />
Change permission of ''dovecot-dict-quota.conf'' file:<br />
<br />
chown dovecot /etc/docecot/dovecot-dict-quota.conf<br />
<br />
Restart Dovecot:<br />
<br />
/etc/init.d/dovecot restart<br />
<br />
== Update Roundcube Webmail configuration ==<br />
<br />
Move Roundcube configuration files to ''/etc/roundcube'':<br />
<br />
mv /usr/share/webapps/roundcube/config/main.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/db.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/mimetypes.php /etc/roundcube<br />
<br />
Enable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
Install ''roundcubemail-install'' package:<br />
<br />
apk add roundcubemail-installer<br />
<br />
Run configuration and system checks:<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=1<br />
:'''NOTE:''' You may need to install php-dom, php-intl components and restart Lighttpd.<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=3<br />
<br />
:Replace '''imap_root'' with ''imap_ns_personal'' in /etc/roundcube/main.inc.php<br />
<br />
$rcmail_config['imap_ns_personal'] = null;<br />
<br />
:Run only commands that are superscribed with the previously installed version number from ''/usr/share/webapps/roundcube/SQL/postgres.update.sql'':<br />
<br />
cp /usr/share/webapps/roundcube/SQL/postgres.update.sql /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql<br />
<br />
:Edit ''/usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql'', remove not needed commands and run script:<br />
<br />
su - postgres<br />
psql -f /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql roundcubemail<br />
exit<br />
<br />
:Change ownership of two new tables:<br />
<br />
psql -U postgres roundcubemail<br />
roundcubemail=# ALTER TABLE contactgroups OWNER TO roundcube;<br />
roundcubemail=# ALTER TABLE contactgroupmembers OWNER TO roundcube;<br />
<br />
Due to security reason disable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
Due to security reason remove ''roundcubemail-install'' package:<br />
<br />
apk del roundcubemail-installer<br />
<br />
Makes sure you have restored all customizations such ''watermark.gif'', ''roundcube_logo.gif'', ''favicon.ico'' or custom roundcube skin. If you would like to disable displaying of standard logos update template files accordingly.<br />
<br />
Comment all entries like ''<div ... img src="/images/roundcube_logo.png"...'' in files:<br />
<br />
includes/header.html<br />
templates/error.html<br />
templates/messageprint.html<br />
templates/login.html<br />
templates/printmessage.html<br />
<br />
Comment all entries like ''<img src="/images/watermark.gif"...'' in files:<br />
<br />
templates/identities.html<br />
templates/messageerror.html<br />
watermark.html<br />
<br />
Restart Lighttpd:<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Test Roundcube Webmail site including functionality of activated plug-ins.<br />
<br />
== Optionally enable compression in Lighttpd ==<br />
<br />
Uncomment '''mod_compress''' and '''mod_setenv''' and modify website section as follows:<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_Upgrade_2.x&diff=5113ISP Mail Server Upgrade 2.x2011-05-03T10:18:56Z<p>Iilluzion: </p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server Upgrade to 2.x ==<br />
<br />
It's assumed that currently your server is running under Alpine Linux 1.10.x. The goal of this document is to describe how to upgrade [http://wiki.alpinelinux.org/wiki/ISP_Mail_Server_HowTo ISP Mail Server] to run under Alpine Linux 2.x. An upgrade process involves several significant changes in application configuration and database data and schema handling. Applications that come with Alpine Linux 2.x have a lot of bug and security fixes as well as new functionality. Upgrading of some components will require changing configurations files, update database schema and export/import data.<br />
<br />
'''NOTE:''' The ISP Mail Server can be run in RAM having directories for data such as Postfix mailboxes, PostgreSQL databases to be mounted on hard drive RAID/LVM partitions.<br />
<br />
== System Preparations before upgrade ==<br />
<br />
'''IMPORTANT NOTE''': Please perform full system backup including system configuration and user data. Make sure sure that backup is valid.<br />
<br />
We recommend you to stop all user services permanently until system fully upgraded and tested. While system tests are being perform block user access for all users. <br />
<br />
'''NOTE:''' One of the ways to block user access is to use firewall rules.<br />
<br />
Remove services from auto-start:<br />
<br />
rc-update del lighttpd<br />
rc-update del dovecot<br />
rc-update del postfix<br />
rc-update del freshclam<br />
rc-update del clamd<br />
rc-update del clamsmtpd<br />
rc-update del slapd<br />
rc-update del postgresql<br />
rc-update del cron<br />
<br />
Stop services except ''postfesql'':<br />
<br />
/etc/init.d/lighttpd stop<br />
/etc/init.d/slapd stop<br />
/etc/init.d/dovecot stop<br />
/etc/init.d/postfix stop<br />
/etc/init.d/clamsmtpd stop<br />
/etc/init.d/freshclam stop<br />
/etc/init.d/clamd stop<br />
/etc/init.d/cron stop<br />
<br />
== Dump PostreSQL databases ==<br />
<br />
Since version 9 has significant changes in compare to version 8 you must dump all PostgreSQL databases and later restore data after PostgreSQL is upgraded.<br />
<br />
Create a directory where data will be dumped:<br />
<br />
mkdir <Path to datadump directory><br />
chown postges <Path to datadump directory><br />
<br />
Login as ''postgres'' and dump data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
pg_dumpall > postgresql.bak.8.4.2<br />
exit<br />
<br />
Stop PostgreSQL services:<br />
<br />
/etc/init.d/postgresql stop<br />
<br />
'''IMPORTANT NOTE''': Please perform backup of dumped data and PostgeSQL data directory ''/var/lib/postgresql/8.4''. Make sure sure that backup is valid.<br />
<br />
== Upgrading Alpine Linux ==<br />
<br />
'''NOTE:''' We recommend to upgrade to Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues.<br />
<br />
Follow instructions described on page: http://wiki.alpinelinux.org/wiki/Upgrading_Alpine_-_v1.9.x. <br />
<br />
'''NOTE:''' If your server is running in RAM make sure that you have ''/media/usbdisk'' in ''/etc/fstab'' and ''/etc/lbu/lbu.conf'' files.<br />
<br />
After reboot you may check changes in new configuration files and proceed with adjustments as needed:<br />
<br />
find /etc -iname "*apk-new"<br />
<br />
== Import data to PostgeSQL ==<br />
<br />
Make sure that file ''/etc/conf.d/psotgresql'' contains: <br />
<br />
PGDATA="/var/lib/postgresql/9.0/data"<br />
<br />
Check if you need any special setting in ''/var/lib/postgresql/9.0/data/pg_hba.conf'' and ''/var/lib/postgresql/9.0/data/postgresql.conf''. In most cases these files could remain unchanged.<br />
<br />
Start PostgeSQL (It will setup itself since by default AUTO_SETUP=yes)<br />
<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
Import previously dumped data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
psql -f postgresql.bak.8.4.2 postgres<br />
exit<br />
<br />
== Start other services ==<br />
<br />
Other services do not require any changes of their current configurations, you may just start them: <br />
<br />
/etc/init.d/clamd start<br />
/etc/init.d/freshclam start<br />
/etc/init.d/clamsmtp start<br />
/etc/init.d/postfix start<br />
/etc/init.d/lighttpd start<br />
/etc/init.d/slapd start<br />
/etc/init.d/cron start<br />
<br />
Add these service to boot sequence: <br />
<br />
rc-update add lighttpd<br />
rc-update add freshclam<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
rc-update add postfix<br />
rc-update add slapd<br />
rc-update add cron<br />
<br />
== Update Dovecot configuration ==<br />
<br />
Since Dovecot has many configuration settings changed since 1.x version, the best way is to parse old configuration with ''doveconf'' tool:<br />
<br />
cd /etc/dovecot<br />
doveconf -n > dovecot.conf-new<br />
mv dovecot.conf dovecot.conf-old<br />
mv dovecot.conf-new dovecot.conf<br />
/etc/init.d/dovecot start<br />
<br />
If you receive a warning such as "''Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)''" the update ''anvil'' service configuration:<br />
<br />
vi /etc/dovecot/dovecot.conf<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
/etc/init.d/dovecot restart<br />
<br />
== Update Quota Configuration ==<br />
<br />
If you setup Quota support you need to make the following modifications: <br />
<br />
vi /etc/dovecot/dovecot.conf<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = vmail<br />
} <br />
}<br />
<br />
Change permission of ''dovecot-dict-quota.conf'' file:<br />
<br />
chown dovecot /etc/docecot/dovecot-dict-quota.conf<br />
<br />
Restart Dovecot:<br />
<br />
/etc/init.d/dovecot restart<br />
<br />
== Update Roundcube Webmail configuration ==<br />
<br />
Move Roundcube configuration files to ''/etc/roundcube'':<br />
<br />
mv /usr/share/webapps/roundcube/config/main.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/db.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/mimetypes.php /etc/roundcube<br />
<br />
Enable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
Install ''roundcubemail-install'' package:<br />
<br />
apk add roundcubemail-installer<br />
<br />
Run configuration and system checks:<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=1<br />
:'''NOTE:''' You may need to install php-dom, php-intl components and restart Lighttpd.<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=3<br />
<br />
:Replace '''imap_root'' with ''imap_ns_personal'' in /etc/roundcube/main.inc.php<br />
<br />
$rcmail_config['imap_ns_personal'] = null;<br />
<br />
:Run only commands that are superscribed with the previously installed version number from ''/usr/share/webapps/roundcube/SQL/postgres.update.sql'':<br />
<br />
cp /usr/share/webapps/roundcube/SQL/postgres.update.sql /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql<br />
<br />
:Edit ''/usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql'', remove not needed commands and run script:<br />
<br />
su - postgres<br />
psql -f /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql roundcubemail<br />
exit<br />
<br />
:Change ownership of two new tables:<br />
<br />
psql -U postgres roundcubemail<br />
roundcubemail=# ALTER TABLE contactgroups OWNER TO roundcube;<br />
roundcubemail=# ALTER TABLE contactgroupmembers OWNER TO roundcube;<br />
<br />
Due to security reason disable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
Due to security reason remove ''roundcubemail-install'' package:<br />
<br />
apk del roundcubemail-installer<br />
<br />
Makes sure you have restored all customizations such ''watermark.gif'', ''roundcube_logo.gif'', ''favicon.ico'' or custom roundcube skin. If you would like to disable displaying of standard logos update template files accordingly:<br />
<br />
includes/header.html:<!--<div id="header"><a href="./"><img id="logo" src="/images/roundcube_logo.png" alt="logo" title="<roundcube:object name='productname' />" /></a></div>--><br />
templates/error.html:<!--<div id="header"><img src="/images/roundcube_logo.png" alt="<roundcube:object name='productname' />" /></div>--><br />
templates/messageprint.html:<!--<div id="header"><img src="/images/roundcube_logo.png" alt="<roundcube:object name="productname" />" /></div>--><br />
templates/login.html:<!--<img id="logo" src="/images/roundcube_logo.png" border="0" alt="<roundcube:object name='productname' />" style="margin:0 11px" /> --><br />
templates/printmessage.html:<!--<div id="header"><img src="/images/roundcube_logo.png" alt="<roundcube:object name="productname" />" /></div>--><br />
<br />
templates/identities.html: <!--<img src="/images/watermark.gif" width="260" height="228" alt="" />--><br />
templates/login.html: /images/watermark.gif<br />
templates/messageerror.html:<!--<img src="/images/watermark.gif" width="260" height="228" alt="" />--><br />
templates/messageerror.html:<!--<img src="/images/watermark.gif" width="260" height="228" alt="" />--><br />
watermark.html:<!--<img src="images/watermark.gif" width="260" height="228" alt="" />--><br />
<br />
Restart Lighttpd:<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Test Roundcube Webmail site including functionality of activated plug-ins.<br />
<br />
== Optionally enable compression in Lighttpd ==<br />
<br />
Uncomment '''mod_compress''' and '''mod_setenv''' and modify website section as follows:<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Tutorials_and_Howtos&diff=5112Tutorials and Howtos2011-05-03T10:15:41Z<p>Iilluzion: /* Installation */</p>
<hr />
<div>[[Image:package_edutainment.svg|left|link=]]<br />
{{TOC right}}'''Welcome to Tutorials and Howtos, a place of basic and advanced configuration tasks for your Alpine Linux.'''<br />
The tutorials are hands-on and the reader is expected to try and achieve the goals described in each step, possibly with the help of a good examples. The output in one step is the starting point for the following step.<br/><br />
Howtos are smaller articles explaining how to perform a particular task with Alpine Linux. We encourage people to send in both complete articles as well as requesting topics to be covered. If you think you have the skills and knowledge to write an Alpine Linux related article please do so on this Wiki. If you want to request a topic, please add your request in this page [[Talk:Tutorials_and_Howtos|Discussion]]. <br />
<br />
== Installation ==<br />
<br />
* [[Setting up a basic vserver]]<br />
* [[Setting up Logical Volumes with LVM]]<br />
* [[Replacing non-Alpine Linux with Alpine remotely]]<br />
* [[XFCE Setup]]<br />
* [[Enable Serial Console on Boot]]<br />
* [[How to enable APK caching]]<br />
* [[Install Alpine on VirtualBox]]<br />
* [[Upgrading to Edge]]<br />
* [[Setting up a software raid1 array]]<br />
* [[Running Alpine Linux As a QEMU networked Guest ]]<br />
* [[Manually editing a existing apkovl]]<br />
<br />
== Networking ==<br />
* [[Configure Networking]]<br />
* [[Howto Configure a Network Bridge]]<br />
* [[Howto Configure static routes]]<br />
* [[Using serial modem]]<br />
* [[Using HSDPA modem]]<br />
* [[Using Alpine on Windows domain with IPSEC isolation]]<br />
* [[Setting up Satellite Internet Connection]]<br />
* [[Connecting to a wireless accesspoint]]<br />
<br />
== iSCSI ==<br />
* [[iSCSI Target and Initiator Configuration]]<br />
* [[iSCSI Raid and Clustered File Systems]]<br />
* [[High performance SCST iSCSI Target on Linux software Raid]]<br />
<br />
== Network Services ==<br />
* [[Setting Up Lighttpd With FastCGI]]<br />
* [[Setting up a OpenVPN-server with Alpine]]<br />
* [[Setting up Zaptel/Asterisk on Alpine]]<br />
* [[Setting up Transmission (bittorrent) with Clutch WebUI]]<br />
* [[Hosting services on Alpine]] ''(This applies to hosting mail, webservices and other services)''<br />
** [[Setting up postfix with virtual domains]]<br />
** [[Protecting your email server with Alpine]]<br />
** [[Hosting Web/Email services on Alpine]]<br />
* [[Setting up a ssh-server]]<br />
* [[Multiple Instances of Services]]<br />
* [[ISP Mail Server HowTo]] ''(Postfix+PostfixAdmin+DoveCot+Roundcube+ClamAV+Spamd - A full-serivce ISP mail server)''<br />
** [[ISP Mail Server Upgrade 2.x]]<br />
* [[Freepbx on Alpine Linux]]<br />
* [[Apache authentication: NTLM Single Signon]]<br />
* [[Generating SSL certs with ACF]]<br />
* [[Changing passwords for ACF]]<br />
* [[Freeradius Active Directory Integration]]<br />
* [[High Availability High Performance Web Cache]] ''uCarp + HAProxy for High Availability Services such as Squid web proxy''<br />
<br />
== Web Applications ==<br />
* [[2600hz]] ''FreeSWITCH, Asterisk GUI web acces tool.''<br />
* [[Awstats]] ''Free log file analyzer.''<br />
* [[Drupal]] ''Content Management System (CMS) written in PHP.''<br />
* [[EyeOS]] ''Cloud Computing Desktop.''<br />
* [[FreePBX_V3]] ''FreeSWITCH, Asterisk GUI web acces tool.''<br />
* [[Glpi]] ''Information Resource-Manager.''<br />
* [[MediaWiki]] ''Free web-based wiki software application''<br />
* [[Phpizabi]] ''Social Networking Platform.''<br />
* [[PhpPgAdmin]] ''Web-based administration tool for PostgreSQL.''<br />
* [[Phpmyadmin]] ''Web-based administration tool for MYSQL.''<br />
* [[Redmine]] ''Project management system ''<br />
* [[Roundcube]] ''Webmail system''<br />
* [[Statusnet]] ''Microblogging Platform.''<br />
* [[Sqstat]] ''Script to look active squid users connections.''<br />
* [[Webmin]] ''A web-based interface for Linux system.''<br />
* [[WordPress]] ''Web software to create website or blog. ''<br />
<br />
== Monitoring ==<br />
* [[Traffic monitoring]] ''(For Alpine Linux firewalls)''<br />
* [[Setting up traffic monitoring using rrdtool (and snmp)]]<br />
* [[Setting up Smokeping]] ''(Smokeping network latency monitoring)''<br />
* [[Setting up Cacti]]<br />
* [[Setting up NRPE daemon]] ''(Performs remote Nagios checks)''<br />
* [[Setting up Zabbix]]<br />
* [[Setting Up Fprobe And Ntop]] ''NetFlow collection and analysis''<br />
<br />
== Misc ==<br />
* [[Setting up lm_sensors]]<br />
* [[Formatting HD/Floppy/Other]]<br />
* [[Screen on console]]<br />
* [[Using espeak on Alpine Linux]]<br />
* [[IPTV How To]]<br />
* [[Pllua]]<br />
* [[Error message on boot: Address space collision: host bridge window conflicts with Adaptor ROM]]<br />
<br />
== Drafts ==<br />
Those are not finished yet.<br />
* [[AlpineSystem:CoLinux_Setup | Installing Alpine on CoLinux ]]<br />
* [[Using Racoon for Remote Sites]]<br />
* [[High Performance and Fault Tolerant Routing with Alpine Linux]]<br />
* [[Setting up Transparent Squid Proxy]] ''(Covers Squid proxy and URL Filtering system)''<br />
** [[Obtaining user information via SNMP]] ''(Using the Squark Squid authentication helper)''<br />
* [[Setting up Streaming an Asterisk Channel]]<br />
* [[Setting up A Network Monitoring and Inventory System]] ''((Nagios + OpenAudit and related components)''<br />
* [[Intrusion Detection using Snort]] ''Installing and configuring Snort and related applications on Alpine 2.0.x''<br />
* [[IP Accounting]] ''Installing and configuring pmacct for IP Accounting, Netflow/sFlow collector''<br />
* [[Howto Setup a Wireless Access Point]] ''Setting up Secure Wireless AP w/ WPA encryption with bridge to wired network''<br />
<br />
<br />
== Obsolete Docs ==<br />
Those are candidates for rewriting/removal.<br />
* [[Bootstrapping Alpine on Soekris net4xxx]]<br />
* [[Bootstrapping Alpine on PC Engines ALIX.3]]<br />
* [[Setting up a /var partition on software IDE raid1]]<br />
* [[Native Harddisk Install]]<br />
* [[Installing XUbuntu using Alpine boot floppy]]<br />
* [[Setting up trac wiki]]</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Tutorials_and_Howtos&diff=5111Tutorials and Howtos2011-05-03T09:36:08Z<p>Iilluzion: /* Network Services */</p>
<hr />
<div>[[Image:package_edutainment.svg|left|link=]]<br />
{{TOC right}}'''Welcome to Tutorials and Howtos, a place of basic and advanced configuration tasks for your Alpine Linux.'''<br />
The tutorials are hands-on and the reader is expected to try and achieve the goals described in each step, possibly with the help of a good examples. The output in one step is the starting point for the following step.<br/><br />
Howtos are smaller articles explaining how to perform a particular task with Alpine Linux. We encourage people to send in both complete articles as well as requesting topics to be covered. If you think you have the skills and knowledge to write an Alpine Linux related article please do so on this Wiki. If you want to request a topic, please add your request in this page [[Talk:Tutorials_and_Howtos|Discussion]]. <br />
<br />
== Installation ==<br />
* [[Setting up a basic vserver]]<br />
* [[Setting up Logical Volumes with LVM]]<br />
* [[Replacing non-Alpine Linux with Alpine remotely]]<br />
* [[XFCE Setup]]<br />
* [[Enable Serial Console on Boot]]<br />
* [[How to enable APK caching]]<br />
* [[Install Alpine on VirtualBox]]<br />
* [[Upgrading to Edge]]<br />
* [[Setting up a software raid1 array]]<br />
* [[Running Alpine Linux As a QEMU networked Guest ]]<br />
* [[Manually editing a existing apkovl]]<br />
<br />
== Networking ==<br />
* [[Configure Networking]]<br />
* [[Howto Configure a Network Bridge]]<br />
* [[Howto Configure static routes]]<br />
* [[Using serial modem]]<br />
* [[Using HSDPA modem]]<br />
* [[Using Alpine on Windows domain with IPSEC isolation]]<br />
* [[Setting up Satellite Internet Connection]]<br />
* [[Connecting to a wireless accesspoint]]<br />
<br />
== iSCSI ==<br />
* [[iSCSI Target and Initiator Configuration]]<br />
* [[iSCSI Raid and Clustered File Systems]]<br />
* [[High performance SCST iSCSI Target on Linux software Raid]]<br />
<br />
== Network Services ==<br />
* [[Setting Up Lighttpd With FastCGI]]<br />
* [[Setting up a OpenVPN-server with Alpine]]<br />
* [[Setting up Zaptel/Asterisk on Alpine]]<br />
* [[Setting up Transmission (bittorrent) with Clutch WebUI]]<br />
* [[Hosting services on Alpine]] ''(This applies to hosting mail, webservices and other services)''<br />
** [[Setting up postfix with virtual domains]]<br />
** [[Protecting your email server with Alpine]]<br />
** [[Hosting Web/Email services on Alpine]]<br />
* [[Setting up a ssh-server]]<br />
* [[Multiple Instances of Services]]<br />
* [[ISP Mail Server HowTo]] ''(Postfix+PostfixAdmin+DoveCot+Roundcube+ClamAV+Spamd - A full-serivce ISP mail server)''<br />
** [[ISP Mail Server Upgrade 2.x]]<br />
* [[Freepbx on Alpine Linux]]<br />
* [[Apache authentication: NTLM Single Signon]]<br />
* [[Generating SSL certs with ACF]]<br />
* [[Changing passwords for ACF]]<br />
* [[Freeradius Active Directory Integration]]<br />
* [[High Availability High Performance Web Cache]] ''uCarp + HAProxy for High Availability Services such as Squid web proxy''<br />
<br />
== Web Applications ==<br />
* [[2600hz]] ''FreeSWITCH, Asterisk GUI web acces tool.''<br />
* [[Awstats]] ''Free log file analyzer.''<br />
* [[Drupal]] ''Content Management System (CMS) written in PHP.''<br />
* [[EyeOS]] ''Cloud Computing Desktop.''<br />
* [[FreePBX_V3]] ''FreeSWITCH, Asterisk GUI web acces tool.''<br />
* [[Glpi]] ''Information Resource-Manager.''<br />
* [[MediaWiki]] ''Free web-based wiki software application''<br />
* [[Phpizabi]] ''Social Networking Platform.''<br />
* [[PhpPgAdmin]] ''Web-based administration tool for PostgreSQL.''<br />
* [[Phpmyadmin]] ''Web-based administration tool for MYSQL.''<br />
* [[Redmine]] ''Project management system ''<br />
* [[Roundcube]] ''Webmail system''<br />
* [[Statusnet]] ''Microblogging Platform.''<br />
* [[Sqstat]] ''Script to look active squid users connections.''<br />
* [[Webmin]] ''A web-based interface for Linux system.''<br />
* [[WordPress]] ''Web software to create website or blog. ''<br />
<br />
== Monitoring ==<br />
* [[Traffic monitoring]] ''(For Alpine Linux firewalls)''<br />
* [[Setting up traffic monitoring using rrdtool (and snmp)]]<br />
* [[Setting up Smokeping]] ''(Smokeping network latency monitoring)''<br />
* [[Setting up Cacti]]<br />
* [[Setting up NRPE daemon]] ''(Performs remote Nagios checks)''<br />
* [[Setting up Zabbix]]<br />
* [[Setting Up Fprobe And Ntop]] ''NetFlow collection and analysis''<br />
<br />
== Misc ==<br />
* [[Setting up lm_sensors]]<br />
* [[Formatting HD/Floppy/Other]]<br />
* [[Screen on console]]<br />
* [[Using espeak on Alpine Linux]]<br />
* [[IPTV How To]]<br />
* [[Pllua]]<br />
* [[Error message on boot: Address space collision: host bridge window conflicts with Adaptor ROM]]<br />
<br />
== Drafts ==<br />
Those are not finished yet.<br />
* [[AlpineSystem:CoLinux_Setup | Installing Alpine on CoLinux ]]<br />
* [[Using Racoon for Remote Sites]]<br />
* [[High Performance and Fault Tolerant Routing with Alpine Linux]]<br />
* [[Setting up Transparent Squid Proxy]] ''(Covers Squid proxy and URL Filtering system)''<br />
** [[Obtaining user information via SNMP]] ''(Using the Squark Squid authentication helper)''<br />
* [[Setting up Streaming an Asterisk Channel]]<br />
* [[Setting up A Network Monitoring and Inventory System]] ''((Nagios + OpenAudit and related components)''<br />
* [[Intrusion Detection using Snort]] ''Installing and configuring Snort and related applications on Alpine 2.0.x''<br />
* [[IP Accounting]] ''Installing and configuring pmacct for IP Accounting, Netflow/sFlow collector''<br />
* [[Howto Setup a Wireless Access Point]] ''Setting up Secure Wireless AP w/ WPA encryption with bridge to wired network''<br />
<br />
<br />
== Obsolete Docs ==<br />
Those are candidates for rewriting/removal.<br />
* [[Bootstrapping Alpine on Soekris net4xxx]]<br />
* [[Bootstrapping Alpine on PC Engines ALIX.3]]<br />
* [[Setting up a /var partition on software IDE raid1]]<br />
* [[Native Harddisk Install]]<br />
* [[Installing XUbuntu using Alpine boot floppy]]<br />
* [[Setting up trac wiki]]</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Tutorials_and_Howtos&diff=5110Tutorials and Howtos2011-05-03T09:08:27Z<p>Iilluzion: /* Network Services */</p>
<hr />
<div>[[Image:package_edutainment.svg|left|link=]]<br />
{{TOC right}}'''Welcome to Tutorials and Howtos, a place of basic and advanced configuration tasks for your Alpine Linux.'''<br />
The tutorials are hands-on and the reader is expected to try and achieve the goals described in each step, possibly with the help of a good examples. The output in one step is the starting point for the following step.<br/><br />
Howtos are smaller articles explaining how to perform a particular task with Alpine Linux. We encourage people to send in both complete articles as well as requesting topics to be covered. If you think you have the skills and knowledge to write an Alpine Linux related article please do so on this Wiki. If you want to request a topic, please add your request in this page [[Talk:Tutorials_and_Howtos|Discussion]]. <br />
<br />
== Installation ==<br />
* [[Setting up a basic vserver]]<br />
* [[Setting up Logical Volumes with LVM]]<br />
* [[Replacing non-Alpine Linux with Alpine remotely]]<br />
* [[XFCE Setup]]<br />
* [[Enable Serial Console on Boot]]<br />
* [[How to enable APK caching]]<br />
* [[Install Alpine on VirtualBox]]<br />
* [[Upgrading to Edge]]<br />
* [[Setting up a software raid1 array]]<br />
* [[Running Alpine Linux As a QEMU networked Guest ]]<br />
* [[Manually editing a existing apkovl]]<br />
<br />
== Networking ==<br />
* [[Configure Networking]]<br />
* [[Howto Configure a Network Bridge]]<br />
* [[Howto Configure static routes]]<br />
* [[Using serial modem]]<br />
* [[Using HSDPA modem]]<br />
* [[Using Alpine on Windows domain with IPSEC isolation]]<br />
* [[Setting up Satellite Internet Connection]]<br />
* [[Connecting to a wireless accesspoint]]<br />
<br />
== iSCSI ==<br />
* [[iSCSI Target and Initiator Configuration]]<br />
* [[iSCSI Raid and Clustered File Systems]]<br />
* [[High performance SCST iSCSI Target on Linux software Raid]]<br />
<br />
== Network Services ==<br />
* [[Setting Up Lighttpd With FastCGI]]<br />
* [[Setting up a OpenVPN-server with Alpine]]<br />
* [[Setting up Zaptel/Asterisk on Alpine]]<br />
* [[Setting up Transmission (bittorrent) with Clutch WebUI]]<br />
* [[Hosting services on Alpine]] ''(This applies to hosting mail, webservices and other services)''<br />
** [[Setting up postfix with virtual domains]]<br />
** [[Protecting your email server with Alpine]]<br />
** [[Hosting Web/Email services on Alpine]]<br />
* [[Setting up a ssh-server]]<br />
* [[Multiple Instances of Services]]<br />
* [[ISP Mail Server HowTo]] ''(Postfix+PostfixAdmin+DoveCot+Roundcube+ClamAV+Spamd - A full-serivce ISP mail server)''<br />
** [[Upgrading ISP Mail Server to 2.x]]<br />
* [[Freepbx on Alpine Linux]]<br />
* [[Apache authentication: NTLM Single Signon]]<br />
* [[Generating SSL certs with ACF]]<br />
* [[Changing passwords for ACF]]<br />
* [[Freeradius Active Directory Integration]]<br />
* [[High Availability High Performance Web Cache]] ''uCarp + HAProxy for High Availability Services such as Squid web proxy''<br />
<br />
== Web Applications ==<br />
* [[2600hz]] ''FreeSWITCH, Asterisk GUI web acces tool.''<br />
* [[Awstats]] ''Free log file analyzer.''<br />
* [[Drupal]] ''Content Management System (CMS) written in PHP.''<br />
* [[EyeOS]] ''Cloud Computing Desktop.''<br />
* [[FreePBX_V3]] ''FreeSWITCH, Asterisk GUI web acces tool.''<br />
* [[Glpi]] ''Information Resource-Manager.''<br />
* [[MediaWiki]] ''Free web-based wiki software application''<br />
* [[Phpizabi]] ''Social Networking Platform.''<br />
* [[PhpPgAdmin]] ''Web-based administration tool for PostgreSQL.''<br />
* [[Phpmyadmin]] ''Web-based administration tool for MYSQL.''<br />
* [[Redmine]] ''Project management system ''<br />
* [[Roundcube]] ''Webmail system''<br />
* [[Statusnet]] ''Microblogging Platform.''<br />
* [[Sqstat]] ''Script to look active squid users connections.''<br />
* [[Webmin]] ''A web-based interface for Linux system.''<br />
* [[WordPress]] ''Web software to create website or blog. ''<br />
<br />
== Monitoring ==<br />
* [[Traffic monitoring]] ''(For Alpine Linux firewalls)''<br />
* [[Setting up traffic monitoring using rrdtool (and snmp)]]<br />
* [[Setting up Smokeping]] ''(Smokeping network latency monitoring)''<br />
* [[Setting up Cacti]]<br />
* [[Setting up NRPE daemon]] ''(Performs remote Nagios checks)''<br />
* [[Setting up Zabbix]]<br />
* [[Setting Up Fprobe And Ntop]] ''NetFlow collection and analysis''<br />
<br />
== Misc ==<br />
* [[Setting up lm_sensors]]<br />
* [[Formatting HD/Floppy/Other]]<br />
* [[Screen on console]]<br />
* [[Using espeak on Alpine Linux]]<br />
* [[IPTV How To]]<br />
* [[Pllua]]<br />
* [[Error message on boot: Address space collision: host bridge window conflicts with Adaptor ROM]]<br />
<br />
== Drafts ==<br />
Those are not finished yet.<br />
* [[AlpineSystem:CoLinux_Setup | Installing Alpine on CoLinux ]]<br />
* [[Using Racoon for Remote Sites]]<br />
* [[High Performance and Fault Tolerant Routing with Alpine Linux]]<br />
* [[Setting up Transparent Squid Proxy]] ''(Covers Squid proxy and URL Filtering system)''<br />
** [[Obtaining user information via SNMP]] ''(Using the Squark Squid authentication helper)''<br />
* [[Setting up Streaming an Asterisk Channel]]<br />
* [[Setting up A Network Monitoring and Inventory System]] ''((Nagios + OpenAudit and related components)''<br />
* [[Intrusion Detection using Snort]] ''Installing and configuring Snort and related applications on Alpine 2.0.x''<br />
* [[IP Accounting]] ''Installing and configuring pmacct for IP Accounting, Netflow/sFlow collector''<br />
* [[Howto Setup a Wireless Access Point]] ''Setting up Secure Wireless AP w/ WPA encryption with bridge to wired network''<br />
<br />
<br />
== Obsolete Docs ==<br />
Those are candidates for rewriting/removal.<br />
* [[Bootstrapping Alpine on Soekris net4xxx]]<br />
* [[Bootstrapping Alpine on PC Engines ALIX.3]]<br />
* [[Setting up a /var partition on software IDE raid1]]<br />
* [[Native Harddisk Install]]<br />
* [[Installing XUbuntu using Alpine boot floppy]]<br />
* [[Setting up trac wiki]]</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_Upgrade_2.x&diff=5109ISP Mail Server Upgrade 2.x2011-05-03T09:05:53Z<p>Iilluzion: Created page with "Category:mail == A Full Service Mail Server Upgrade to 2.x == It's assumed that currently your server is running under Alpine Linux 1.10.x. The goal of this document is to d..."</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server Upgrade to 2.x ==<br />
<br />
It's assumed that currently your server is running under Alpine Linux 1.10.x. The goal of this document is to describe how to upgrade "ISP Mail Server" to run under Alpine Linux 2.2. An upgrade process involves several significant changes in application configuration and database data and schema handling. Applications that come with Alpine Linux 2.x have a lot of bug and security fixes as well as new functionality. Upgrading of some components will require changing configurations files, update database schema and export/import data.<br />
<br />
'''NOTE:''' The ISP Mail Server can be run in RAM having directories for data such as Postfix mailboxes, PostgreSQL databases to be mounted on hard drive RAID/LVM partitions.<br />
<br />
== System Preparations before upgrade ==<br />
<br />
'''IMPORTANT NOTE''': Please perform full system backup including system configuration and user data. Make sure sure that backup is valid.<br />
<br />
We recommend you to stop all user services permanently until system fully upgraded and tested. While system tests are being perform block user access for all users. <br />
<br />
'''NOTE:''' One of the ways to block user access is to use firewall rules.<br />
<br />
Remove services from auto-start:<br />
<br />
rc-update del lighttpd<br />
rc-update del dovecot<br />
rc-update del postfix<br />
rc-update del freshclam<br />
rc-update del clamd<br />
rc-update del clamsmtpd<br />
rc-update del slapd<br />
rc-update del postgresql<br />
rc-update del cron<br />
<br />
Stop services except ''postfesql'':<br />
<br />
/etc/init.d/lighttpd stop<br />
/etc/init.d/slapd stop<br />
/etc/init.d/dovecot stop<br />
/etc/init.d/postfix stop<br />
/etc/init.d/clamsmtpd stop<br />
/etc/init.d/freshclam stop<br />
/etc/init.d/clamd stop<br />
/etc/init.d/cron stop<br />
<br />
== Dump PostreSQL databases ==<br />
<br />
Since version 9 has significant changes in compare to version 8 you must dump all PostgreSQL databases and later restore data after PostgreSQL is upgraded.<br />
<br />
Create a directory where data will be dumped:<br />
<br />
mkdir <Path to datadump directory><br />
chown postges <Path to datadump directory><br />
<br />
Login as ''postgres'' and dump data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
pg_dumpall > postgresql.bak.8.4.2<br />
exit<br />
<br />
Stop PostgreSQL services:<br />
<br />
/etc/init.d/postgresql stop<br />
<br />
'''IMPORTANT NOTE''': Please perform backup of dumped data and PostgeSQL data directory ''/var/lib/postgresql/8.4''. Make sure sure that backup is valid.<br />
<br />
== Upgrading Alpine Linux ==<br />
<br />
'''NOTE:''' We recommend to upgrade to Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues.<br />
<br />
Follow instructions described on page: http://wiki.alpinelinux.org/wiki/Upgrading_Alpine_-_v1.9.x. <br />
<br />
'''NOTE:''' If your server is running in RAM make sure that you have ''/media/usbdisk'' in ''/etc/fstab'' and ''/etc/lbu/lbu.conf'' files.<br />
<br />
After reboot you may check changes in new configuration files and proceed with adjustments as needed:<br />
<br />
find /etc -iname "*apk-new"<br />
<br />
== Import data to PostgeSQL ==<br />
<br />
Make sure that file ''/etc/conf.d/psotgresql'' contains: <br />
<br />
PGDATA="/var/lib/postgresql/9.0/data"<br />
<br />
Check if you need any special setting in ''/var/lib/postgresql/9.0/data/pg_hba.conf'' and ''/var/lib/postgresql/9.0/data/postgresql.conf''. In most cases these files could remain unchanged.<br />
<br />
Start PostgeSQL (It will setup itself since by default AUTO_SETUP=yes)<br />
<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
Import previously dumped data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
psql -f postgresql.bak.8.4.2 postgres<br />
exit<br />
<br />
== Start other services ==<br />
<br />
Other services do not require any changes of their current configurations, you may just start them: <br />
<br />
/etc/init.d/clamd start<br />
/etc/init.d/freshclam start<br />
/etc/init.d/clamsmtp start<br />
/etc/init.d/postfix start<br />
/etc/init.d/lighttpd start<br />
/etc/init.d/slapd start<br />
/etc/init.d/cron start<br />
<br />
Add these service to boot sequence: <br />
<br />
rc-update add lighttpd<br />
rc-update add freshclam<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
rc-update add postfix<br />
rc-update add slapd<br />
rc-update add cron<br />
<br />
== Update Dovecot configuration ==<br />
<br />
Since Dovecot has many configuration settings changed since 1.x version, the best way is to parse old configuration with ''doveconf'' tool:<br />
<br />
cd /etc/dovecot<br />
doveconf -n > dovecot.conf-new<br />
mv dovecot.conf dovecot.conf-old<br />
mv dovecot.conf-new dovecot.conf<br />
/etc/init.d/dovecot start<br />
<br />
If you receive a warning such as "''Warning: service anvil { client_limit=NNNN } is lower than required under max. load (MMMM)''" the update ''anvil'' service configuration:<br />
<br />
vi /etc/dovecot/dovecot.conf<br />
<br />
service anvil {<br />
client_limit = <MMMM><br />
}<br />
<br />
/etc/init.d/dovecot restart<br />
<br />
== Update Quota Configuration ==<br />
<br />
If you setup Quota support you need to make the following modifications: <br />
<br />
vi /etc/dovecot/dovecot.conf<br />
<br />
service dict {<br />
unix_listener dict {<br />
group =<br />
mode = 0600<br />
user = mailuser<br />
} <br />
}<br />
<br />
Change permission of ''dovecot-dict-quota.conf'' file:<br />
<br />
chown dovecot /etc/docecot/dovecot-dict-quota.conf<br />
<br />
Restart Dovecot:<br />
<br />
/etc/init.d/dovecot restart<br />
<br />
== Update Roundcube Webmail configuration ==<br />
<br />
Move Roundcube configuration files to ''/etc/roundcube'':<br />
<br />
mv /usr/share/webapps/roundcube/config/main.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/db.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/mimetypes.php /etc/roundcube<br />
<br />
Enable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
Install ''roundcubemail-install'' package:<br />
<br />
apk add roundcubemail-installer<br />
<br />
Run configuration and system checks:<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=1<br />
:'''NOTE:''' You may need to install php-dom, php-intl components and restart Lighttpd.<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=3<br />
<br />
:Replace '''imap_root'' with ''imap_ns_personal'' in /etc/roundcube/main.inc.php<br />
<br />
$rcmail_config['imap_ns_personal'] = null;<br />
<br />
:Run only commands that are superscribed with the previously installed version number from ''/usr/share/webapps/roundcube/SQL/postgres.update.sql'':<br />
<br />
cp /usr/share/webapps/roundcube/SQL/postgres.update.sql /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql<br />
<br />
:Edit ''/usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql'', remove not needed commands and run script:<br />
<br />
su - postgres<br />
psql -f /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql roundcubemail<br />
exit<br />
<br />
:Change ownership of two new tables:<br />
<br />
psql -U postgres roundcubemail<br />
roundcubemail=# ALTER TABLE contactgroups OWNER TO roundcube;<br />
roundcubemail=# ALTER TABLE contactgroupmembers OWNER TO roundcube;<br />
<br />
Due to security reason disable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
Due to security reason remove ''roundcubemail-install'' package:<br />
<br />
apk del roundcubemail-installer<br />
<br />
Makes sure you have restored all customizations such ''watermark.gif'', ''roundcube_logo.gif'', ''favicon.ico'' or custom roundcube skin. If you would like to disable displaying of standard logos update template files accordingly:<br />
<br />
includes/header.html:<!--<div id="header"><a href="./"><img id="logo" src="/images/roundcube_logo.png" alt="logo" title="<roundcube:object name='productname' />" /></a></div>--><br />
templates/error.html:<!--<div id="header"><img src="/images/roundcube_logo.png" alt="<roundcube:object name='productname' />" /></div>--><br />
templates/messageprint.html:<!--<div id="header"><img src="/images/roundcube_logo.png" alt="<roundcube:object name="productname" />" /></div>--><br />
templates/login.html:<!--<img id="logo" src="/images/roundcube_logo.png" border="0" alt="<roundcube:object name='productname' />" style="margin:0 11px" /> --><br />
templates/printmessage.html:<!--<div id="header"><img src="/images/roundcube_logo.png" alt="<roundcube:object name="productname" />" /></div>--><br />
<br />
templates/identities.html: <!--<img src="/images/watermark.gif" width="260" height="228" alt="" />--><br />
templates/login.html: /images/watermark.gif<br />
templates/messageerror.html:<!--<img src="/images/watermark.gif" width="260" height="228" alt="" />--><br />
templates/messageerror.html:<!--<img src="/images/watermark.gif" width="260" height="228" alt="" />--><br />
watermark.html:<!--<img src="images/watermark.gif" width="260" height="228" alt="" />--><br />
<br />
Restart Lighttpd:<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Test Roundcube Webmail site including functionality of activated plug-ins.<br />
<br />
== Optionally enable compression in Lighttpd ==<br />
<br />
Uncomment '''mod_compress''' and '''mod_setenv''' and modify website section as follows:<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
vi /etc/lighttpd/lighttpd.conf<br />
<br />
...<br />
"mod_setenv",<br />
"mod_compress",<br />
...<br />
static-file.etags = "enable"<br />
etag.use-mtime = "enable"<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" { setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000") }<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=User:Iilluzion&diff=5101User:Iilluzion2011-05-02T07:37:39Z<p>Iilluzion: </p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server Upgrade to 2.x ==<br />
<br />
It's assumed that currently your server is running under Alpine Linux 1.10.x. The goal of this document is to describe how to upgrade "ISP Mail Server" to run under Alpine Linux 2.2. An upgrade process involves several significant changes in application configuration and database data and schema handling. Applications that come with Alpine Linux 2.x have a lot of bug and security fixes as well as new functionality. Upgrading of some components will require changing configurations files, update database schema and export/import data.<br />
<br />
'''NOTE:''' The ISP Mail Server can be run in RAM having directories for data such as Postfix mailboxes, PostgreSQL databases to be mounted on hard drive RAID/LVM partitions.<br />
<br />
== System Preparations before upgrade ==<br />
<br />
'''IMPORTANT NOTE''': Please perform full system backup including system configuration and user data. Make sure sure that backup is valid.<br />
<br />
We recommend you to stop all user services permanently until system fully upgraded and tested. While system tests are being perform block user access for all users. <br />
<br />
'''NOTE:''' One of the ways to block user access is to use firewall rules.<br />
<br />
Remove services from auto-start:<br />
<br />
rc-update del lighttpd<br />
rc-update del dovecot<br />
rc-update del postfix<br />
rc-update del freshclam<br />
rc-update del clamd<br />
rc-update del clamsmtpd<br />
rc-update del slapd<br />
rc-update del postgresql<br />
rc-update del cron<br />
<br />
Stop services except ''postfesql'':<br />
<br />
/etc/init.d/lighttpd stop<br />
/etc/init.d/slapd stop<br />
/etc/init.d/dovecot stop<br />
/etc/init.d/postfix stop<br />
/etc/init.d/clamsmtpd stop<br />
/etc/init.d/freshclam stop<br />
/etc/init.d/clamd stop<br />
/etc/init.d/cron stop<br />
<br />
== Dump PostreSQL databases ==<br />
<br />
Since version 9 has significant changes in compare to version 8 you must dump all postgresql databases and later restore data after postgresql is upgraded.<br />
<br />
Create a directory where data will be dumped:<br />
<br />
mkdir <Path to datadump directory><br />
chown postges <Path to datadump directory><br />
<br />
Login as ''postgres'' and dump data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
pg_dumpall > postgresql.bak.8.4.2<br />
exit<br />
<br />
Stop PostgreSQL services:<br />
<br />
/etc/init.d/postgresql stop<br />
<br />
'''IMPORTANT NOTE''': Please perform backup of dumped data and PostgeSQL data directory ''/var/lib/postgresql/8.4''. Make sure sure that backup is valid.<br />
<br />
== Upgrading Alpine Linux ==<br />
<br />
'''NOTE:''' We recommend to upgrade to Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues.<br />
<br />
Follow instructions described on page: http://wiki.alpinelinux.org/wiki/Upgrading_Alpine_-_v1.9.x. After system reboot proceed with next parts of this documents to complete upgrade.<br />
<br />
== Import data to PostgeSQL ==<br />
<br />
Make sure that file ''/etc/conf.d/psotgresql'' contains: <br />
<br />
PGDATA="/var/lib/postgresql/9.0/data"<br />
<br />
Check if you need any special setting in ''/var/lib/postgresql/9.0/data/pg_hba.conf'' and ''/var/lib/postgresql/9.0/data/postgresql.conf''. In most cases these files could remain unchanged.<br />
<br />
Start PostgeSQL (It will setup itself since by default AUTO_SETUP=yes)<br />
<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
Import previously dumped data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
psql -f postgresql.bak.8.4.2 postgres<br />
exit<br />
<br />
== Start other services ==<br />
<br />
Other services do not require any changes of their current configurations, you may just start them: <br />
<br />
/etc/init.d/clamd start<br />
/etc/init.d/freshclam start<br />
/etc/init.d/clamsmtp start<br />
/etc/init.d/postfix start<br />
/etc/init.d/lighttpd start<br />
/etc/init.d/slapd start<br />
/etc/init.d/cron start<br />
<br />
Add these service to boot sequence: <br />
<br />
rc-update add lighttpd<br />
rc-update add freshclam<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
rc-update add postfix<br />
rc-update add slapd<br />
rc-update add cron<br />
<br />
== Update Dovecot configuration ==<br />
<br />
Since Dovecot has many configuration settings changed since 1.x version, the best way is to parse old configuration with ''doveconf'' tool:<br />
<br />
cd /etc/dovecot<br />
doveconf -n > dovecot.conf-new<br />
mv dovecot.conf dovecot.conf-old<br />
mv dovecot.conf-new dovecot.conf<br />
/etc/init.d/dovecot start<br />
<br />
== Update Quota Configuration ==<br />
<br />
== Update Roundcube Webmail configuration ==<br />
<br />
Move Roundcube configuration files to ''/etc/roundcube'':<br />
<br />
mv /usr/share/webapps/roundcube/config/main.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/db.inc.php /etc/roundcube<br />
mv /usr/share/webapps/roundcube/config/mimetypes.php /etc/roundcube<br />
<br />
Enable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = true;<br />
<br />
Install ''roundcubemail-install'' package:<br />
<br />
apk add roundcubemail-installer<br />
<br />
Run configuration and system checks:<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=1<br />
:'''NOTE:''' You may need to install php-dom, php-intl components and restart Lighttpd.<br />
<br />
* https://host.example.com/roundcube/installer/index.php?_step=3<br />
<br />
:Replace '''imap_root'' with ''imap_ns_personal<br />
'' in /etc/roundcube/main.inc.php<br />
<br />
$rcmail_config['imap_ns_personal'] = null;<br />
<br />
<br />
:Run only commands that are superscribed with the previously installed version number from ''/usr/share/webapps/roundcube/SQL/postgres.update.sql'':<br />
cp /usr/share/webapps/roundcube/SQL/postgres.update.sql /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql<br />
<br />
edit /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql and remove not needed commands<br />
<br />
su - postgres<br />
<br />
psql -f /usr/share/webapps/roundcube/SQL/postgres.update-3.1.sql roundcubemail<br />
<br />
exit<br />
<br />
<br />
:Change ownership of two new tables:<br />
<br />
psql -U postgres roundcubemail<br />
roundcubemail=# ALTER TABLE contactgroups OWNER TO roundcube;<br />
roundcubemail=# ALTER TABLE contactgroupmembers OWNER TO roundcube;<br />
<br />
Due to security reason disable ''installer'' mode in ''/etc/roundcube/main.inc.php'' file:<br />
<br />
$rcmail_config['enable_installer'] = false;<br />
<br />
Due to security reason remove ''roundcubemail-install'' package:<br />
<br />
apk del roundcubemail-installer<br />
<br />
<br />
Makes sure you have restored all customizations such watermark.gif, roundcube_logo.gif, favicon.ico or custom roundcube skin. IF you would like to disable displaying of standard logos update template files accordingly:<br />
<br />
<br />
includes/header.html:<!--<div id="header"><a href="./"><img id="logo" src="/images/roundcube_logo.png" alt="logo" title="<roundcube:object name='productname' />" /></a></div>--><br />
<br />
templates/error.html:<!--<div id="header"><img src="/images/roundcube_logo.png" alt="<roundcube:object name='productname' />" /></div>--><br />
<br />
templates/messageprint.html:<!--<div id="header"><img src="/images/roundcube_logo.png" alt="<roundcube:object name="productname" />" /></div>--><br />
<br />
templates/login.html:<!--<img id="logo" src="/images/roundcube_logo.png" border="0" alt="<roundcube:object name='productname' />" style="margin:0 11px" /> --><br />
<br />
templates/printmessage.html:<!--<div id="header"><img src="/images/roundcube_logo.png" alt="<roundcube:object name="productname" />" /></div>--><br />
<br />
<br />
<br />
Test Roundcube Webmail site including functionality of activated plug-ins.<br />
<br />
<br />
== Final Notes ==<br />
<br />
<br />
16. some fixes<br />
<br />
run find /etc -iname "*apk-new"<br />
<br />
and check is there any significant changes in config files<br />
<br />
fix accordingly <br />
<br />
Some optimizations mod-compres mod-setenv for lighttpd<br />
<br />
mkdir -p /var/lib/lighttpd/cache<br />
<br />
lbu add /var/lib/lighttpd/cache/compress<br />
<br />
lbu exclude /var/lib/lighttpd/cache/compress/*<br />
<br />
chown lighttpd:lighttpd /var/lib/lighttpd/cache<br />
<br />
<br />
<br />
nano /etc/lighttpd/lighttpd.conf<br />
<br />
uncomment mod_compress and mod_setenv<br />
<br />
<br />
<br />
modify website section:<br />
<br />
static-file.etags = "enable"<br />
<br />
etag.use-mtime = "enable"<br />
<br />
$HTTP["url"] =~ "^/(plugins|skins|program)" {<br />
<br />
setenv.add-response-header = ( "Cache-Control" => "public, max-age=2592000")<br />
<br />
}<br />
<br />
compress.cache-dir = var.statedir + "/cache/compress"<br />
<br />
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml", "image/gif", "image/png")</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=User:Iilluzion&diff=5100User:Iilluzion2011-05-02T07:07:10Z<p>Iilluzion: </p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server Upgrade to 2.x ==<br />
<br />
It's assumed that currently your server is running under Alpine Linux 1.10.x. The goal of this document is to describe how to upgrade "ISP Mail Server" to run under Alpine Linux 2.2. An upgrade process involves several significant changes in application configuration and database data and schema handling. Applications that come with Alpine Linux 2.x have a lot of bug and security fixes as well as new functionality. Upgrading of some components will require changing configurations files, update database schema and export/import data.<br />
<br />
'''NOTE:''' The ISP Mail Server can be run in RAM having directories for data such as Postfix mailboxes, PostgreSQL databases to be mounted on hard drive RAID/LVM partitions.<br />
<br />
== System Preparations before upgrade ==<br />
<br />
'''IMPORTANT NOTE''': Please perform full system backup including system configuration and user data. Make sure sure that backup is valid.<br />
<br />
We recommend you to stop all user services permanently until system fully upgraded and tested. While system tests are being perform block user access for all users. <br />
<br />
'''NOTE:''' One of the ways to block user access is to use firewall rules.<br />
<br />
Remove services from auto-start:<br />
<br />
rc-update del lighttpd<br />
rc-update del dovecot<br />
rc-update del postfix<br />
rc-update del freshclam<br />
rc-update del clamd<br />
rc-update del clamsmtpd<br />
rc-update del slapd<br />
rc-update del postgresql<br />
rc-update del cron<br />
<br />
Stop services except ''postfesql'':<br />
<br />
/etc/init.d/lighttpd stop<br />
/etc/init.d/slapd stop<br />
/etc/init.d/dovecot stop<br />
/etc/init.d/postfix stop<br />
/etc/init.d/clamsmtpd stop<br />
/etc/init.d/freshclam stop<br />
/etc/init.d/clamd stop<br />
/etc/init.d/cron stop<br />
<br />
== Dump PostreSQL databases ==<br />
<br />
Since version 9 has significant changes in compare to version 8 you must dump all postgresql databases and later restore data after postgresql is upgraded.<br />
<br />
Create a directory where data will be dumped:<br />
<br />
mkdir <Path to datadump directory><br />
chown postges <Path to datadump directory><br />
<br />
Login as ''postgres'' and dump data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
pg_dumpall > postgresql.bak.8.4.2<br />
exit<br />
<br />
Stop PostgreSQL services:<br />
<br />
/etc/init.d/postgresql stop<br />
<br />
'''IMPORTANT NOTE''': Please perform backup of dumped data and PostgeSQL data directory ''/var/lib/postgresql/8.4''. Make sure sure that backup is valid.<br />
<br />
== Upgrading Alpine Linux ==<br />
<br />
'''NOTE:''' We recommend to upgrade to Alpine Linux version not earlier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues.<br />
<br />
Follow instructions described on page: http://wiki.alpinelinux.org/wiki/Upgrading_Alpine_-_v1.9.x. After system reboot proceed with next parts of this documents to complete upgrade.<br />
<br />
== Import data to PostgeSQL ==<br />
<br />
Make sure that file ''/etc/conf.d/psotgresql'' contains: <br />
<br />
PGDATA="/var/lib/postgresql/9.0/data"<br />
<br />
Check if you need any special setting in ''/var/lib/postgresql/9.0/data/pg_hba.conf'' and ''/var/lib/postgresql/9.0/data/postgresql.conf''. In most cases these files could remain unchanged.<br />
<br />
Start PostgeSQL (It will setup itself since by default AUTO_SETUP=yes<br />
)<br />
<br />
/etc/init.d/postgresql start<br />
<br />
<br />
rc-update add postgresql<br />
<br />
Import previously dumped data:<br />
<br />
<br />
su - postgres<br />
<br />
cd <Path to datadump directory><br />
psql -f postgresql.bak.8.4.2 postgres<br />
<br />
exit<br />
<br />
<br />
<br />
== Start other services ==<br />
<br />
Other services do not require any changes of their current configurations, you may just start them: <br />
<br />
/etc/init.d/clamd start<br />
/etc/init.d/freshclam start<br />
/etc/init.d/clamsmtp start<br />
/etc/init.d/postfix start<br />
/etc/init.d/lighttpd start<br />
/etc/init.d/slapd start<br />
/etc/init.d/cron start<br />
<br />
Add these service to boot sequence: <br />
<br />
rc-update add lighttpd<br />
rc-update add freshclam<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
rc-update add postfix<br />
rc-update add slapd<br />
rc-update add cron<br />
<br />
== Update Dovecot configuration and start ==<br />
<br />
Since Dovecot has many configuration settings changed since 1.x version, the best way is to parse old configuration with ''doveconf'' tool:<br />
<br />
cd /etc/dovecot<br />
<br />
doveconf -n > dovecot.conf-new<br />
<br />
mv dovecot.conf dovecot.conf-old<br />
<br />
mv dovecot.conf-new dovecot.conf<br />
<br />
/etc/init.d/dovecot start<br />
<br />
<br />
<br />
<br />
<br />
<br />
== Final Notes ==</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=User:Iilluzion&diff=5099User:Iilluzion2011-05-02T06:08:24Z<p>Iilluzion: Upgrading ISP Mail server from 1.10.x to 2.x</p>
<hr />
<div>[[Category:mail]]<br />
== A Full Service Mail Server Upgrade to 2.x ==<br />
<br />
It's assumed that currently your server is running under Alpine Linux 1.10.x. The goal of this document is to describe how to upgrade "ISP Mail Server" to run under Alpine Linux 2.2. An upgrade process involves several significant changes in application configuration and database data and schema handling. Applications that come with Alpine Linux 2.x have a lot of bug and security fixes as well as new functionality. Upgrading of some components will require changing configurations files, update database schema and export/import data.<br />
<br />
== System Preparations before upgrade ==<br />
<br />
'''IMPORTANT NOTE''': Please perform full system backup including system configuration and user data. Make sure sure that backup is valid.<br />
<br />
We recommend you to stop all user services permanently until system fully upgraded and tested. While system tests are being perform block user access for all users. <br />
<br />
'''NOTE:''' One of the ways to block user access is to use firewall rules.<br />
<br />
Remove services from auto-start:<br />
<br />
rc-update del lighttpd dovecot postfix freshclam clamd clamsmtpd slapd postgresql cron<br />
<br />
Stop services except ''postfesql'':<br />
<br />
/etc/init.d/lighttpd stop<br />
/etc/init.d/slapd stop<br />
/etc/init.d/dovecot stop<br />
/etc/init.d/postfix stop<br />
/etc/init.d/clamsmtpd stop<br />
/etc/init.d/freshclam stop<br />
/etc/init.d/clamd stop<br />
/etc/init.d/cron stop<br />
<br />
== Dump PostreSQL databases ==<br />
<br />
Since version 9 has significant changes in compare to version 8 you must dump all postgresql databases and later restore data after postgresql is upgraded.<br />
<br />
Create a directory where data will be dumped:<br />
<br />
mkdir <Path to datadump directory><br />
chown postges <Path to datadump directory><br />
<br />
Login as ''postgres'' and dump data:<br />
<br />
su - postgres<br />
cd <Path to datadump directory><br />
pg_dumpall > postgresql.bak.8.4.2<br />
exit<br />
<br />
Stop PostgreSQL services:<br />
<br />
/etc/init.d/postgresql stop<br />
<br />
'''IMPORTANT NOTE''': Please perform backup of dumped data and PostgeSQL data directory ''/var/lib/postgresql/8.4''. Make sure sure that backup is valid.<br />
<br />
== Upgrading Alpine Linux ==<br />
<br />
Follow instructions described on page: http://wiki.alpinelinux.org/wiki/Upgrading_Alpine_-_v1.9.x.<br />
<br />
'''NOTE:''' We recommend to upgrade to Alpine Linux version not eralier than 2.2, since release 2.2 has a lot of important fixes for bugs and security issues.<br />
<br />
* Upgrading Alpine Linux<br />
:* Notes about systems running in RAM<br />
* Upgrading Ligihttpd and PHP<br />
* Upgrading Postgress<br />
:* Export and Import databases<br />
* Upgrading Postfix<br />
* Upgrading Dovecot<br />
:* Changing main configuration<br />
:* Changing Quota configuration<br />
* Upgrading Virus Scanning<br />
* Upgrading RoundCube Webmail<br />
:* Upgrading database schema<br />
* Upgrading OpenLDAP<br />
* Final notes</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3518ISP Mail Server HowTo2010-04-07T06:53:46Z<p>Iilluzion: password plugin minor fixes and action log added</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.11<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown root:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password,modified) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# GRANT INSERT ON log TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_minimum_length'] = 7;<br />
$rcmail_config['password_require_nonalpha'] = true;<br />
...<br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c, modified = NOW() where username = %u; INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),%u || ' (' || %h || ')',%d,'edit_password',%u)";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3517ISP Mail Server HowTo2010-04-06T16:40:53Z<p>Iilluzion: Minor fixes</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.11<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown root:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c where username = %u";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
rm script<br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
# by peername.ip=<IP>%<netmask> read<br />
# by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
In order to enable php-ldap support you need to restart lighttpd server<br />
<br />
/etc/init.d/lighttpd restart<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'sql';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('sql','example.com');<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3515ISP Mail Server HowTo2010-04-02T12:14:35Z<p>Iilluzion: correct permissions for dovecot-dict-quota.conf</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.11<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
chown root:root /etc/dovecot/dovecot-dict-quota.conf<br />
chmod 600 /etc/dovecot/dovecot-dict-quota.conf<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c where username = %u";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3512ISP Mail Server HowTo2010-04-02T11:35:51Z<p>Iilluzion: minor</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.11<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c where username = %u";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3511ISP Mail Server HowTo2010-04-02T11:16:06Z<p>Iilluzion: full absolute user home dir path</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.11<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' || maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c where username = %u";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
Put the following into a new file called '''script''':<br />
<br />
<pre><br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
);<br />
<br />
ALTER TABLE ldap_oc_mappings ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_oc_mappings ADD PRIMARY KEY (id);<br />
<br />
CREATE TABLE ldap_attr_mappings_test (<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
);<br />
<br />
ALTER TABLE ldap_attr_mappings_test ADD COLUMN id SERIAL;<br />
ALTER TABLE ldap_attr_mappings_test ADD PRIMARY KEY (id);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
</pre><br />
<br />
Finally, execute the commands in the file with:<br />
cat script | psql -U postfix postfix<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3507ISP Mail Server HowTo2010-03-26T12:58:56Z<p>Iilluzion: redirect hosts to their secure equivalents</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.11<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c where username = %u";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
id integer SERIAL,<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE TABLE ldap_attr_mappings_test (<br />
id integer SERIAL,<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
EOF<br />
</pre><br />
<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3506ISP Mail Server HowTo2010-03-26T12:47:24Z<p>Iilluzion: multi-domain certificate note</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.11<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c where username = %u";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
id integer SERIAL,<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE TABLE ldap_attr_mappings_test (<br />
id integer SERIAL,<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
EOF<br />
</pre><br />
<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
'''Note:''' 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.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3503ISP Mail Server HowTo2010-03-23T05:13:51Z<p>Iilluzion: Minor corrections</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.11<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in ''/usr/share/webapps/roundcube/plugins'' directory. For example you may want to enable ''password'' plug-in to let users change their passwords directly from RoundCube using an extra Password Tab added to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# \q<br />
<br />
* Setup ''password'' plug-in parameters in ''/usr/share/webapps/roundcube/plugins/password/config.inc.php''<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c where username = %u";<br />
</pre><br />
<br />
* Enable ''password'' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
id integer SERIAL,<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE TABLE ldap_attr_mappings_test (<br />
id integer SERIAL,<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
EOF<br />
</pre><br />
<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3502ISP Mail Server HowTo2010-03-22T17:30:08Z<p>Iilluzion: Enabling "Change Password" RoundCube Plug-in</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain. This can be done with busybox sed (replace example.com with your domain name):<br />
<br />
sed -i -e 's/change-this-to-your.domain.tld/example.com/g' /var/www/domains/host.example.com/www/postfixadmin/config.inc.php<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add clamsmtpd<br />
/etc/init.d/clamd start<br />
/etc/init.d/clamsmtpd start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add teh following inside the ''auth default'' stanza:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.11<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select '/var/mail/domains/' as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
==== Enable Plug-ins ====<br />
<br />
RoundCube has various useful plug-ins, which could be found in /usr/share/webapps/roundcube/plugins directory. For example you may want to enable '''password''' plug-in to let user change his password directly from RoundCube. The '''password''' plugin adds an extra Tab to User Settings.<br />
<br />
* Grant limited permissions for ''roundcube'' database role <br />
psql -U postgres postfix<br />
postfix=# GRANT UPDATE (password) ON mailbox TO roundcube;<br />
postfix=# GRANT SELECT (username) ON mailbox TO roundcube;<br />
postfix=# \q<br />
exit<br />
<br />
* Setup '''password''' plug-in parameters in ../plugins/password/config.inc.php<br />
mv /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
vi /usr/share/webapps/roundcube/plugins/password/config.inc.php<br />
<br />
<pre><br />
$rcmail_config['password_db_dsn'] = 'pgsql://roundcube:<roundcube_password>@localhost/postfix';<br />
...<br />
$rcmail_config['password_query'] = "UPDATE mailbox set password = %c where username = %u";<br />
</pre><br />
<br />
* Enable '''password''' plug-in<br />
vi /usr/share/webapps/roundcube/config/main.inc.php<br />
<br />
<pre><br />
...<br />
$rcmail_config['plugins'] = array('password');<br />
</pre><br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'com' according to your domain name parts.<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
id integer SERIAL,<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE TABLE ldap_attr_mappings_test (<br />
id integer SERIAL,<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
EOF<br />
</pre><br />
<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Optional: Configure Web Server Virtual Domains ==<br />
<br />
'''Note:''' These steps can be done ''in addition to'' the default lighttpd configuration above, which allows you to access the ACF, PostfixAdmin and Roundcube interfaces as subfolders of one web service.<br />
<br />
This server hosts three separate web applications, and these can be handled as three ''different'' 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 '''A''' records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3483ISP Mail Server HowTo2010-03-08T14:06:49Z<p>Iilluzion: minor fix</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain.<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add freshclam<br />
rc-update add clamsmtp<br />
/etc/init.d/clamd start<br />
/etc/init.d/freshclam start<br />
/etc/init.d/clamsmtp start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
<br />
<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.10<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
<br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'org' according to your domain name parts.<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
id integer SERIAL,<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE TABLE ldap_attr_mappings_test (<br />
id integer SERIAL,<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
EOF<br />
</pre><br />
<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exampleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Configure DNS ==<br />
<br />
This server hosts three separate web applications, and these can be handled as three different 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 A records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3482ISP Mail Server HowTo2010-03-08T13:43:18Z<p>Iilluzion: minor changes regardng exampl domain</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain.<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add freshclam<br />
rc-update add clamsmtp<br />
/etc/init.d/clamd start<br />
/etc/init.d/freshclam start<br />
/etc/init.d/clamsmtp start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
<br />
<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.10<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
<br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain example.com. So make sure you replaced all entries of 'example' and 'org' according to your domain name parts.<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
id integer SERIAL,<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE TABLE ldap_attr_mappings_test (<br />
id integer SERIAL,<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'com'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'com'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
EOF<br />
</pre><br />
<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exmpleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Configure DNS ==<br />
<br />
This server hosts three separate web applications, and these can be handled as three different 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 A records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=ISP_Mail_Server_HowTo&diff=3481ISP Mail Server HowTo2010-03-08T13:36:44Z<p>Iilluzion: OpenLDAP with SQL backend added for email lookups</p>
<hr />
<div>== A Full Service Mail Server ==<br />
<br />
The goal of this document is to describe how to set up postfix, dovecot, clamav, dspam, roundecube, and postfixadmin for a full-featured "ISP" level mail server.<br />
<br />
The server must provide:<br />
<br />
* multiple virtual domains<br />
* admins for each domain (to add/remove virtual accounts)<br />
* Quota support per domain / account<br />
* downloading email via IMAP / IMAPS / POP3 / POP3S<br />
* relaying email for authenticated users with TLS or SSL (Submission / SMTPS protocol)<br />
* Standard filters (virus/spam/rbl/etc)<br />
* Web mail client<br />
* Value Add services<br />
<br />
== Set up Lighttpd + PHP ==<br />
<br />
PostfixAdmin needs php pgpsql and imap modules, so we do it in this step.<br />
<br />
apk add lighttpd php php-pgsql php-imap<br />
<br />
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):<br />
<br />
mkdir -p /var/www/domains/host.example.com/www<br />
ln -s /usr/share/acf/www /var/www/domains/host.example.com/www/acf<br />
<br />
Edit /var/www/domains/host.example.com/index.html to put a simple redirection page:<br />
<br />
<pre><br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html lang="en"><br />
<head><br />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><br />
<title>host.example.com Redirector</title><br />
</head><br />
<body><br />
<ul><br />
<li><a href="/acf">ACF</a></li><br />
<li><a href="/postfixadmin">PostfixAdmin</a></li><br />
<li><a href="/roundcube">Roundcube</a></li><br />
</ul><br />
</body><br />
</pre><br />
<br />
Edit /etc/lighttpd/mod_cgi.conf to serve haserl files by adding a "" => "" cgi handler and to treat /acf/cgi-bin as a CGI directory (remove the '^')<br />
<br />
$HTTP["url"] =~ "/cgi-bin/" {<br />
# disable directory listings<br />
dir-listing.activate = "disable"<br />
# only allow cgi's in this directory<br />
cgi.assign = (<br />
".pl" => "/usr/bin/perl",<br />
".cgi" => "/usr/bin/perl",<br />
"" => ""<br />
)<br />
}<br />
<br />
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 ''host.example.com'' with the actual domain and ''ip_address_of_server'' with the actual IP address):<br />
<br />
<pre><br />
<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/host.example.com/"<br />
simple-vhost.document-root = "www/"<br />
<br />
$SERVER["socket"] == "ip_address_of_server:443" {<br />
ssl.engine = "enable"<br />
ssl.pemfile = "/etc/lighttpd/server-bundle.pem"<br />
ssl.ca-file = "/etc/lighttpd/ca-crt.pem"<br />
}<br />
</pre><br />
<br />
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<br />
<br />
server.modules = (<br />
# other modules may be listed<br />
"mod_simple_vhost", <br />
# other modules may be listed<br />
.<br />
.<br />
.<br />
include "mod_cgi.conf"<br />
<br />
include "mod_fastcgi.conf"<br />
<br />
<br />
Get a web certificate, and install it. If you want to use a self-signed cert, you can use [[Generating SSL certs with ACF]] or [[Generating SSL certs with ACF 1.9]]. If you create a certificate with ACF, you can create the "server-bundle.pem" and the "ca-crt.pem" file with these commands:<br />
<br />
openssl pkcs12 -nokeys -cacerts -in certificate.pfx -out /etc/lighttpd/ca-crt.pem<br />
openssl pkcs12 -nodes -in certifcate.pfx -out /etc/lighttpd/server-bundle.pem<br />
chown root:root /etc/lighttpd/server-bundle.pem<br />
chmod 400 /etc/lighttpd/server-bundle.pem<br />
<br />
<br />
'''Note:''' The server certificate ''and'' key are in the server-bundle.pem file, so it is critical that the file be read-only by user "root".<br />
<br />
Editme: We should probably only serve ACF to restricted hosts<br />
<br />
Stop and remove mini_httpd; start lighttpd, test<br />
<br />
/etc/init.d/mini_httpd stop<br />
rc-update del mini_httpd<br />
apk del mini_httpd<br />
rc-update add lighttpd<br />
/etc/init.d/lighttpd start<br />
<br />
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/<br />
<br />
== Install Postgresql ==<br />
<br />
Add and configure postgresql<br />
<br />
apk add acf-postgresql postgresql-client<br />
/etc/init.d/postgresql setup<br />
/etc/init.d/postgresql start<br />
rc-update add postgresql<br />
<br />
At this point any user can connect to the sql server with "trust" mechanism. If you want to enforce password authentication (you probably do) edit /var/lib/postgresql/8.4/data/pg_hba.conf<br />
<br />
<br />
Editme: What should we recommend?<br />
<br />
<br />
Create the postfix database:<br />
<br />
psql -U postgres<br />
create user postfix with password '******';<br />
create database postfix owner postfix;<br />
\c postfix<br />
create language plpgsql;<br />
\q<br />
<br />
(Of course, use your selected password where ******* is shown above.)<br />
<br />
== Install PostfixAdmin ==<br />
<br />
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.<br />
<br />
Download PostfixAdmin from Sourceforge. When these instructions were written, 2.3 was the current release, so (replace host.example.com with the actual domain):<br />
wget http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin_2.3.tar.gz<br />
tar zxvf postfixadmin_2.3.tar.gz<br />
mkdir -p /var/www/domains/host.example.com/www/postfixadmin<br />
mv postfixadmin-2.3/* /var/www/domains/host.example.com/www/postfixadmin<br />
rm -rf postfixadmin*<br />
<br />
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):<br />
<br />
$CONF['configured'] = true;<br />
$CONF['setup_password'] = ""; << Don't change this yet<br />
$CONF['database_type'] = 'pgsql';<br />
$CONF['database_host'] = 'localhost';<br />
$CONF['database_user'] = 'postfix';<br />
$CONF['database_password'] = '*****'; << The password you chose above<br />
$CONF['database_name'] = 'postfix';<br />
$CONF['database_prefix'] = "";<br />
$CONF['admin_email'] = 'you@some.email.com'; << Your email address <br />
$CONF['encrypt'] = 'md5crypt';<br />
$CONF['authlib_default_flavor'] = 'md5raw';<br />
$CONF['dovecotpw'] = "/usr/sbin/dovecotpw";<br />
$CONF['domain_path'] = 'YES';<br />
$CONF['domain_in_mailbox'] = 'NO';<br />
$CONF['aliases'] = '10'; <br />
$CONF['mailboxes'] = '10';<br />
$CONF['maxquota'] = '10';<br />
$CONF['quota'] = 'YES';<br />
$CONF['quota_multiplier'] = '1024000';<br />
$CONF['vacation'] = 'NO'; <br />
$CONF['vacation_control'] ='NO';<br />
$CONF['vacation_control_admin'] = 'NO';<br />
$CONF['alias_control'] = 'YES';<br />
$CONF['alias_control_admin'] = 'YES';<br />
$CONF['special_alias_control'] = 'YES';<br />
$CONF['fetchmail'] = 'NO';<br />
$CONF['user_footer_link'] = "http://host.example.com/postfixadmin";<br />
$CONF['footer_link'] = 'http://host.example.com/postfixadmin/main.php';<br />
$CONF['create_mailbox_subdirs_prefix']=""; <br />
$CONF['used_quotas'] = 'YES'; <br />
$CONF['new_quota_table'] = 'YES'; <br />
<br />
You should further edit /var/www/domains/host.example.com/www/postfixadmin/config.inc.php and replace all instances of "change-this-to-your.domain.tld" with your actual mail domain.<br />
<br />
Go to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create the password hash, add it to the config.inc.php file<br />
<br />
Go back to http://host.example.com/postfixadmin/setup.php<br />
<br />
Create superadmin account.<br />
<br />
== Install Postfix ==<br />
<br />
Create a user for the virtual mail delivery, and get its uid/gid (you'll need the numeric uid/gid for postfix)<br />
<br />
adduser vmail -H -D -s /bin/false<br />
grep vmail /etc/passwd<br />
<br />
(In examples below, we use 1006/1006 for the uid/gid)<br />
<br />
Create the mail directory, and assign vmail as the owner<br />
mkdir -p /var/mail/domains<br />
chown -R vmail:vmail /var/mail/domains<br />
<br />
<br />
Install postfix<br />
<br />
apk add acf-postfix postfix-pgsql<br />
<br />
Edit the /etc/postfix/main.cf file. Here's an example (don't forget to replace the uid/gid):<br />
<br />
myhostname=host.example.com<br />
mydomain=example.com<br />
<br />
mydestination = localhost.$mydomain, localhost<br />
mynetworks_style = subnet<br />
mynetworks = 127.0.0.0/8<br />
<br />
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_domains_maps.cf<br />
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
<br />
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/pgsql_virtual_mailbox_maps.cf,<br />
proxy:pgsql:/etc/postfix/sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
<br />
virtual_mailbox_base = /var/mail/domains/<br />
virtual_gid_maps = static:1006<br />
virtual_uid_maps = static:1006<br />
virtual_minimum_uid = 100<br />
virtual_transport = virtual<br />
<br />
<br />
# This next command means you must create a virtual<br />
# domain for the host itself - ALL mail goes through<br />
# The virtual transport<br />
<br />
mailbox_transport = virtual<br />
local_transport = virtual<br />
local_transport_maps = $virtual_mailbox_maps<br />
<br />
smtpd_helo_required = yes<br />
disable_vrfy_command = yes<br />
message_size_limit = 10240000<br />
queue_minfree = 51200000<br />
<br />
smtpd_sender_restrictions =<br />
permit_mynetworks,<br />
reject_non_fqdn_sender,<br />
reject_unknown_sender_domain<br />
<br />
smtpd_recipient_restrictions =<br />
reject_non_fqdn_recipient,<br />
reject_unknown_recipient_domain,<br />
permit_mynetworks,<br />
permit_sasl_authenticated,<br />
reject_unauth_destination,<br />
reject_rbl_client dnsbl.sorbs.net,<br />
reject_rbl_client zen.spamhaus.org,<br />
reject_rbl_client bl.spamcop.net<br />
<br />
smtpd_data_restrictions = reject_unauth_pipelining<br />
<br />
# we will use this later - This prevents cleartext authentication<br />
# for relaying<br />
smtpd_tls_auth_only = yes<br />
<br />
<br />
Now we need to create a *bunch* of files so that postfix can get the delivery information out of sql. Here's a shell script to create the scripts. Change PGPW to the password for the postfix user of the postfix SQL database.<br />
<br />
cd /etc/postfix<br />
mkdir sql<br />
PGPW="ChangeMe"<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_catchall_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias,alias_domain where alias_domain.alias_domain = '%d' and alias.address = '@' || alias_domain.target_domain and alias.active = true and alias_domain.active= true <br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox,alias_domain where alias_domain.alias_domain = '%d' and mailbox.username = '%u' || '@' || alias_domain.target_domain and mailbox.active = true and alias_domain.active<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_domain_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = select goto from alias,alias_domain where alias_domain.alias_domain='%d' and alias.address = '%u' || '@' || alias_domain.target_domain and alias.active= true and alias_domain.active= true<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_alias_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select goto From alias Where address='%s' and active ='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_domains_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select domain from domain where domain='%s' and active='1'<br />
EOF<br />
<br />
cat - <<EOF >sql/pgsql_virtual_mailbox_maps.cf<br />
user=postfix<br />
password = $PGPW<br />
hosts = localhost<br />
dbname = postfix<br />
query = Select maildir from mailbox where username='%s' and active=true<br />
EOF<br />
<br />
chown -R postfix:postfix sql<br />
chmod 640 sql/*<br />
<br />
<br />
At this point you should be able to start up postfix<br />
<br />
newaliases # so postfix is happy...<br />
/etc/init.d/postfix start<br />
rc-update add postfix<br />
<br />
<br />
=== Create a domain in PostfixAdmin and test ===<br />
<br />
Go to http://host.example.com/postfixadmin/<br />
<br />
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).<br />
<br />
From the machine, send a test message:<br />
<br />
sendmail -t root@example.com<br />
subject: test<br />
.<br />
^d<br />
<br />
<br />
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<br />
<br />
== Install Dovecot ==<br />
<br />
Dovecot is the POP3/IMAP server to retrieve mail.<br />
<br />
As before, we install dovecot: <br />
<br />
apk add acf-dovecot dovecot-pgsql<br />
<br />
edit /etc/dovecot/dovecot.conf<br />
<br />
<pre><br />
# Select only the protocols you wish to support - all are listed in the next line<br />
protocols = imap imaps pop pop3s<br />
log_path = /var/log/dovecot.log<br />
info_log_path = /var/log/dovecot-info.log<br />
disable_plaintext_auth = no<br />
<br />
# Authenticated IMAP<br />
ssl = yes<br />
ssl_cert_file = /etc/lighttpd/server-bundle.pem<br />
ssl_key_file = /etc/lighttpd/server-bundle.pem<br />
auth_verbose = yes<br />
auth_debug = no<br />
mail_location = maildir:/var/mail/domains/%d/%n<br />
auth default {<br />
mechanisms = plain<br />
passdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
userdb static {<br />
args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
}<br />
}<br />
</pre><br />
<br />
Be sure to replace the uid and gid with the appropriate values for the vmail user.<br />
<br />
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. <br />
<br />
Create the /etc/dovecot/dovecot-sql.conf file:<br />
<br />
driver = pgsql<br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
password_query = select username,password from mailbox where local_part = '%n' and domain = '%d'<br />
default_pass_scheme = MD5-CRYPT<br />
<br />
Again, change the password above to your postfix user password, and protect the file from prying eyes:<br />
<br />
chown root:root /etc/dovecot/dovecot-sql.conf<br />
chmod 600 /etc/dovecot/dovecot-sql.conf<br />
<br />
<br />
Start dovecot<br />
/etc/init.d/dovecot start<br />
rc-update add dovecot<br />
<br />
== Testing ==<br />
<br />
Make sure your firewall allows in ports 25(SMTP) 110 (POP3), 995 (POP3S), 143(IMAP), 993(IMAPS), or whatever subset you support. <br />
<br />
At this point, you should be able to:<br />
* Create a new domain and add users with PostfixAdmin<br />
* Send mail to those users via SMTP to port 25<br />
* Retrieve mail using the user's full email and password (e.g. username: user@example.com password: ChangeMe)<br />
<br />
== Value Add Features ==<br />
<br />
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.<br />
<br />
<br />
=== Virus Scanning ===<br />
<br />
This procedure uses clamav and the postfix content_filter mechanism to scan inbound and outbound email for viruses. Infected emails are dropped. Clean emails are tagged with a "scanned by clamav" header.<br />
<br />
<br />
* Install clamav and clamsmtp:<br />
apk add acf-clamav clamsmtp<br />
* Edit the /etc/clamav/clamd.conf file if desired (not necessary in most cases)<br />
* Edit /etc/clamsmtpd.conf and verify the following lines<br />
OutAddress: 10026<br />
Listen: 127.0.0.1:10025 <br />
Header: X-Virus-Scanned: ClamAV using ClamSMTP<br />
Action: drop<br />
User: clamav <br />
* Start the daemons<br />
rc-update add clamd<br />
rc-update add freshclam<br />
rc-update add clamsmtp<br />
/etc/init.d/clamd start<br />
/etc/init.d/freshclam start<br />
/etc/init.d/clamsmtp start<br />
* Verify clamsmtp is listening on port 10025:<br />
netstat -anp | grep clamsmtp<br />
* [http://memberwebs.com/stef/software/clamsmtp/postfix.html Following the clamsmtp instructions]<br />
** edit /etc/postfix/main.cf and add:<br />
content_filter = scan:[127.0.0.1]:10025 <br />
** edit /etc/postfix/master.cf and add<br />
# AV scan filter (used by content_filter)<br />
scan unix - - n - 16 smtp<br />
-o smtp_send_xforward_command=yes<br />
-o smtp_enforce_tls=no<br />
# For injecting mail back into postfix from the filter<br />
127.0.0.1:10026 inet n - n - 16 smtpd<br />
-o content_filter=<br />
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks<br />
-o smtpd_helo_restrictions=<br />
-o smtpd_client_restrictions=<br />
-o smtpd_sender_restrictions=<br />
-o smtpd_recipient_restrictions=permit_mynetworks,reject<br />
-o mynetworks_style=host<br />
-o smtpd_authorized_xforward_hosts=127.0.0.0/8<br />
* postfix reload<br />
* Send and email into a local virtual domain - it should have the ''X-Virus-Scanned: ClamAV using ClamSMTP'' header.<br />
<br />
<br />
<br />
<br />
=== Relay for Authenticated Users ===<br />
<br />
As configured above, the mail server accepts email from the Internet, but it does not relay email. If it is a perimeter exchanger for a protected network, then you can add the protected networks to the ''mynetworks'' configuration line in /etc/postfix/main.cf<br />
<br />
This configuration change allows ''remote'' users to authenticate against the mail server and relay through it. The rules for relaying are:<br />
* Only authenticated users can relay<br />
* Authentication Credentials must be encrypted with TLS or SSL<br />
* Allow Submission and SMTPS ports for relaying (many consumer networks block port 25 - SMTP by default)<br />
The process uses the dovecot authentication mechanism (used with IMAPS) to authenticate users before they are allowed to relay through postfix.<br />
<br />
<br />
* Edit /etc/dovecot/dovecot.conf and add:<br />
# this is for postfix SASL (authenticated users can relay through us)<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
}<br />
}<br />
* Restart dovecot<br />
/etc/init.d/dovecot restart<br />
* Edit /etc/postfix/main.cf and add:<br />
# TLS Stuff -- since we allow SASL with tls *only*, we have to set up TLS first <br />
<br />
smtpd_tls_cert_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_key_file = /etc/lighttpd/server-bundle.pem<br />
smtpd_tls_CAfile = /etc/lighttpd/ca-crt.pem<br />
# If tls_security_level is set to "encrypt", then SMTP rejects <br />
# unencrypted email (e.g. normal mail) which is bad.<br />
# By setting it to "may" you get TLS encrypted mail from google, slashdot, and other <br />
# interesting places. Check your logs to see who<br />
smtpd_tls_security_level = may<br />
# Log info about the negotiated encryption levels<br />
smtpd_tls_received_header = yes<br />
smtpd_tls_loglevel = 1<br />
<br />
# SASL - this allows senders to authenticiate themselves<br />
# This along with "permit_sasl_authenticated" in smtpd_recipient_restrictions allows relaying<br />
smtpd_sasl_type = dovecot<br />
smtpd_sasl_path = private/dovecot-auth.sock<br />
smtpd_sasl_auth_enable = yes<br />
smtpd_sasl_authenticated_header = yes<br />
smtpd_tls_auth_only = yes<br />
* 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:<br />
submission inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
smtps inet n - n - - smtpd<br />
-o smtpd_tls_security_level=encrypt<br />
-o smtpd_tls_wrappermode=yes<br />
-o smtpd_sasl_auth_enable=yes<br />
-o smtpd_client_restrictions=permit_sasl_authenticated,reject<br />
-o milter_macro_daemon_name=ORIGINATING<br />
*Verfiy submission and smtps are defined in /etc/services<br />
grep "submission\|ssmtp" /etc/services<br />
submission 587/tcp # mail message submission<br />
submission 587/udp<br />
smtps 465/tcp ssmtp # smtp protocol over TLS/SSL<br />
smtps 465/udp ssmtp<br />
* Restart postfix<br />
postfix reload<br />
<br />
At this point, you should be able to set up a mail client to relay through the server with TLS (port 587) or SSL (port 465) Note that "plain" authentication is used because the underlying link is encrypted. For example, in Thunderbird leave "secure authentication" unchecked, and choose STARTTLS (or TLS) for the connection security.<br />
<br />
<br />
=== Mailbox Quotas ===<br />
<br />
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 ''patch''. Postfix and Dovecot are both conservative systems, so if the patch isn't in the upstream source, we'll assume there's a good reason. There is a way of using quotas without patches - and it involves using dovecot's [http://wiki.dovecot.org/LDA deliver] lda for local delivery.<br />
<br />
Note: As of Jan 2010, the documention is confusing, with multiple versions of dovecot, PostfixAdmin, and Mysql referenced. These instructions apply to:<br />
* Postgresql 8.4.2 <br />
* PostfixAdmin 2.3 <br />
* Dovecot 1.2.10<br />
* Postfix 2.6.5<br />
<br />
Presumably later versions will work the same, but if not, please update the documentation and versions above.<br />
<br />
* Update /etc/dovecot.conf (old lines shown commented out):<br />
<br />
<pre><br />
# old postfix <br />
# userdb static {<br />
# args = uid=1006 gid=1006 home=/var/mail/domains/%d/%n<br />
# }<br />
<br />
# new quota support:<br />
userdb prefetch {<br />
}<br />
<br />
userdb sql {<br />
args = /etc/dovecot/dovecot-sql.conf<br />
}<br />
<br />
socket listen {<br />
client {<br />
path = /var/spool/postfix/private/dovecot-auth.sock<br />
mode = 0660<br />
user = postfix<br />
group = postfix<br />
}<br />
# These lines below are for the deliver lda<br />
master {<br />
path = /var/run/dovecot/auth-master<br />
mode = 0660<br />
user = vmail<br />
group = vmail<br />
}<br />
}<br />
}<br />
<br />
protocol imap { <br />
mail_plugins = quota imap_quota <br />
} <br />
<br />
protocol pop3 { <br />
mail_plugins = quota <br />
} <br />
<br />
dict { <br />
quotadict = pgsql:/etc/dovecot/dovecot-dict-quota.conf <br />
} <br />
<br />
plugin { <br />
quota = dict:user::proxy::quotadict <br />
} <br />
<br />
protocol lda { <br />
postmaster_address = postmaster@host.example.com<br />
mail_plugins = quota <br />
auth_socket_path = /var/run/dovecot/auth-master<br />
sendmail_path = /usr/sbin/sendmail<br />
} <br />
</pre><br />
<br />
You should already have a <tt>socket-> listen-> client</tt> section, but it is listed above to show where it goes in relationship to the <tt>socket -> listen -> master</tt> section<br />
<br />
<br />
* edit <tt>/etc/dovecot/dovecot-sql.conf</tt> and replace the user and password queries with the following (you may not have a user_query yet - add it):<br />
<br />
password_query = select username as user, password, 1006 as userdb_uid, 1006 as userdb_gid, '*:bytes=' || quota as userdb_quota_rule from mailbox where local_part = '%n' and domain = '%d'<br />
user_query = select maildir as home, 1006 as uid, 1006 as gid, '*:bytes=' || quota as quota_rule from mailbox where local_part = '%n' and domain ='%d'<br />
<br />
<br />
* create <tt>/etc/dovecot/dovecot-dict-quota.conf</tt><br />
connect = host=localhost dbname=postfix user=postfix password=********<br />
<br />
map {<br />
pattern = priv/quota/storage<br />
table = quota2<br />
username_field =username<br />
value_field = bytes<br />
}<br />
<br />
map {<br />
pattern= priv/quota/messages<br />
table = quota2<br />
username_field = username<br />
value_field = messages<br />
}<br />
<br />
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.<br />
<br />
<br />
* create a new transport for the dovecot lda. Add the following to /etc/postfix/master.cf:<br />
# The dovecot deliver lda<br />
dovecot unix - n n - - pipe<br />
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}<br />
<br />
* Edit the /etc/postfix/main.cf. Replace <br />
virtual_transport = virtual <br />
with<br />
virtual_transport = dovecot<br />
dovecot_destination_recipient_limit = 1<br />
<br />
<br />
'''TODO''' This will cause over-quota emails to bounce. Which could be a source of backscatter. We need a way of checking quota limits after RBL checking but before the message is accepted in the queue.<br />
<br />
=== WebMail (RoundCube) ===<br />
<br />
[http://roundcube.net/ RoundCube] is an "ajax /Web2.0" web-mail client. These instructions are for the Alpine Linux 1.10 repository <br />
<br />
* Add the package and related php modules:<br />
apk add roundcubemail php-xml php-openssl php-mcrypt php-gd php-iconv<br />
<br />
* link the roundcube application back into the docroot<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/host.example.com/www/roundcube<br />
<br />
* follow the instructions in /usr/share/webapps/roundcube/INSTALL:<br />
cd /usr/share/webapps/roundcube<br />
chown -R lighttpd:lighttpd temp logs<br />
<br />
su postgres<br />
createuser roundcube<br />
Shall the new role be a superuser? (y/n) n<br />
Shall the new role be allowed to create databases? (y/n) n<br />
Shall the new role be allowed to create more new roles? (y/n) y<br />
createdb -O roundcube -E UNICODE -T template0 roundcubemail<br />
psql roundcubemail<br />
roundcubemail=# ALTER USER roundcube WITH PASSWORD 'the_new_password';<br />
roundcubemail=# \c - roundcube<br />
roundcubemail=> \i /usr/share/webapps/roundcube/SQL/postgres.initial.sql<br />
roundcubemail=> \q<br />
exit<br />
<br />
* edit /etc/php/php.ini and set date.timezone to your local timezone, or to UTC<br />
<br />
* restart lighttpd to verify the new php libraries are used<br />
/etc/init.d/lighttpd restart<br />
<br />
* Point your browser to http://host.example.com/roundcube/installer<br />
* Start installation<br />
<br />
For the specific configuration parameters in the install step:<br />
<br />
{| class="wikitable"<br />
!Property<br />
!Setting<br />
|-<br />
| ''enable_spellcheck'' || disabled <br />
|-<br />
| ''identities_level'' || one identity with possibility to edit all params but not email address <br />
|-<br />
| ''log driver'' || syslog <br />
|-<br />
| ''sylog_id'' || roundcube <br />
|-<br />
| ''syslog_facility'' || mailsubsystem <br />
|-<br />
| ''db_dnsw'' || pgsql properties, as described above <br />
|-<br />
| ''imap_host'' || 127.0.0.1 <br />
|-<br />
| ''auto_create_user'' || enabled <br />
|-<br />
| ''smtp_server'' || 127.0.0.1<br />
|-<br />
| ''smtp_port'' || 25<br />
|-<br />
| ''smtp_user/smtp_pass'' || enable ''Use Current IMAP username and password for SMTP authentication''<br />
|-<br />
| ''smtp_log'' || enable (optional, but gives additional log record)<br />
|}<br />
<br />
The other items can be left at default settings, or adjusted if desired.<br />
<br />
* Follow the instructions in step 3 of the install to copy the files to the server<br />
* You should now be able to get to roundcube at http://host.example.com/roundcube<br />
<br />
<br />
<br />
<br />
After its working, the INSTALL file recommends removing the install directory. If you want to keep the installer around later, you can simply change the ownership and permissions. So do '''one''' of the following:<br />
cd /usr/share/webapps/roundcube<br />
rm -rf LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
or<br />
cd /usr/share/webapps/roundcube<br />
chown -R root:root LICENSE UPGRADING INSTALL README CHANGELOG SQL installer<br />
chmod -R 600 LICENSE UPGRADING INSTALL README CHANGELOG SQL <br />
chmod 700 SQL installer<br />
<br />
<br />
<br />
=== OpenLDAP based Address Book ===<br />
<br />
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 <br />
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 <br />
applications to inter-operate without replication, and exchange data as needed. The SQL backend uses UnixODBC to connect to PostgresSQL. <br />
<br />
* Install OpenLDAP and ODBC<br />
<br />
<pre><br />
apk add openldap libldap openldap-back-sql php-ldap unixodbc psqlodbc ca-certificates<br />
</pre><br />
<br />
'''Note''': Perhaps some packages should be installed from "edge" repository<br />
<br />
* Update "postfix" database (it will add 'id' columns to mailbox and domain tables, also will create tables and views to represent LDAP metainformation)<br />
<br />
'''Note''': These instructions are for example domain: example.com<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
ALTER TABLE domain ADD COLUMN id SERIAL; <br />
ALTER TABLE mailbox ADD COLUMN id SERIAL; <br />
<br />
CREATE TABLE ldap_entry_objclasses (<br />
entry_id integer NOT NULL,<br />
oc_name character varying(64)<br />
);<br />
<br />
CREATE TABLE ldap_oc_mappings (<br />
id integer SERIAL,<br />
name character varying(64) NOT NULL,<br />
keytbl character varying(64) NOT NULL,<br />
keycol character varying(64) NOT NULL,<br />
create_proc character varying(255),<br />
delete_proc character varying(255),<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE TABLE ldap_attr_mappings_test (<br />
id integer SERIAL,<br />
oc_map_id integer NOT NULL REFERENCES ldap_oc_mappings(id),<br />
name character varying(255) NOT NULL,<br />
sel_expr character varying(255) NOT NULL,<br />
sel_expr_u character varying(255),<br />
from_tbls character varying(255) NOT NULL,<br />
join_where character varying(255),<br />
add_proc character varying(255),<br />
delete_proc character varying(255),<br />
param_order integer NOT NULL,<br />
expect_return integer NOT NULL,<br />
PRIMARY KEY(id)<br />
);<br />
<br />
CREATE VIEW ldap_dcs AS<br />
(SELECT (domain.id + 100000) AS id, <br />
((('dc='::text || split_part((domain.domain)::text, '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part((domain.domain)::text, '.'::text, 2) = 'org'::text) THEN split_part((domain.domain)::text, '.'::text, 2) <br />
ELSE ((split_part((domain.domain)::text, '.'::text, 2) || ',dc='::text) || split_part((domain.domain)::text, '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
100000 AS parent, <br />
0 AS keyval, <br />
domain.domain<br />
FROM domain <br />
WHERE domain.domain <> 'ALL' <br />
UNION <br />
SELECT 100000 AS id, <br />
'dc=com' AS dn, <br />
1 AS oc_map_id, <br />
0 AS parent, <br />
0 AS keyval, <br />
'com' AS domain);<br />
<br />
CREATE VIEW ldap_entries AS<br />
SELECT mailbox.id, <br />
((((('cn='::text || initcap(replace(split_part((mailbox.username)::text, '@'::text, 1), '.'::text, ' '::text))) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 1)) || ',dc='::text) || <br />
CASE WHEN (split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) = 'org'::text) <br />
THEN split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) <br />
ELSE ((split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 2) || ',dc='::text) || <br />
split_part(split_part((mailbox.username)::text, '@'::text, 2), '.'::text, 3)) <br />
END) AS dn, <br />
1 AS oc_map_id, <br />
(SELECT ldap_dcs.id <br />
FROM ldap_dcs <br />
WHERE ((ldap_dcs.domain)::text = (mailbox.domain)::text)) AS parent, <br />
mailbox.id AS keyval <br />
FROM mailbox <br />
UNION <br />
SELECT ldap_dcs.id, <br />
ldap_dcs.dn, <br />
ldap_dcs.oc_map_id, <br />
ldap_dcs.parent, <br />
ldap_dcs.keyval <br />
FROM ldap_dcs;<br />
EOF<br />
</pre><br />
<br />
<br />
* Fill out LDAP tables according to following example (make sure to separate values with TABs):<br />
<br />
<pre><br />
cat - <<EOF | psql -U postgres postfix<br />
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;<br />
1 1 displayName mailbox.name \N mailbox \N \N \N 3 0<br />
2 1 mail mailbox.username \N mailbox \N \N \N 3 0<br />
3 1 cn mailbox.name \N mailbox \N \N \N 3 0<br />
4 1 userPassword '{CRYPT}'||mailbox.password \N mailbox \N \N \N 3 0<br />
\.<br />
<br />
COPY ldap_oc_mappings (id, name, keytbl, keycol, create_proc, delete_proc, expect_return) FROM stdin;<br />
1 exampleBox mailbox id \N \N 1<br />
\.<br />
EOF<br />
</pre><br />
<br />
* Check that "ldap_dcs" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_dcs' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval | domain <br />
--------+-----------------------------+-----------+--------+--------+--------------------<br />
100000 | dc=com | 1 | 0 | 0 | com<br />
100001 | dc=example,dc=com | 1 | 100000 | 0 | example.com<br />
</pre><br />
<br />
* Check that "ldap_entries" view presens something like this:<br />
<br />
<pre><br />
echo 'select * from ldap_entries' | psql -U postgres postfix<br />
</pre><br />
<br />
<pre><br />
id | dn | oc_map_id | parent | keyval <br />
--------+-------------------------------------------------------+-----------+--------+--------<br />
1 | cn=address1,dc=example,dc=com | 1 | 100001 | 1<br />
...<br />
123 | cn=address123,dc=example,dc=com | 1 | 100001 | 1<br />
100000 | dc=com | 1 | 0 | 0<br />
100001 | dc=example,dc=com | 1 | 100000 | 0<br />
</pre><br />
<br />
* Configure ODBC parameters<br />
<br />
Edit /etc/odbc.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = Connection to Postgres<br />
Driver = PostgreSQL<br />
Trace = Yes<br />
TraceFile = sql.log<br />
Database = postfix<br />
Servername = 127.0.0.1<br />
UserName =<br />
Password =<br />
Port = 5432<br />
Protocol = 6.4<br />
ReadOnly = No<br />
RowVersining = No<br />
ShowSystemTables = No<br />
ShowOidColumn = No<br />
FakeOidIndex = No<br />
ConnSettings =<br />
</pre><br />
<br />
Edit /etc/odbcinst.ini:<br />
<br />
<pre><br />
[PostgreSQL]<br />
Description = PostgreSQL driver for Linux<br />
Driver = /usr/lib/psqlodbcw.so<br />
Setup = /usr/lib/libodbcpsqlS.so<br />
FileUsage = 1<br />
</pre><br />
<br />
* Test ODBC connection<br />
<br />
<pre><br />
echo "select * from domain;" | isql PostgreSQL postgres<br />
</pre><br />
<br />
* Provide permission to certificate for LDAP server<br />
<br />
<pre><br />
chown ldap /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Edit LDAP schema<br />
<br />
Edit /etc/openldap/schema/example.com.schema:<br />
<br />
<pre><br />
attributetype ( 0.9.2342.19200300.100.1.3<br />
NAME ( 'mail' 'rfc822Mailbox' )<br />
DESC 'RFC1274: RFC822 Mailbox'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )<br />
<br />
attributetype ( 2.16.840.1.113730.3.1.241<br />
NAME 'displayName'<br />
DESC 'RFC2798: preferred name to be used when displaying entries'<br />
EQUALITY caseIgnoreMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15<br />
SINGLE-VALUE )<br />
<br />
objectclass ( 2.16.840.1.113730.3.2.2<br />
NAME 'exampleBox'<br />
DESC 'example.com mailbox'<br />
MUST ( displayName $ mail $ userPassword )<br />
)<br />
<br />
# RFC 1274 + RFC 2247<br />
attributetype ( 0.9.2342.19200300.100.1.25<br />
NAME ( 'dc' 'domainComponent' )<br />
DESC 'RFC1274/2247: domain component'<br />
EQUALITY caseIgnoreIA5Match<br />
SUBSTR caseIgnoreIA5SubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )<br />
<br />
attributetype ( 2.5.4.46 NAME 'dnQualifier'<br />
DESC 'RFC2256: DN qualifier'<br />
EQUALITY caseIgnoreMatch<br />
ORDERING caseIgnoreOrderingMatch<br />
SUBSTR caseIgnoreSubstringsMatch<br />
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )<br />
</pre><br />
<br />
* Configure LDAP server<br />
<br />
Edit /etc/openldap/slapd.conf:<br />
<br />
<pre><br />
include /etc/openldap/schema/example.com.schema<br />
pidfile /var/run/openldap/slapd.pid<br />
argsfile /var/run/openldap/slapd.args<br />
<br />
TLSCipherSuite HIGH<br />
TLSCACertificateFile /etc/lighttpd/ca-crt.pem<br />
TLSCertificateFile /etc/lighttpd/server-bundle.pem<br />
TLSCertificateKeyFile /etc/lighttpd/server-bundle.pem<br />
TLSVerifyClient never <br />
<br />
# This is needed for proper representation of MD5-CRYPT format stored in database<br />
# see more details in http://strugglers.net/~andy/blog/2010/01/23/openldap-and-md5crypt/<br />
password-hash {CRYPT}<br />
password-crypt-salt-format "$1$%.8s"<br />
<br />
loglevel stats<br />
moduleload /usr/lib/openldap/back_sql.so<br />
sizelimit 3000<br />
<br />
database sql<br />
<br />
dbname PostgreSQL<br />
dbuser postfix<br />
dbpasswd *****<br />
<br />
suffix "dc=example,dc=com"<br />
rootdn "cn=admin,dc=example,dc=com"<br />
rootpw {MD5}<Hashed password for root dn><br />
<br />
upper_func "upper"<br />
strcast_func "text"<br />
concat_pattern "?||?"<br />
has_ldapinfo_dn_ru no<br />
lastmod off<br />
<br />
access to attrs=userPassword by * auth<br />
<br />
access to * by peername.ip=127.0.0.1 read<br />
### by peername.ip=<IP>%<netmask> read<br />
### by peername.ip=<IP> read<br />
by users read<br />
</pre><br />
<br />
* Set permissions for slapd.conf<br />
<br />
<pre><br />
chown ldap:ldap /etc/openldap/slapd.conf<br />
</pre><br />
<br />
* Configure startup parameters to make sure that LDAP server start AFTER PostgreSQL and listens on localhost with clear text and public IP with SSL<br />
<br />
Edit /etc/conf.d/slapd:<br />
<br />
<pre><br />
echo rc_need="postgresql" <br />
OPTS="-h 'ldaps:// ldap://127.0.0.1'"<br />
</pre><br />
<br />
* Start LDAP server<br />
<br />
<pre><br />
rc-update add slapd default<br />
/etc/init.d/slapd start<br />
</pre><br />
<br />
* Configure LDAP client utilities<br />
<br />
Edit /etc/openldap/ldap.conf<br />
<br />
<pre><br />
BASE dc=example,dc=com<br />
URI ldaps://host.example.com<br />
<br />
TLS_CACERT /etc/lighttpd/ca-crt.pem<br />
TLS_CERT /etc/lighttpd/server-bundle.pem<br />
TLS_KEY /etc/lighttpd/server-bundle.pem<br />
</pre><br />
<br />
* Test LDAP server<br />
<br />
<pre><br />
ldapsearch -z 3<br />
ldapsearch -z 3 -x -W -D cn=admin,dc=example,dc=com<br />
ldapsearch -z 3 -x -W -D cn=address1,dc=example,dc=com<br />
</pre><br />
<br />
* Configure RoundCube webmail for email lookups<br />
<br />
Edit /usr/share/webapps/roundcube/config/main.inc.php:<br />
<br />
<pre><br />
$rcmail_config['ldap_debug'] = false;<br />
...<br />
$rcmail_config['address_book_type'] = 'ldap';<br />
<br />
$rcmail_config['ldap_public']['example.com'] = array(<br />
'name' => 'example.com',<br />
'hosts' => array('127.0.0.1'),<br />
'port' => 389,<br />
'use_tls' => false,<br />
'user_specific' => false,<br />
'base_dn' => 'dc=example,dc=com',<br />
'bind_dn' => '',<br />
'bind_pass' => '',<br />
'writable' => false,<br />
'LDAP_Object_Classes' => array("top", "exmpleBox"),<br />
'required_fields' => array("cn", "sn", "mail"),<br />
'LDAP_rdn' => 'mail',<br />
'ldap_version' => 3,<br />
'search_fields' => array('mail', 'cn', 'sn', 'givenName'),<br />
'name_field' => 'cn',<br />
'email_field' => 'mail',<br />
'surname_field' => 'sn',<br />
'firstname_field' => 'gn',<br />
'sort' => 'cn',<br />
'scope' => 'sub',<br />
'filter' => '(objectClass=*)', // Construct here any filter you need<br />
'fuzzy_search' => true);<br />
<br />
$rcmail_config['autocomplete_addressbooks'] = array('example.com');<br />
</pre><br />
<br />
<br />
== log rotation ==<br />
<br />
Ensure the busybox cron service is started and is configured to auto-start:<br />
<br />
/etc/init.d/cron start<br />
rc-update add cron default<br />
<br />
Add log rotate:<br />
<br />
apk add logrotate<br />
<br />
Edit ''/etc/logrotate.conf'' as desired, but the defaults should be sufficient for most people.<br />
<br />
== Configure DNS ==<br />
<br />
This server hosts three separate web applications, and these can be handled as three different 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):<br />
<br />
* ACF - Alpine Configuration Framework for managing the server<br />
* PostfixAdmin - for managing the postfix installation<br />
* RoundCube - for accessing individual mailboxes<br />
<br />
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 A records.<br />
<br />
Then, configure lighttpd to handle the three separate domains by editing /etc/lighttpd/lighttpd.conf:<br />
<br />
<pre><br />
$HTTP["host"] == "ACF_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ACF_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "POSTFIXADMIN_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/POSTFIXADMIN_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
<br />
$HTTP["host"] == "ROUNDCUBE_DOMAIN" {<br />
simple-vhost.server-root = "/var/www/domains/"<br />
simple-vhost.default-host = "/ROUNDCUBE_DOMAIN/"<br />
simple-vhost.document-root = "www/"<br />
}<br />
</pre><br />
<br />
And, then link the appropriate www directories.<br />
<pre><br />
mkdir -p /var/www/domains/ACF_DOMAIN<br />
ln -s /usr/share/acf/www /var/www/domains/ACF_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/POSTFIXADMIN_DOMAIN<br />
ln -s /var/www/domains/host.example.com/www/postfixadmin /var/www/domains/POSTFIXADMIN_DOMAIN/www<br />
<br />
mkdir -p /var/www/domains/ROUNDCUBE_DOMAIN<br />
ln -s /usr/share/webapps/roundcube /var/www/domains/ROUNDCUBE_DOMAIN/www<br />
</pre></div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Setting_up_Satellite_Internet_Connection&diff=2098Setting up Satellite Internet Connection2008-01-29T07:55:34Z<p>Iilluzion: /* Conclusion */</p>
<hr />
<div>= Satellite Internet Connection HOW-TO =<br />
<br />
== Introduction ==<br />
<br />
This document briefly explains Satellite technology, how it works, what do you need, configuration and how to sharing it between several clients. So the main focus is the Internet connection, satellite TV is not reviewed. <br />
<br />
== How does it work? ==<br />
<br />
So first we make the request (using land Internet connection) to the Sat-Server usually via a tunnel, after it will retrieve out info from Internet and it will send it to Satellite; in the end we would receive data from the it to our home using a parabolic antenna and a Sat Card. <br />
<br />
Satellite works very well with protocols, which have a little request data and a much bigger answer size. Although, a big time of answer is the biggest problem of satellite connection that may prevent using interactive services such as VoIP. The delay of answer may be considered basing on that a typical Sat distance is like 36.000 km, so an average overall delay time is 300-400 ms. <br />
<br />
To install the little satellite system we need:<br />
<br />
* DVB-S Card<br />
* Parabolic Antenna (Satellite Dish)<br />
* LNB Digital Converter <br />
<br />
== Technical Information ==<br />
<br />
A satellite link as a classical Wireless link is very different from Wired link. It may cause some additional problems to solve, such as reachability, privacy problems and so on. Also there could be weather problems, particularly in snow or rain conditions. <br />
<br />
=== Antenna / Converter ===<br />
<br />
A parabolic antenna gives a very high gain in RX. A frequency that is being received from the satellite transponder is from 11GHz up to 12.7 GHz. The Digital Converter transforms it to 1-2 GHz and send signal to the DVB-S card receiver through the coax cable up to 30-40m. This documents assumes that your parabolic antenna is properly mounted and calibrated as well as proper converter (usually Ku-band) is used.<br />
<br />
=== DVB-S Receiver Card === <br />
<br />
DVB-S card receives analog signals via coax cable and converts it to digital signals pretty like Ethernet card, after that the OS transforms it to a TCP/IP packets.<br />
<br />
== DVB Setup ==<br />
<br />
'''1. Install DVB-S Card and check if system recognized it'''<br />
<br />
Please note, that in most cases you need PCI version 2.1 or higher (check DVB card specifications). In practice it is Pentium-III or later systems.<br />
<br />
# lspci | grep -i "multimedia controller"<br />
<br />
'''2. Make sure that kernel modules are loaded'''<br />
<br />
You have to use Alpine 1.7.10 release or higher that should load appropriate kernel modules for DVB card on startup. You may check if DVB devices are installed. <br />
<br />
# ls -la /dev/dvb*<br />
<br />
'''3. Install LinuxTV Applications'''<br />
<br />
# apk_add linuxtv-dvb-apps<br />
<br />
'''4. Create and edit file ''channels.conf'''''<br />
<br />
This file contains settings for each Satellite you are using. For example the satellite ''Sirius-4 Nordic Beam'' has the following parameters: Freq - 12322Mhz, Polarization - vertical, Symbol Rate - 27.654711Ms/s, FEC -7/8. <br />
<br />
Anyway, all parameters you have to receive from ISP or find in the Internet. Please look at [http://www.sat2k.com/ivs.htm Satellite Parameters] and [http://www.ses-sirius.com/english/ SES SIRIUS]. <br />
<br />
The following example is for "Sirius-4 Nordic Beam":<br />
<br />
# echo "Sirius4-Nord:12322:v:0:27500:0:0:0" >> /etc/channels.conf<br />
<br />
'''5. Tune DVB Receiver'''<br />
<br />
Check configured channels:<br />
<br />
# szap -c /etc/channels.conf -q<br />
<br />
Tune the channel number 001:<br />
<br />
# szap -c /etc/channels.conf -n 1<br />
<br />
In some cases you may need to run this command permanently in background because of a bug in kernel modules for some dvb cards.<br />
<br />
Option A:<br />
<br />
# szap -c /etc/channels.conf -n 1 > /dev/null 2>&1 &<br />
<br />
Option B:<br />
<br />
# start-stop-daemon --start --background --exec /usr/bin/szap -- -c /etc/channels.conf -n 1<br />
<br />
'''6. Set up DVB network interface'''<br />
<br />
Your ISP provides you the PID, which is used for select a transmission between many signal from same frequency.<br />
<br />
# dvbnet -a 0 -p $PID<br />
<br />
# ifconfig dvb0_0 hw ether $MAC<br />
# ifconfig dvb0_0 $IP netmask 255.255.255.255 up<br />
<br />
Here $IP is any IP address, which does not match with any other adrres in your network. The $MAC you specify here is usually the MAC address of your DVB card, in some cases ISP calculates MAC address for you. In any case ISP sends data only for registered MAC addresses.<br />
<br />
Due to nature of satellite connection, the dvb interface receives packets, which have been originated from other sources, actually ether from land internet connection interface or, in most cases, from virtual tunnel device. So in order to allow receiving such packets the source validation should be disabled on dvb0_0 interface. <br />
<br />
# echo "0" > /proc/sys/net/ipv4/conf/dvb0_0/rp_filter<br />
<br />
Another way to achieve that is to allow the shorewall to control that using ROUTE_FILTER and routefilter parameters.<br />
<br />
'''7. Test if satellite interface is receiving data'''<br />
<br />
You should see many packets for other clients of your ISP.<br />
<br />
# apk_add tcpdump<br />
# tcpdump -n -i dvb0_0<br />
<br />
== Authentication with ISP ==<br />
<br />
Before you receive your data via satellite your ISP should authenticate you as their registered client. There are several common techniques could be used:<br />
<br />
* Some ISPs use the "Proxy Authentication", when you used their proxy, you also need to give login and password to continue the request. Once done, the ISP use your IP address to calculate your MAC address, to which send the answer. <br />
<br />
* Some other ISPs require you make a VPN connection (using your login and password) first, then they will control your registration account (where they retrieve your MAC address) and will send data to your card (your MAC address). <br />
<br />
* If you have static public IP, perhaps, the most convenient way is when ISPs suggest making a GRE/IPIP tunnel, which is used to sent authenticated requests to ISP satellite server. Consequently ISP sends back answers via satellite you are connected to.<br />
<br />
Here is an example of setting up GRE tunnel with a ISP:<br />
<br />
'''1. Make static routes'''<br />
<br />
All queries to DNS servers of your land ISP should go via land line.<br />
<br />
# route add $DNS1 gw $DEFAULT_LAND_GATEWAY<br />
# route add $DNS2 gw $DEFAULT_LAND_GATEWAY<br />
<br />
GRE packets should always go via land default gateway. <br />
<br />
# route add $SAT_ISP_GRE_IP gw $DEFAULT_LAND_GATEWAY<br />
<br />
It is assumed that $DEFAULT_LAND_GATEWAY is default gateway given by the land ISP, $DNSx are your DNS servers provided by the land ISP and $SAT_ISP_GRE_IP is remote IP of GRE tunnel of the satellite ISP.<br />
<br />
Changes of default route will be made after a tunnel interface is created.<br />
<br />
'''2. Make GRE tunnel and setup tunnel interface'''<br />
<br />
# apk_add iproute2<br />
<br />
# modprobe ip_gre<br />
# modprobe tun<br />
<br />
# ip tunnel add tun0 mode gre local $MY_STATIC_IP remote $SAT_ISP_GRE_IP ttl 250<br />
# ifconfig tun0 $LOCAL_TUN_IP pointopoint $REMOTE_TUN_IP up<br />
<br />
Parameters of a tunnel such as $SAT_ISP_GRE_IP, $LOCAL_TUN_IP, $REMOTE_TUN_IP are provided by the satellite ISP.<br />
<br />
Now make new default route that goes via tunnel interface. So most requests will go via GRE tunnel to satellite ISP with source IP as $LOCAL_TUN_IP. Answers expected via dvb interface for destination IP as $LOCAL_TUN_IP.<br />
<br />
# route del default<br />
# route add default dev tun0<br />
<br />
'''3. Test satellite internet connectivity<br />
<br />
# ping wiki.alpinelinux.org<br />
<br />
# tcpdump -n -i tun0<br />
# tcpdump -n -i dvb0_0 host $LOCAL_TUN_IP<br />
<br />
== Sharing Satellite Internet Connection ==<br />
<br />
It is assumed that we need to share the satellite internet with clients in a local network that already is connected via second Ethernet interface to satellite internet machine. This requires enabling IP forwarding, set up simple SNAT masquerading and traffic filtering rules. The easiest way is to use Shorewall for that purpose.<br />
<br />
''' 1. Install shorewall'''<br />
<br />
# apk_add shorewall<br />
<br />
'''2. Set up ''shorewall.conf'''''<br />
<br />
IP_FORWARDING=yes<br />
ROUTE_FILTER=No<br />
CLAMPMSS=Yes # See '''RFC2923'''<br />
<br />
'''3. Set up ''zones'''''<br />
<br />
inet ipv4<br />
loc ipv4<br />
tun ipv4<br />
dvb ipv4<br />
<br />
'''4. Set up ''interfaces'''''<br />
<br />
loc eth1 detect routefilter<br />
inet eth0 detect norfc1918,routefilter<br />
tun tun0 - norfc1918,routefilter<br />
dvb dvb0_0 - <br />
<br />
'''5. Set up ''policy'''''<br />
<br />
loc all REJECT info<br />
dvb all REJECT info<br />
all all DROP info<br />
<br />
'''6. Set up SNAT masquerading in ''masq'''''<br />
<br />
tun0 eth1<br />
<br />
'''7. Set up ''params'''''<br />
<br />
#This IP address are provided by the satellite ISP<br />
SAT_ISP_GRE_IP=<br />
LOCAL_TUN_IP=<br />
<br />
'''7. Set up ''rules'''''<br />
<br />
SECTION ESTABLISHED<br />
REJECT dvb fw:!$LOCAL_TUN_IP<br />
<br />
SECTION RELATED<br />
REJECT dvb fw:!$LOCAL_TUN_IP<br />
<br />
SECTION NEW<br />
DNS/ACCEPT fw inet<br />
Ping/ACCEPT fw inet<br />
<br />
#Allow Web/FTP queries via GRE tunnel to ISP<br />
# Answers come as RELATED/ESTABLISHED traffic via DVB<br />
Web/ACCEPT fw tun<br />
Web/ACCEPT loc tun <br />
FTP/ACCEPT fw tun <br />
FTP/ACCEPT loc tun <br />
Ping/ACCEPT fw tun <br />
Ping/ACCEPT pr tun<br />
<br />
'''8. Set up ''tunnels'''''<br />
<br />
gre inet $SAT_ISP_GRE_IP<br />
<br />
== Conclusion ==<br />
<br />
This document reviewed just basic ideas how to setup and share satellite internet connection. Further releases of Alpine Linux will include start up and configuration scripts (see Mailing Lists). Note, that more advanced traffic routing is beyond of scope of this document.<br />
<br />
Another advanced topic that is beyond of scope is how to use remote proxy/VPN services to protect/encrypt your Satellite traffic against grabbers. This configuration may protect HTTP/POP3 and other types of data against unauthorized grabbing with attempts to sniff personal mail, electronic addresses and other information.<br />
<br />
== More information ==<br />
<br />
[http://en.wikipedia.org/wiki/Satellite_dish Satellite Dish]<br />
[http://en.wikipedia.org/wiki/Ku_band Ku-band]<br />
[http://www.linuxtv.org/wiki LinuxTV Wiki]<br />
[http://www.hack-it.net/How-To/Sat-HOWTO.html Satellite HOW-TO]<br />
[http://tier.cs.berkeley.edu/wiki/HOWTO:IPTunnelling IP Tunnelling HOW-TO]<br />
[http://www.sat2k.com/ivs.htm Satellite Parameters] <br />
[http://www.ses-sirius.com/english/ SES SIRIUS]<br />
[http://www.shorewall.net Shorewall]<br />
[http://http://lartc.org/howto Linux Advanced Routing & Traffic Control HOWTO]</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Setting_up_Satellite_Internet_Connection&diff=2097Setting up Satellite Internet Connection2008-01-28T10:47:42Z<p>Iilluzion: /* DVB Setup */</p>
<hr />
<div>= Satellite Internet Connection HOW-TO =<br />
<br />
== Introduction ==<br />
<br />
This document briefly explains Satellite technology, how it works, what do you need, configuration and how to sharing it between several clients. So the main focus is the Internet connection, satellite TV is not reviewed. <br />
<br />
== How does it work? ==<br />
<br />
So first we make the request (using land Internet connection) to the Sat-Server usually via a tunnel, after it will retrieve out info from Internet and it will send it to Satellite; in the end we would receive data from the it to our home using a parabolic antenna and a Sat Card. <br />
<br />
Satellite works very well with protocols, which have a little request data and a much bigger answer size. Although, a big time of answer is the biggest problem of satellite connection that may prevent using interactive services such as VoIP. The delay of answer may be considered basing on that a typical Sat distance is like 36.000 km, so an average overall delay time is 300-400 ms. <br />
<br />
To install the little satellite system we need:<br />
<br />
* DVB-S Card<br />
* Parabolic Antenna (Satellite Dish)<br />
* LNB Digital Converter <br />
<br />
== Technical Information ==<br />
<br />
A satellite link as a classical Wireless link is very different from Wired link. It may cause some additional problems to solve, such as reachability, privacy problems and so on. Also there could be weather problems, particularly in snow or rain conditions. <br />
<br />
=== Antenna / Converter ===<br />
<br />
A parabolic antenna gives a very high gain in RX. A frequency that is being received from the satellite transponder is from 11GHz up to 12.7 GHz. The Digital Converter transforms it to 1-2 GHz and send signal to the DVB-S card receiver through the coax cable up to 30-40m. This documents assumes that your parabolic antenna is properly mounted and calibrated as well as proper converter (usually Ku-band) is used.<br />
<br />
=== DVB-S Receiver Card === <br />
<br />
DVB-S card receives analog signals via coax cable and converts it to digital signals pretty like Ethernet card, after that the OS transforms it to a TCP/IP packets.<br />
<br />
== DVB Setup ==<br />
<br />
'''1. Install DVB-S Card and check if system recognized it'''<br />
<br />
Please note, that in most cases you need PCI version 2.1 or higher (check DVB card specifications). In practice it is Pentium-III or later systems.<br />
<br />
# lspci | grep -i "multimedia controller"<br />
<br />
'''2. Make sure that kernel modules are loaded'''<br />
<br />
You have to use Alpine 1.7.10 release or higher that should load appropriate kernel modules for DVB card on startup. You may check if DVB devices are installed. <br />
<br />
# ls -la /dev/dvb*<br />
<br />
'''3. Install LinuxTV Applications'''<br />
<br />
# apk_add linuxtv-dvb-apps<br />
<br />
'''4. Create and edit file ''channels.conf'''''<br />
<br />
This file contains settings for each Satellite you are using. For example the satellite ''Sirius-4 Nordic Beam'' has the following parameters: Freq - 12322Mhz, Polarization - vertical, Symbol Rate - 27.654711Ms/s, FEC -7/8. <br />
<br />
Anyway, all parameters you have to receive from ISP or find in the Internet. Please look at [http://www.sat2k.com/ivs.htm Satellite Parameters] and [http://www.ses-sirius.com/english/ SES SIRIUS]. <br />
<br />
The following example is for "Sirius-4 Nordic Beam":<br />
<br />
# echo "Sirius4-Nord:12322:v:0:27500:0:0:0" >> /etc/channels.conf<br />
<br />
'''5. Tune DVB Receiver'''<br />
<br />
Check configured channels:<br />
<br />
# szap -c /etc/channels.conf -q<br />
<br />
Tune the channel number 001:<br />
<br />
# szap -c /etc/channels.conf -n 1<br />
<br />
In some cases you may need to run this command permanently in background because of a bug in kernel modules for some dvb cards.<br />
<br />
Option A:<br />
<br />
# szap -c /etc/channels.conf -n 1 > /dev/null 2>&1 &<br />
<br />
Option B:<br />
<br />
# start-stop-daemon --start --background --exec /usr/bin/szap -- -c /etc/channels.conf -n 1<br />
<br />
'''6. Set up DVB network interface'''<br />
<br />
Your ISP provides you the PID, which is used for select a transmission between many signal from same frequency.<br />
<br />
# dvbnet -a 0 -p $PID<br />
<br />
# ifconfig dvb0_0 hw ether $MAC<br />
# ifconfig dvb0_0 $IP netmask 255.255.255.255 up<br />
<br />
Here $IP is any IP address, which does not match with any other adrres in your network. The $MAC you specify here is usually the MAC address of your DVB card, in some cases ISP calculates MAC address for you. In any case ISP sends data only for registered MAC addresses.<br />
<br />
Due to nature of satellite connection, the dvb interface receives packets, which have been originated from other sources, actually ether from land internet connection interface or, in most cases, from virtual tunnel device. So in order to allow receiving such packets the source validation should be disabled on dvb0_0 interface. <br />
<br />
# echo "0" > /proc/sys/net/ipv4/conf/dvb0_0/rp_filter<br />
<br />
Another way to achieve that is to allow the shorewall to control that using ROUTE_FILTER and routefilter parameters.<br />
<br />
'''7. Test if satellite interface is receiving data'''<br />
<br />
You should see many packets for other clients of your ISP.<br />
<br />
# apk_add tcpdump<br />
# tcpdump -n -i dvb0_0<br />
<br />
== Authentication with ISP ==<br />
<br />
Before you receive your data via satellite your ISP should authenticate you as their registered client. There are several common techniques could be used:<br />
<br />
* Some ISPs use the "Proxy Authentication", when you used their proxy, you also need to give login and password to continue the request. Once done, the ISP use your IP address to calculate your MAC address, to which send the answer. <br />
<br />
* Some other ISPs require you make a VPN connection (using your login and password) first, then they will control your registration account (where they retrieve your MAC address) and will send data to your card (your MAC address). <br />
<br />
* If you have static public IP, perhaps, the most convenient way is when ISPs suggest making a GRE/IPIP tunnel, which is used to sent authenticated requests to ISP satellite server. Consequently ISP sends back answers via satellite you are connected to.<br />
<br />
Here is an example of setting up GRE tunnel with a ISP:<br />
<br />
'''1. Make static routes'''<br />
<br />
All queries to DNS servers of your land ISP should go via land line.<br />
<br />
# route add $DNS1 gw $DEFAULT_LAND_GATEWAY<br />
# route add $DNS2 gw $DEFAULT_LAND_GATEWAY<br />
<br />
GRE packets should always go via land default gateway. <br />
<br />
# route add $SAT_ISP_GRE_IP gw $DEFAULT_LAND_GATEWAY<br />
<br />
It is assumed that $DEFAULT_LAND_GATEWAY is default gateway given by the land ISP, $DNSx are your DNS servers provided by the land ISP and $SAT_ISP_GRE_IP is remote IP of GRE tunnel of the satellite ISP.<br />
<br />
Changes of default route will be made after a tunnel interface is created.<br />
<br />
'''2. Make GRE tunnel and setup tunnel interface'''<br />
<br />
# apk_add iproute2<br />
<br />
# modprobe ip_gre<br />
# modprobe tun<br />
<br />
# ip tunnel add tun0 mode gre local $MY_STATIC_IP remote $SAT_ISP_GRE_IP ttl 250<br />
# ifconfig tun0 $LOCAL_TUN_IP pointopoint $REMOTE_TUN_IP up<br />
<br />
Parameters of a tunnel such as $SAT_ISP_GRE_IP, $LOCAL_TUN_IP, $REMOTE_TUN_IP are provided by the satellite ISP.<br />
<br />
Now make new default route that goes via tunnel interface. So most requests will go via GRE tunnel to satellite ISP with source IP as $LOCAL_TUN_IP. Answers expected via dvb interface for destination IP as $LOCAL_TUN_IP.<br />
<br />
# route del default<br />
# route add default dev tun0<br />
<br />
'''3. Test satellite internet connectivity<br />
<br />
# ping wiki.alpinelinux.org<br />
<br />
# tcpdump -n -i tun0<br />
# tcpdump -n -i dvb0_0 host $LOCAL_TUN_IP<br />
<br />
== Sharing Satellite Internet Connection ==<br />
<br />
It is assumed that we need to share the satellite internet with clients in a local network that already is connected via second Ethernet interface to satellite internet machine. This requires enabling IP forwarding, set up simple SNAT masquerading and traffic filtering rules. The easiest way is to use Shorewall for that purpose.<br />
<br />
''' 1. Install shorewall'''<br />
<br />
# apk_add shorewall<br />
<br />
'''2. Set up ''shorewall.conf'''''<br />
<br />
IP_FORWARDING=yes<br />
ROUTE_FILTER=No<br />
CLAMPMSS=Yes # See '''RFC2923'''<br />
<br />
'''3. Set up ''zones'''''<br />
<br />
inet ipv4<br />
loc ipv4<br />
tun ipv4<br />
dvb ipv4<br />
<br />
'''4. Set up ''interfaces'''''<br />
<br />
loc eth1 detect routefilter<br />
inet eth0 detect norfc1918,routefilter<br />
tun tun0 - norfc1918,routefilter<br />
dvb dvb0_0 - <br />
<br />
'''5. Set up ''policy'''''<br />
<br />
loc all REJECT info<br />
dvb all REJECT info<br />
all all DROP info<br />
<br />
'''6. Set up SNAT masquerading in ''masq'''''<br />
<br />
tun0 eth1<br />
<br />
'''7. Set up ''params'''''<br />
<br />
#This IP address are provided by the satellite ISP<br />
SAT_ISP_GRE_IP=<br />
LOCAL_TUN_IP=<br />
<br />
'''7. Set up ''rules'''''<br />
<br />
SECTION ESTABLISHED<br />
REJECT dvb fw:!$LOCAL_TUN_IP<br />
<br />
SECTION RELATED<br />
REJECT dvb fw:!$LOCAL_TUN_IP<br />
<br />
SECTION NEW<br />
DNS/ACCEPT fw inet<br />
Ping/ACCEPT fw inet<br />
<br />
#Allow Web/FTP queries via GRE tunnel to ISP<br />
# Answers come as RELATED/ESTABLISHED traffic via DVB<br />
Web/ACCEPT fw tun<br />
Web/ACCEPT loc tun <br />
FTP/ACCEPT fw tun <br />
FTP/ACCEPT loc tun <br />
Ping/ACCEPT fw tun <br />
Ping/ACCEPT pr tun<br />
<br />
'''8. Set up ''tunnels'''''<br />
<br />
gre inet $SAT_ISP_GRE_IP<br />
<br />
== Conclusion ==<br />
<br />
This document reviewed just basic ideas how to setup and share satellite internet connection. Further releases of Alpine Linux will include start up and configuration scripts (see Mailing Lists). Note, that more advanced traffic routing is beyond of scope of this document.<br />
<br />
== More information ==<br />
<br />
[http://en.wikipedia.org/wiki/Satellite_dish Satellite Dish]<br />
[http://en.wikipedia.org/wiki/Ku_band Ku-band]<br />
[http://www.linuxtv.org/wiki LinuxTV Wiki]<br />
[http://www.hack-it.net/How-To/Sat-HOWTO.html Satellite HOW-TO]<br />
[http://tier.cs.berkeley.edu/wiki/HOWTO:IPTunnelling IP Tunnelling HOW-TO]<br />
[http://www.sat2k.com/ivs.htm Satellite Parameters] <br />
[http://www.ses-sirius.com/english/ SES SIRIUS]<br />
[http://www.shorewall.net Shorewall]<br />
[http://http://lartc.org/howto Linux Advanced Routing & Traffic Control HOWTO]</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Setting_up_Satellite_Internet_Connection&diff=2096Setting up Satellite Internet Connection2008-01-26T08:09:58Z<p>Iilluzion: </p>
<hr />
<div>= Satellite Internet Connection HOW-TO =<br />
<br />
== Introduction ==<br />
<br />
This document briefly explains Satellite technology, how it works, what do you need, configuration and how to sharing it between several clients. So the main focus is the Internet connection, satellite TV is not reviewed. <br />
<br />
== How does it work? ==<br />
<br />
So first we make the request (using land Internet connection) to the Sat-Server usually via a tunnel, after it will retrieve out info from Internet and it will send it to Satellite; in the end we would receive data from the it to our home using a parabolic antenna and a Sat Card. <br />
<br />
Satellite works very well with protocols, which have a little request data and a much bigger answer size. Although, a big time of answer is the biggest problem of satellite connection that may prevent using interactive services such as VoIP. The delay of answer may be considered basing on that a typical Sat distance is like 36.000 km, so an average overall delay time is 300-400 ms. <br />
<br />
To install the little satellite system we need:<br />
<br />
* DVB-S Card<br />
* Parabolic Antenna (Satellite Dish)<br />
* LNB Digital Converter <br />
<br />
== Technical Information ==<br />
<br />
A satellite link as a classical Wireless link is very different from Wired link. It may cause some additional problems to solve, such as reachability, privacy problems and so on. Also there could be weather problems, particularly in snow or rain conditions. <br />
<br />
=== Antenna / Converter ===<br />
<br />
A parabolic antenna gives a very high gain in RX. A frequency that is being received from the satellite transponder is from 11GHz up to 12.7 GHz. The Digital Converter transforms it to 1-2 GHz and send signal to the DVB-S card receiver through the coax cable up to 30-40m. This documents assumes that your parabolic antenna is properly mounted and calibrated as well as proper converter (usually Ku-band) is used.<br />
<br />
=== DVB-S Receiver Card === <br />
<br />
DVB-S card receives analog signals via coax cable and converts it to digital signals pretty like Ethernet card, after that the OS transforms it to a TCP/IP packets.<br />
<br />
== DVB Setup ==<br />
<br />
'''1. Install DVB-S Card and check if system recognized it'''<br />
<br />
Please note, that in most cases you need PCI version 2.1 or higher (check DVB card specifications). In practice it is Pentium-III or later systems.<br />
<br />
# lspci | grep -i "multimedia controller"<br />
<br />
'''2. Make sure that kernel modules are loaded'''<br />
<br />
You have to use Alpine 1.7.10 release or higher that should load appropriate kernel modules for DVB card on startup. You may check if DVB devices are installed. <br />
<br />
# ls -la /dev/dvb*<br />
<br />
'''3. Install LinuxTV Applications'''<br />
<br />
# apk_add linuxtv-dvb-apps<br />
<br />
'''4. Create and edit file ''channels.conf'''''<br />
<br />
This file contains settings for each Satellite you are using. For example the satellite ''Sirius-4 Nordic Beam'' has the following parameters: Freq - 12322Mhz, Polarization - vertical, Symbol Rate - 27.654711Ms/s, FEC -7/8. <br />
<br />
Anyway, all parameters you have to receive from ISP or find in the Internet. Please look at [http://www.sat2k.com/ivs.htm Satellite Parameters] and [http://www.ses-sirius.com/english/ SES SIRIUS]. <br />
<br />
The following example is for "Sirius-4 Nordic Beam":<br />
<br />
# echo "Sirius4-Nord:12322:v:0:27654:0:0:0" >> /etc/channels.conf<br />
<br />
'''5. Tune DVB Receiver'''<br />
<br />
Check configured channels:<br />
<br />
# szap -c /etc/channels.conf -q<br />
<br />
Tune the channel number 001:<br />
<br />
# szap -c /etc/channels.conf -n 1<br />
<br />
In some cases you may need to run this command permanently in background because of a bug in kernel modules for some dvb cards.<br />
<br />
Option A:<br />
<br />
# szap -c /etc/channels.conf -n 1 > /dev/null 2>&1 &<br />
<br />
Option B:<br />
<br />
# start-stop-daemon --start --background --exec /usr/bin/szap -- -c /etc/channels.conf -n 1<br />
<br />
'''6. Set up DVB network interface'''<br />
<br />
Your ISP provides you the PID, which is used for select a transmission between many signal from same frequency.<br />
<br />
# dvbnet -a 0 -p $PID<br />
<br />
# ifconfig dvb0_0 hw ether $MAC<br />
# ifconfig dvb0_0 $IP netmask 255.255.255.255 up<br />
<br />
Here $IP is any IP address, which does not match with any other adrres in your network. The $MAC you specify here is usually the MAC address of your DVB card, in some cases ISP calculates MAC address for you. In any case ISP sends data only for registered MAC addresses.<br />
<br />
Due to nature of satellite connection, the dvb interface receives packets, which have been originated from other sources, actually ether from land internet connection interface or, in most cases, from virtual tunnel device. So in order to allow receiving such packets the source validation should be disabled on dvb0_0 interface. <br />
<br />
# echo "0" > /proc/sys/net/ipv4/conf/dvb0_0/rp_filter<br />
<br />
Another way to achieve that is to allow the shorewall to control that using ROUTE_FILTER and routefilter parameters.<br />
<br />
'''7. Test if satellite interface is receiving data'''<br />
<br />
You should see many packets for other clients of your ISP.<br />
<br />
# apk_add tcpdump<br />
# tcpdump -n -i dvb0_0<br />
<br />
== Authentication with ISP ==<br />
<br />
Before you receive your data via satellite your ISP should authenticate you as their registered client. There are several common techniques could be used:<br />
<br />
* Some ISPs use the "Proxy Authentication", when you used their proxy, you also need to give login and password to continue the request. Once done, the ISP use your IP address to calculate your MAC address, to which send the answer. <br />
<br />
* Some other ISPs require you make a VPN connection (using your login and password) first, then they will control your registration account (where they retrieve your MAC address) and will send data to your card (your MAC address). <br />
<br />
* If you have static public IP, perhaps, the most convenient way is when ISPs suggest making a GRE/IPIP tunnel, which is used to sent authenticated requests to ISP satellite server. Consequently ISP sends back answers via satellite you are connected to.<br />
<br />
Here is an example of setting up GRE tunnel with a ISP:<br />
<br />
'''1. Make static routes'''<br />
<br />
All queries to DNS servers of your land ISP should go via land line.<br />
<br />
# route add $DNS1 gw $DEFAULT_LAND_GATEWAY<br />
# route add $DNS2 gw $DEFAULT_LAND_GATEWAY<br />
<br />
GRE packets should always go via land default gateway. <br />
<br />
# route add $SAT_ISP_GRE_IP gw $DEFAULT_LAND_GATEWAY<br />
<br />
It is assumed that $DEFAULT_LAND_GATEWAY is default gateway given by the land ISP, $DNSx are your DNS servers provided by the land ISP and $SAT_ISP_GRE_IP is remote IP of GRE tunnel of the satellite ISP.<br />
<br />
Changes of default route will be made after a tunnel interface is created.<br />
<br />
'''2. Make GRE tunnel and setup tunnel interface'''<br />
<br />
# apk_add iproute2<br />
<br />
# modprobe ip_gre<br />
# modprobe tun<br />
<br />
# ip tunnel add tun0 mode gre local $MY_STATIC_IP remote $SAT_ISP_GRE_IP ttl 250<br />
# ifconfig tun0 $LOCAL_TUN_IP pointopoint $REMOTE_TUN_IP up<br />
<br />
Parameters of a tunnel such as $SAT_ISP_GRE_IP, $LOCAL_TUN_IP, $REMOTE_TUN_IP are provided by the satellite ISP.<br />
<br />
Now make new default route that goes via tunnel interface. So most requests will go via GRE tunnel to satellite ISP with source IP as $LOCAL_TUN_IP. Answers expected via dvb interface for destination IP as $LOCAL_TUN_IP.<br />
<br />
# route del default<br />
# route add default dev tun0<br />
<br />
'''3. Test satellite internet connectivity<br />
<br />
# ping wiki.alpinelinux.org<br />
<br />
# tcpdump -n -i tun0<br />
# tcpdump -n -i dvb0_0 host $LOCAL_TUN_IP<br />
<br />
== Sharing Satellite Internet Connection ==<br />
<br />
It is assumed that we need to share the satellite internet with clients in a local network that already is connected via second Ethernet interface to satellite internet machine. This requires enabling IP forwarding, set up simple SNAT masquerading and traffic filtering rules. The easiest way is to use Shorewall for that purpose.<br />
<br />
''' 1. Install shorewall'''<br />
<br />
# apk_add shorewall<br />
<br />
'''2. Set up ''shorewall.conf'''''<br />
<br />
IP_FORWARDING=yes<br />
ROUTE_FILTER=No<br />
CLAMPMSS=Yes # See '''RFC2923'''<br />
<br />
'''3. Set up ''zones'''''<br />
<br />
inet ipv4<br />
loc ipv4<br />
tun ipv4<br />
dvb ipv4<br />
<br />
'''4. Set up ''interfaces'''''<br />
<br />
loc eth1 detect routefilter<br />
inet eth0 detect norfc1918,routefilter<br />
tun tun0 - norfc1918,routefilter<br />
dvb dvb0_0 - <br />
<br />
'''5. Set up ''policy'''''<br />
<br />
loc all REJECT info<br />
dvb all REJECT info<br />
all all DROP info<br />
<br />
'''6. Set up SNAT masquerading in ''masq'''''<br />
<br />
tun0 eth1<br />
<br />
'''7. Set up ''params'''''<br />
<br />
#This IP address are provided by the satellite ISP<br />
SAT_ISP_GRE_IP=<br />
LOCAL_TUN_IP=<br />
<br />
'''7. Set up ''rules'''''<br />
<br />
SECTION ESTABLISHED<br />
REJECT dvb fw:!$LOCAL_TUN_IP<br />
<br />
SECTION RELATED<br />
REJECT dvb fw:!$LOCAL_TUN_IP<br />
<br />
SECTION NEW<br />
DNS/ACCEPT fw inet<br />
Ping/ACCEPT fw inet<br />
<br />
#Allow Web/FTP queries via GRE tunnel to ISP<br />
# Answers come as RELATED/ESTABLISHED traffic via DVB<br />
Web/ACCEPT fw tun<br />
Web/ACCEPT loc tun <br />
FTP/ACCEPT fw tun <br />
FTP/ACCEPT loc tun <br />
Ping/ACCEPT fw tun <br />
Ping/ACCEPT pr tun<br />
<br />
'''8. Set up ''tunnels'''''<br />
<br />
gre inet $SAT_ISP_GRE_IP<br />
<br />
== Conclusion ==<br />
<br />
This document reviewed just basic ideas how to setup and share satellite internet connection. Further releases of Alpine Linux will include start up and configuration scripts (see Mailing Lists). Note, that more advanced traffic routing is beyond of scope of this document.<br />
<br />
== More information ==<br />
<br />
[http://en.wikipedia.org/wiki/Satellite_dish Satellite Dish]<br />
[http://en.wikipedia.org/wiki/Ku_band Ku-band]<br />
[http://www.linuxtv.org/wiki LinuxTV Wiki]<br />
[http://www.hack-it.net/How-To/Sat-HOWTO.html Satellite HOW-TO]<br />
[http://tier.cs.berkeley.edu/wiki/HOWTO:IPTunnelling IP Tunnelling HOW-TO]<br />
[http://www.sat2k.com/ivs.htm Satellite Parameters] <br />
[http://www.ses-sirius.com/english/ SES SIRIUS]<br />
[http://www.shorewall.net Shorewall]<br />
[http://http://lartc.org/howto Linux Advanced Routing & Traffic Control HOWTO]</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Setting_up_Streaming_an_Asterisk_Channel&diff=2095Setting up Streaming an Asterisk Channel2008-01-26T08:08:58Z<p>Iilluzion: </p>
<hr />
<div>= Streaming an Asterisk Channel HOW-TO =<br />
<br />
== Introduction ==<br />
<br />
The Asterisk is well known as VoIP service. Obviously, the nature of VoIP technology requires a real time communication, which makes certain requirements to a network connectivity layer in such regards as link speed/bandwidth, IP packet prioritization/control and network latency. <br />
<br />
In some cases it is desireable to provide at least one way communication possibility. For example, this idea could be used to give an ability at least "to listen" to a corporate work meeting/conferece, which is organized by means Asterisk MeetMe conference feature to those Remote Locations that still have relatively poor network connectivity layer with a Head Office. Another application is streaming an Asterisk channel to the Internet.<br />
<br />
== How does it work? ==<br />
<br />
The Asterisk is used with conjunction with sound streaming software such as Icecast2 server. The streaming technology provides "caching/buffering" capabilities. So broadcasted/recieved sound is being buffered, which helps overall sound quality to remain high surviving most of problems in network bandwidth and latencies.<br />
<br />
The Asterisk system places an automatic call to connect two extensions. One extension provides an Asterisk channel sound (MusicOnHold, Playback, MeetMe adn etc.), the second one starts the Asterisk Ices application and merges sound to it. The Ices Application depends on Icecast Ices, which is a source of sound to Icecast2 service.<br />
<br />
After sound is merged to Icecast Service by means Icecast Ices and Asterisk Ices Applications it could be listened as ogg sound stream by WinAmp, VLC media players. The stream cache parameter should be ajusted according local needs to achieve the acceptable sound quality.<br />
<br />
== Setup Asterisk Ices Application ==<br />
<br />
== Setup Icecast Ices Source ==<br />
<br />
== Setup Icecast2 Service ==<br />
<br />
== Using Media Players ==<br />
<br />
== More Information ==</div>Iilluzionhttps://wiki.alpinelinux.org/w/index.php?title=Setting_up_Satellite_Internet_Connection&diff=2036Setting up Satellite Internet Connection2007-12-28T20:28:00Z<p>Iilluzion: /* Sharing Satellite Internet Connection */</p>
<hr />
<div>= Satellite Internet Connection HOW-TO =<br />
<br />
== Introduction ==<br />
<br />
This document briefly explains Satellite technology, how it works, what do you need, configuration and how to sharing it between several clients. So the main focus is the Internet connection, satellite TV is not reviewed. <br />
<br />
== How does it work? ==<br />
<br />
So first we make the request (using land Internet connection) to the Sat-Server usually via a tunnel, after it will retrieve out info from Internet and it will send it to Satellite; in the end we would receive data from the it to our home using a parabolic antenna and a Sat Card. <br />
<br />
Satellite works very well with protocols, which have a little request data and a much bigger answer size. Although, a big time of answer is the biggest problem of satellite connection that may prevent using interactive services such as VoIP. The delay of answer may be considered basing on that a typical Sat distance is like 36.000 km, so an average overall delay time is 300-400 ms. <br />
<br />
To install the little satellite system we need:<br />
<br />
* DVB-S Card<br />
* Parabolic Antenna (Satellite Dish)<br />
* LNB Digital Converter <br />
<br />
== Technical Information ==<br />
<br />
A satellite link as a classical Wireless link is very different from Wired link. It may cause some additional problems to solve, such as reachability, privacy problems and so on. Also there could be weather problems, particularly in snow or rain conditions. <br />
<br />
=== Antenna / Converter ===<br />
<br />
A parabolic antenna gives a very high gain in RX. A frequency that is being received from the satellite transponder is from 11GHz up to 12.7 GHz. The Digital Converter transforms it to 1-2 GHz and send signal to the DVB-S card receiver through the coax cable up to 30-40m. This documents assumes that your parabolic antenna is properly mounted and calibrated as well as proper converter (usually Ku-band) is used.<br />
<br />
=== DVB-S Receiver Card === <br />
<br />
DVB-S card receives analog signals via coax cable and converts it to digital signals pretty like Ethernet card, after that the OS transforms it to a TCP/IP packets.<br />
<br />
== DVB Setup ==<br />
<br />
'''1. Install DVB-S Card and check if system recognized it'''<br />
<br />
Please note, that in most cases you need PCI version 2.1 or higher (check DVB card specifications). In practice it is Pentium-III or later systems.<br />
<br />
# lspci | grep -i "multimedia controller"<br />
<br />
'''2. Make sure that kernel modules are loaded'''<br />
<br />
You have to use Alpine 1.7.10 release or higher that should load appropriate kernel modules for DVB card on startup. You may check if DVB devices are installed. <br />
<br />
# ls -la /dev/dvb*<br />
<br />
'''3. Install LinuxTV Applications'''<br />
<br />
# apk_add linuxtv-dvb-apps<br />
<br />
'''4. Create and edit file ''channels.conf'''''<br />
<br />
This file contains settings for each Satellite you are using. For example the satellite ''Sirius-2 Nordic Beam'' has the following parameters: Freq - 12322Mhz, Polarization - vertical, Symbol Rate - 27.670213Ms/s. All parameters you have to receive from ISP or find in the Internet. Please look at [http://www.sat2k.com/ivs.htm Satellite Parameters] and [http://www.ses-sirius.com/english/ SES SIRIUS]. The following example is for Sirius-2 Nordic Beam:<br />
<br />
# echo "Sirius2-Nord:12322:v:0:27670:0:0:0" >> /etc/channels.conf<br />
<br />
Please, note,that the satellite Sirius-2 will be off soon, Sirius-4 has been lunched instead.<br />
<br />
'''5. Tune DVB Receiver'''<br />
<br />
# szap -c /etc/channels.conf -n 0<br />
<br />
In some cases you may need to run this command permanently in background because of a bug kernel modules for some dvb cards.<br />
<br />
# szap -c /etc/channels.conf -n 0 > /dev/null 2>&1 &<br />
<br />
'''6. Set up DVB network interface'''<br />
<br />
Your ISP provides you the PID, which is used for select a transmission between many signal from same frequency.<br />
<br />
# dvbnet -a 0 -p $PID<br />
<br />
# ifconfig dvb0_0 hw ether $MAC<br />
# ifconfig dvb0_0 $IP up<br />
<br />
Here $IP is any IP address, which does not match with any other adrres in your network. The $MAC you specify here is usually the MAC address of your DVB card, in some cases ISP calculates MAC address for you. In any case ISP sends data only for registered MAC addresses.<br />
<br />
Due to nature of satellite connection, the dvb interface receives packets, which have been originated from other sources, actually ether from land internet connection interface or, in most cases, from virtual tunnel device. So in order to allow receiving such packets the source validation should be disabled on dvb0_0 interface. <br />
<br />
# echo "0" > /proc/sys/net/ipv4/conf/dvb0_0/rp_filter <br />
<br />
'''7. Test if satellite interface is receiving data'''<br />
<br />
You should see many packets for other clients of your ISP.<br />
<br />
# apk_add tcpdump<br />
# tcpdump -n -i dvb0_0<br />
<br />
== Authentication with ISP ==<br />
<br />
Before you receive your data via satellite your ISP should authenticate you as their registered client. There are several common techniques could be used:<br />
<br />
* Some ISPs use the "Proxy Authentication", when you used their proxy, you also need to give login and password to continue the request. Once done, the ISP use your IP address to calculate your MAC address, to which send the answer. <br />
<br />
* Some other ISPs require you make a VPN connection (using your login and password) first, then they will control your registration account (where they retrieve your MAC address) and will send data to your card (your MAC address). <br />
<br />
* If you have static public IP, perhaps, the most convenient way is when ISPs suggest making a GRE/IPIP tunnel, which is used to sent authenticated requests to ISP satellite server. Consequently ISP sends back answers via satellite you are connected to.<br />
<br />
Here is an example of setting up GRE tunnel with a ISP:<br />
<br />
'''1. Make static routes'''<br />
<br />
All queries to DNS servers of your land ISP should go via land line.<br />
<br />
# route add $DNS1 gw $DEFAULT_LAND_GATEWAY<br />
# route add $DNS2 gw $DEFAULT_LAND_GATEWAY<br />
<br />
GRE packets should always go via land default gateway. <br />
<br />
# route add $SAT_ISP_GRE_IP gw $DEFAULT_LAND_GATEWAY<br />
<br />
Make new default route that goes via tunnel interface. So most requests will go via GRE tunnel to satellite ISP with source IP as $LOCAL_TUN_IP. Answers expected via dvb interface for destination IP as $LOCAL_TUN_IP.<br />
<br />
# route del default<br />
# route add default dev tun0<br />
<br />
It is assumed that $DEFAULT_LAND_GATEWAY is default gateway given by the land ISP, $DNSx are your DNS servers provided by the land ISP and $SAT_ISP_GRE_IP is remote IP of GRE tunnel of the satellite ISP.<br />
<br />
'''2. Make GRE tunnel and setup tunnel interface'''<br />
<br />
# modprobe ip_gre<br />
# modprobe tun<br />
<br />
# ip tunnel add tun0 mode gre local $MY_STATIC_IP remote $SAT_ISP_GRE_IP ttl 250<br />
# ifconfig tun0 $LOCAL_TUN_IP pointopoint $REMOTE_TUN_IP<br />
<br />
Parameters of a tunnel such as $SAT_ISP_GRE_IP, $LOCAL_TUN_IP, $REMOTE_TUN_IP are provided by the satellite ISP.<br />
<br />
'''3. Test satellite internet connectivity<br />
<br />
# ping wiki.alpinelinux.org<br />
<br />
# tcpdump -n -i tun0<br />
# tcpdump -n -i dvb0_0 host $LOCAL_TUN_IP<br />
<br />
== Sharing Satellite Internet Connection ==<br />
<br />
It is assumed that we need to share the satellite internet with clients in a local network that already is connected via second Ethernet interface to satellite internet machine. This requires enabling IP forwarding, set up simple SNAT masquerading and traffic filtering rules. The easiest way is to use Shorewall for that purpose.<br />
<br />
''' 1. Install shorewall'''<br />
<br />
# apk_add shorewall<br />
<br />
'''2. Set up ''shorewall.conf'''''<br />
<br />
IP_FORWARDING=yes<br />
ROUTE_FILTER=No<br />
CLAMPMSS=Yes # See '''RFC2923'''<br />
<br />
'''3. Set up ''zones'''''<br />
<br />
inet ipv4<br />
loc ipv4<br />
tun ipv4<br />
dvb ipv4<br />
<br />
'''4. Set up ''interfaces'''''<br />
<br />
loc eth1 detect routefilter<br />
inet eth0 detect norfc1918,routefilter<br />
tun tun0 - norfc1918,routefilter<br />
dvb dvb0_0 - <br />
<br />
'''5. Set up ''policy'''''<br />
<br />
loc all REJECT info<br />
dvb all REJECT info<br />
all all DROP info<br />
<br />
'''6. Set up SNAT masquerading in ''masq'''''<br />
<br />
tun0 eth1<br />
<br />
'''7. Set up ''params'''''<br />
<br />
#This IP address are provided by the satellite ISP<br />
SAT_ISP_GRE_IP=<br />
LOCAL_TUN_IP=<br />
<br />
'''7. Set up ''rules'''''<br />
<br />
SECTION ESTABLISHED<br />
REJECT dvb fw:!$LOCAL_TUN_IP<br />
<br />
SECTION RELATED<br />
REJECT dvb fw:!$LOCAL_TUN_IP<br />
<br />
SECTION NEW<br />
DNS/ACCEPT fw inet<br />
Ping/ACCEPT fw inet<br />
<br />
#Allow Web/FTP queries via GRE tunnel to ISP<br />
# Answers come as RELATED/ESTABLISHED traffic via DVB<br />
Web/ACCEPT fw tun<br />
Web/ACCEPT loc tun <br />
FTP/ACCEPT fw tun <br />
FTP/ACCEPT loc tun <br />
Ping/ACCEPT fw tun <br />
Ping/ACCEPT pr tun<br />
<br />
'''8. Set up ''tunnels'''''<br />
<br />
gre inet $SAT_ISP_GRE_IP<br />
<br />
== Conclusion ==<br />
<br />
This document reviewed just basic ideas how to setup and share satellite internet connection. Further releases of Alpine Linux will include start up and configuration scripts.<br />
<br />
== More information ==<br />
<br />
[http://en.wikipedia.org/wiki/Satellite_dish Satellite Dish]<br />
[http://en.wikipedia.org/wiki/Ku_band Ku-band]<br />
[http://www.linuxtv.org/wiki LinuxTV Wiki]<br />
[http://www.hack-it.net/How-To/Sat-HOWTO.html Satellite HOW-TO]<br />
[http://tier.cs.berkeley.edu/wiki/HOWTO:IPTunnelling IP Tunnelling HOW-TO]<br />
[http://www.sat2k.com/ivs.htm Satellite Parameters] <br />
[http://www.ses-sirius.com/english/ SES SIRIUS]<br />
[http://www.shorewall.net Shorewall]<br />
[http://http://lartc.org/howto Linux Advanced Routing & Traffic Control HOWTO]</div>Iilluzion