This is a tutorial on how to install an email server on Debian Wheezy 7.
We are going to install the following components:
E-mail server:
- Postfix
- Dovecot
- Sasl library
- MySQL
Milters:
- SpamAssassin
- Clamav
- Greylist
Webserver:
- Nginx
- PHP5
- phpMyAdmin
- PostfixAdmin
- RoundCube
Please replace any text in red with your info.
Here is a scheme about the internals, click on image to get a clear view:
1. Install Debian Wheezy 7
When installing Debian 7 itself, only select ‘SSH server’ when prompted to select software.
If Debian is ready, install the following packages:
apt-get install sudo mc vim
2. Install MySQL server and client
apt-get install mysql-server mysql-client
Enter a MySQL root password when prompted.
Check that mysqld is running:
ps aux
3. Install PHP5 and Nginx
At this point I use the Dotdeb repo to install PHP version 5.5.x
Add Dotdeb repositories to /etc/apt/sources.list file:
deb http://packages.dotdeb.org wheezy-php55 all
deb-src http://packages.dotdeb.org wheezy-php55 all
Add Dotdeb key:
wget http://www.dotdeb.org/dotdeb.gpg
sudo apt-key add dotdeb.gpg
Update apt cache:
apt-get update
Install PHP5 and Nginx:
apt-get install php5-fpm php5-imap php5-mysql php5-mcrypt php5-intl nginx openssl ssl-cert
Make sure php5-fpm and nginx are running:
service php5-fpm start
service nginx start
Create a folders to store web files:
mkdir /home/clients_ssl
mkdir /home/clients_ssl/<subdomain.domain.tld>
mkdir /home/clients_ssl/<subdomain.domain.tld>/logs
mkdir /home/clients_ssl/<subdomain.domain.tld>/tmp
mkdir /home/clients_ssl/<subdomain.domain.tld>/www
Create nginx config for this site:
vi /etc/nginx/sites-available/<subdomain.domain.tld>_ssl
Press ‘i’ and paste the following in vim, replace <yourip> and <subdomain.domain.tld> with your info:
server {
listen <yourip>:443;
server_name <subdomain.domain.tld>;
ssl on;
ssl_certificate /etc/nginx/certs/<subdomain.domain.tld>.combined.crt;
ssl_certificate_key /etc/nginx/certs/<subdomain.domain.tld>.key;
root /home/clients_ssl/<subdomain.domain.tld>/www;
index index.php index.html index.htm;
location ~ \.php$ {
fastcgi_pass unix:/etc/php5/fpm/socks/ssl_<subdomain.domain.tld>.sock;
include fastcgi_params;
fastcgi_param HTTPS on;
}
location ~ /\. {
deny all;
}
access_log /home/clients_ssl/<subdomain.domain.tld>/logs/access.log;
error_log /home/clients_ssl/<subdomain.domain.tld>/logs/error.log;
error_page 404 /404.html;
}
Remove the default site and put your site online:
rm /etc/nginx/sites-available/default
ln -s /etc/nginx/sites-available/<subdomain.domain.tld>_ssl /etc/nginx/sites-enabled/<subdomain.domain.tld>_ssl
Create the certs folder.
mkdir /etc/nginx/certs
Put your cerificates in there. Get a valid certificate from a certificate authority or create a self signed certificate.
You can google on how to make one. Make sure to edit your Nginx config file to match the certificate filenames.
Restart Nginx
service nginx restart
Create a php5-fpm config file:
vi /etc/php5/fpm/pool.d/ssl_<subdomain.domain.tld>.conf
Press ‘i’ and paste the following in vim, replace <subdomain.domain.tld> with your info:
[ssl_<subdomain.domain.tld>]
listen = /etc/php5/fpm/socks/ssl_<subdomain.domain.tld>.sock
user = u1001
group = g1001
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
pm = dynamic
pm.max_children = 50
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 5
pm.max_requests = 0
php_admin_value[open_basedir]=/
php_admin_value[session.save_path]=/home/clients_ssl/<subdomain.domain.tld>/tmp
php_admin_value[upload_tmp_dir]=/home/clients_ssl/<subdomain.domain.tld>/tmp
php_admin_value[disable_functions]=dl
Create a user for this virtualhost:
groupadd -g 1001 g1001
useradd --no-create-home -g 1001 -u 1001 u1001
Create socks folder:
mkdir /etc/php5/fpm/socks
Remove the default php pool:
rm /etc/php5/fpm/pool.d/www.conf
Add timezone info to php ini file /etc/php5/fpm/php.ini:
date.timezone = Europe/Tallinn
Restart php5-fpm
service php5-fpm restart
4. Install phpMyAdmin
cd /home/clients_ssl/<subdomain.domain.tld>/www
wget 'http://downloads.sourceforge.net/project/phpmyadmin/phpMyAdmin/4.0.8/phpMyAdmin-4.0.8-english.tar.gz?use_mirror=netcologne'
mv phpMyAdmin-4.0.8-english.tar.gz\?use_mirror=netcologne pma.tar.gz
tar -zxvf pma.tar.gz
Hide pma or bots will try to hack into it:
mv phpMyAdmin-4.0.8-english pma_763773
cd pma_763773
cp config.sample.inc.php config.inc.php
Set the right owner for www and tmp folder:
cd /home/clients_ssl/<subdomain.domain.tld>
chown -R 1001.1001 www tmp
Now you should be able to access pma at: https://<subdomain.domain.tld>/pma_763773/
Now open phpMyAdmin and click on ‘SQL’ on the top menubar. Paste the following SQL queries to create a database and user, replace <password> as you see fit:
CREATE DATABASE postfix;
GRANT ALL PRIVILEGES ON postfix.* TO 'postfix_admin'@'%' IDENTIFIED BY '<dbpassword1>';
GRANT SELECT ON postfix.* TO 'postfix'@'%' IDENTIFIED BY '<dbpassword2>';
FLUSH PRIVILEGES;
5. Install PostfixAdmin
Although you can install it from a standard Debian package I am going to download it directly instead so I can put it under my custom path immediately.
cd /home/clients_ssl/<subdomain.domain.tld>/www
wget 'http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.3.6/postfixadmin-2.3.6.tar.gz?use_mirror=garr'
mv postfixadmin-2.3.6.tar.gz\?use_mirror=garr pfa.tar.gz
tar -zxvf pfa.tar.gz
mv postfixadmin-2.3.6 pfa_746338
chown -R 1001.1001 pfa_746338
cd pfa_746338
sed -i 's/change-this-to-your.domain.tld/<subdomain.domain.tld>/g' config.inc.php
Now edit configuration file config.inc.php and change these values:
$CONF['configured'] = true;
$CONF['postfix_admin_url'] = 'https://<subdomain.domain.tld>/pfa_746338';
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix_admin';
$CONF['database_password'] = '<dbpassword1>';
$CONF['database_name'] = 'postfix';
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';
$CONF['fetchmail'] = 'NO';
Go to https://<subdomain.domain.tld>/pfa_746338/setup.php
This setup script should create the nesessary tables to postfix database.
At the bottom of setup.php enter your admin password and click ‘Gererate password hash’.
Edit config.inc.php and add the hash:
$CONF['setup_password'] = '<hash>';
Now enter superadmin account info. You can use this to access PostfixAdmin and configure domains, e-mail accounts, aliases etc.
Try to log in with the admin account here: https://<subdomain.domain.tld>/pfa_746338
6. Install Postfix and Sasl library
apt-get install postfix postfix-mysql libsasl2-modules libsasl2-modules-sql
When prompted, choose ‘Internet Site’.
Use yor domain name as ‘System mail name’: <subdomain.domain.tld>
For example use ‘mail.yourdomain.tld’. Do not use ‘yourdomain.tld’ here if it is going to be one of your virtual mailbox domains.
Create virtual mail user and group:
groupadd -g 3000 vmail
useradd -d /home/vmail -m -u 3000 -g 3000 vmail
Edit /etc/postfix/main.cf:
mydestination = <subdomain.domain.tld>, localhost
and add the following lines:
virtual_uid_maps = static:3000
virtual_gid_maps = static:3000
virtual_mailbox_base = /home/vmail
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_mailbox_domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
relay_domains = mysql:/etc/postfix/mysql_relay_domains.cf
virtual_transport = lmtp:unix:private/dovecot-lmtp
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_non_fqdn_hostname,
reject_non_fqdn_sender,
reject_non_fqdn_recipient,
reject_unauth_destination,
reject_unauth_pipelining,
reject_invalid_hostname
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
milter_default_action = accept
Create the following files:
/etc/postfix/mysql_virtual_mailbox_domains.cf
hosts = 127.0.0.1
user = postfix
password = <dbpassword2>
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = 0 and active = 1
/etc/postfix/mysql_virtual_mailbox_maps.cf
hosts = 127.0.0.1
user = postfix
password = <dbpassword2>
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = 1
/etc/postfix/mysql_virtual_alias_maps.cf
hosts = 127.0.0.1
user = postfix
password = <dbpassword2>
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = 1
/etc/postfix/mysql_relay_domains.cf
hosts = 127.0.0.1
user = postfix
password = <dbpassword2>
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = 1
/etc/postfix/sasl/smtpd.conf
pwcheck_method: auxprop
mech_list: plain login
auxprop_plugin: sql
sql_engine: mysql
sql_hostnames: 127.0.0.1
sql_user: postfix
sql_passwd: <dbpassword2>
sql_database: postfix
sql_select: SELECT password FROM mailbox WHERE username = '%u@%r' AND active = 1
Add postfix user to sasl group:
adduser postfix sasl
Enable secure smtp ports, edit /etc/postfix/master.cf and uncomment:
submission inet n - - - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
smtps inet n - - - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
7. Install Dovecot
apt-get install dovecot-imapd dovecot-pop3d dovecot-mysql dovecot-lmtpd
Create file /etc/dovecot/dovecot-mysql.conf.ext:
driver = mysql
connect = host=127.0.0.1 dbname=postfix user=postfix password=<dbpassword2>
default_pass_scheme = MD5-CRYPT
user_query = SELECT '/home/vmail/%d/%n' as home, 3000 AS uid, 3000 AS gid FROM mailbox WHERE username = '%u'
password_query = SELECT password FROM mailbox WHERE username = '%u'
Edit /etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = no
auth_mechanisms = plain login
#!include auth-system.conf.ext
!include auth-sql.conf.ext
Edit /etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:/home/vmail/%d/%n:INDEX=/home/vmail/%d/%n/indexes
Edit /etc/dovecot/conf.d/10-ssl.conf
ssl = yes
Edit /etc/dovecot/conf.d/20-imap.conf
mail_max_userip_connections = 10
Edit /etc/dovecot/conf.d/auth-sql.conf.ext
passdb {
driver = sql
# Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
args = /etc/dovecot/dovecot-mysql.conf.ext
}
userdb {
driver = sql
args = /etc/dovecot/dovecot-mysql.conf.ext
}
Edit /etc/dovecot/conf.d/10-master.conf
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
service auth {
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
mode = 0666
}
}
Restart services:
service dovecot restart
service postfix restart
You can now add a domain with PostfixAdmin and test your e-mail server.
Any errors are found in logfiles:
/var/log/auth.log
/var/log/mail.log
/var/log/syslog
8. Install Milters
apt-get install clamav-milter clamav-unofficial-sigs milter-greylist spamass-milter
clamav-milter:
Update ClamAv database and start the daemon:
freshclam
/etc/init.d/clamav-daemon start
Edit /etc/default/clamav-milter and uncomment the last line:
SOCKET_RWGROUP=postfix
Create a socket folder inside Postfix chroot environment:
mkdir /var/spool/postfix/clamav
chown clamav /var/spool/postfix/clamav
Configure ClamAv milter:
dpkg-reconfigure clamav-milter
Answer questions as follows:
Handle configuration automatically --> yes
User for daemon --> clamav
Additional groups --> none (empty field)
path to socket --> /var/spool/postfix/clamav/clamav-milter.ctl
group owner for the socket --> clamav
permissions (mode) for socket --> 660
remove stale socket --> yes
wait timeout for clamd --> 120
foreground --> no
chroot --> none (empty field)
pid file --> /var/run/clamav/clamav-milter.pid
temporary path --> /tmp
clamd socket --> unix:/var/run/clamav/clamd.ctl
hosts excluded for scanning --> none (empty field)
mail whitelist --> none (empty field)
action for "infected" mail --> reject
action on error --> defer
reason for rejection --> Rejecting harmful e-mail: %v found.
headers -> replace
log file --> /var/log/clamav/clamav-milter.log
disable log file locking --> no
maximum log file size --> 0
log time --> yes
use syslog --> no
log facility (type of syslog message) --> LOG_LOCAL6
verbose logging --> no
log level when infected --> off
log level when no threat --> off
size limit for scanned messages --> 25
Tell Postfix to use this new milter:
postconf -e 'smtpd_milters = unix:/clamav/clamav-milter.ctl'
postfix reload
spamass-milter:
Edit /etc/default/spamass-milter:
Add ‘-m’ so it won’t change the subject header.
Add ‘-r -1’ so Postfix rejects what SpamAssassin flags as spam.
Add ‘-l’ to avoid scanning e-mails sent by logged in users.
OPTIONS="-u spamass-milter -i 127.0.0.1 -m -r -1 -I"
Restart milter:
service spamass-milter restart
Add a dedicated user for SpamAssassin daemon:
adduser --shell /bin/false --home /var/lib/spamassassin --disabled-password --disabled-login --gecos "" spamd
Edit /etc/default/spamassassin:
ENABLED=1
OPTIONS="--create-prefs --max-children 5 --helper-home-dir=/var/lib/spamassassin -u spamd -g spamd"
CRON=1
Update rules and restart the daemon:
sa-update
service spamassassin restart
Tell Postfix to use new milter:
postconf -e 'smtpd_milters = unix:/clamav/clamav-milter.ctl, unix:/spamass/spamass.sock'
postfix reload
milter-greylist:
Edit /etc/milter-greylist/greylist.conf:
# For sendmail use the following two lines
#socket "/var/run/milter-greylist/milter-greylist.sock"
#user "smmsp"
# For Postfix uncomment the following two lines and comment out the
# sendmail ones above.
socket "/var/spool/postfix/milter-greylist/milter-greylist.sock" 660
user "greylist"
Edit /etc/default/milter-greylist:
ENABLED=1
SOCKET="/var/spool/postfix/milter-greylist/milter-greylist.sock"
Make a folder for the socket and restart milter:
mkdir /var/spool/postfix/milter-greylist
chmod 2755 /var/spool/postfix/milter-greylist
chown greylist:postfix /var/spool/postfix/milter-greylist
service milter-greylist restart
Tell Postfix to use the new milter:
postconf -e 'milter_connect_macros = i b j _ {daemon_name} {if_name} {client_addr}'
postconf -e 'smtpd_milters = unix:/milter-greylist/milter-greylist.sock, unix:/clamav/clamav-milter.ctl, unix:/spamass/spamass.sock'
postfix reload
9. Install RoundCube
wget 'http://downloads.sourceforge.net/project/roundcubemail/roundcubemail/0.9.4/roundcubemail-0.9.4.tar.gz?use_mirror=heanet'
mv roundcubemail-0.9.4.tar.gz\?use_mirror=heanet roundcubemail-0.9.4.tar.gz
tar -zxvf roundcubemail-0.9.4.tar.gz
mv roundcubemail-0.9.4 rcb_733621
chown -R 1001.1001 rcb_733621
Open phpMyAdmin SQL window and paste:
CREATE DATABASE roundcube;
GRANT ALL PRIVILEGES ON roundcube.* TO roundcube@localhost IDENTIFIED BY '<rcpassword>';
FLUSH PRIVILEGES;
Add initial tables and data:
cd /home/clients_ssl/<subdomain.domain.tld>/www/rcb_733621
mysql -u roundcube -p roundcube < SQL/mysql.initial.sql
Go to https://<subdomain.domain.tld>/rcb_733621/installer/
See that your environment is ok and click Next.
On the ‘Create config’ page, you may want to change the following values:
product_name: <yourproductname>
support_url: <yoururl>
database name: roundcube
database password: <rcpassword>
default_host: localhost
smtp_server: localhost
language: en_US
Click Continue
Change the value in textarea to:
$rcmail_config['use_https'] = true;
Then copy all from textarea and paste the contents to main.inc.php and db.inc.php under /home/clients_ssl/<subdomain.domain.tld>/www/rcb_733621/config
Remove installer folder:
mv installer ../../
Open RoundCube at https://<subdomain.domain.tld>/rcb_733621/
This is it 🙂
If this was of any use please link back to this tutorial.
Thank you.
Sources used to build this tutorial:
https://library.linode.com/email/postfix/postfix2.9.6-dovecot2.0.19-mysql
http://www.bytetouch.com/blog/linux/how-to-linux-mail-server-with-postfix-and-dovecot-on-debian-lenny/
https://lelutin.ca/posts/installing_postfix_-_clamav_-_spamassassin_-_dovecot_-_postfixadmin_on_debian_squeeze/