Postfix – sending emails via SMTP relay server (

This is an update to my previous post RE: sending via google SMTP relay but this time let’s use something bit more secure and private.

1. Go to and set yourself up with an email account.

2.  Login to your Raspberry PI as root and run:

 sudo postconf -e 'relayhost = []:587'
 sudo postconf -e 'smtp_sasl_auth_enable = yes'
 sudo postconf -e 'smtp_sasl_security_options = noanonymous'
 sudo postconf -e 'sender_canonical_maps = hash:/etc/postfix/sender_canonical'
 sudo postconf -e 'smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd'
 sudo su -c 'echo "login" > /etc/postfix/sender_canonical'
 sudo su -c 'echo "" > /etc/postfix/sender_canonical'
 sudo chown root:root /etc/postfix/sender_canonical
 sudo chmod 0600 /etc/postfix/sender_canonical
 sudo postmap /etc/postfix/sender_canonical
 sudo su -c 'echo "[]:587" > /etc/postfix/sasl_passwd'
 sudo chown root:root /etc/postfix/sasl_passwd
 sudo chmod 0600 /etc/postfix/sasl_passwd
 sudo postmap /etc/postfix/sasl_passwd

now just restart postfix:

service postfix restart

and test it, run:

tail -f /var/log/mail.log

and send test mail

Raspberry Pi – Setting up home server – email, wordpress blog, webserver, ftp, webmail and management tools.

The objective is to set-up email server with web-mail and anti-spam – all on a £30 Raspberry Pi. On top of that some management tools plus WordPress blogging platform.

For additional few pounds you can purchase yourself a domain and start your own online blog – I use NameCheap – highly recommended – have a look at their offering.


E-mail server:



Additional bits:

Update Firmware:

sudo apt-get install ca-certificates
 sudo apt-get install git-core mc
sudo wget -O /usr/bin/rpi-update
 sudo chmod +x /usr/bin/rpi-update
sudo rpi-update
 sudo ldconfig
 sudo rpi-update
 sudo reboot

Configure IP addresses

nano /etc/network/interfaces

Modify the file so it looks like this:

auto eth0

iface eth0 inet static


/etc/init.d/networking restart


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


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 folders to store web files:

mkdir /home/clients_ssl
 mkdir /home/clients_ssl/
 mkdir /home/clients_ssl/
 mkdir /home/clients_ssl/
 mkdir /home/clients_ssl/

Create nginx config for this site:

nano /etc/nginx/sites-available/MyDomain.net_ssl

Replace and with your info:

server {
ssl on;
 ssl_certificate /etc/nginx/certs/;
 ssl_certificate_key /etc/nginx/certs/;
root /home/clients_ssl/;
 index index.php index.html index.htm;
location ~ \.php$ {
fastcgi_pass unix:/etc/php5/fpm/socks/;
 include fastcgi_params;
 fastcgi_param HTTPS on;
location ~ /\. {
 deny all;
access_log /home/clients_ssl/;
 error_log /home/clients_ssl/;
 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/MyDomain.net_ssl /etc/nginx/sites-enabled/MyDomain.net_ssl

Create the certs folder.

mkdir /etc/nginx/certs
 cd /etc/nginx/certs
 openssl genrsa -des3 -out self-ssl.key 2048
 openssl req -new -key self-ssl.key -out self-ssl.csr

You can remove passphrase from self-ssl.key for nginx server, enter:

cp -v self-ssl.{key,original}
 openssl rsa -in self-ssl.original -out self-ssl.key
 rm -v self-ssl.original
openssl x509 -req -days 4000 -in self-ssl.csr -signkey self-ssl.key -out self-ssl.crt
 mv self-ssl.crt
 mv self-ssl.key

Restart Nginx

service nginx restart

Create a php5-fpm config file:

nano /etc/php5/fpm/pool.d/

paste the following and replace with your info:

listen = /etc/php5/fpm/socks/
 user = u1005
 group = g1005
 pm = dynamic
 pm.max_children = 50
 pm.start_servers = 1
 pm.min_spare_servers = 1
 pm.max_spare_servers = 5
 pm.max_requests = 0

Create a user for this virtualhost:

groupadd -g 1005 g1005
 useradd --no-create-home -g 1005 -u 1005 u1005

Create socks folder:

mkdir /etc/php5/fpm/socks

Remove the default virtualhost:

rm /etc/php5/fpm/pool.d/www.conf

Add timezone info to php ini file /etc/php5/fpm/php.ini:

date.timezone = Europe/London

Restart php5-fpm

service php5-fpm restart


Install phpMyAdmin

cd /home/clients_ssl/
 wget ''
 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 mysql_admin
cd mysql_admin

Set the right owner for www and tmp folder:

cd /home/clients_ssl/
chown -R 1005.1005 www tmp

Now you should be able to access pma at:
Now open phpMyAdmin and click on ‘SQL’ on the top menubar. Paste the following SQL queries to create a database and user, replace as you see fit:

 GRANT ALL PRIVILEGES ON postfix.* TO 'postfix_admin'@'%' IDENTIFIED BY '<password1>';
 GRANT SELECT ON postfix.* TO 'postfix'@'%' IDENTIFIED BY '<password1>';


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/
 wget ''
 mv postfixadmin-2.3.6.tar.gz\?use_mirror=garr pfa.tar.gz
 tar -zxvf pfa.tar.gz
 mv postfixadmin-2.3.6 mail_admin
 chown -R 1005.1005 mail_admin
 cd mail_admin
 sed -i 's/'

Now edit configuration file and change these values:

$CONF['configured'] = true;
 $CONF['postfix_admin_url'] = '';
 $CONF['database_type'] = 'mysqli';
 $CONF['database_host'] = 'localhost';
 $CONF['database_user'] = 'postfix_admin';
 $CONF['database_password'] = '<password1>';
 $CONF['database_name'] = 'postfix';
 $CONF['domain_path'] = 'YES';
 $CONF['domain_in_mailbox'] = 'NO';
 $CONF['fetchmail'] = 'NO';

Go to
This setup script should create the necessary tables to postfix database.
At the bottom of setup.php enter your admin password and click ‘Gererate password hash’.
Edit and add the hash:

$CONF['setup_password'] = '';

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:

Install Postfix and Sasl library

apt-get install postfix postfix-mysql libsasl2-modules libsasl2-modules-sql

When prompted, choose ‘Internet Site’.
Use your domain name as ‘System mail name’:
Create virtual mail user and group:

groupadd -g 3000 vmail
 useradd -d /home/vmail -m -u 3000 -g 3000 vmail

Edit /etc/postfix/ and add the following lines:

mydestination = localhost
virtual_uid_maps = static:3000
 virtual_gid_maps = static:3000
 virtual_mailbox_base = /home/vmail
 virtual_mailbox_domains = mysql:/etc/postfix/
 virtual_mailbox_maps = mysql:/etc/postfix/
 virtual_alias_maps = mysql:/etc/postfix/
 relay_domains = mysql:/etc/postfix/
 virtual_transport = lmtp:unix:private/dovecot-lmtp
 smtpd_recipient_restrictions =
 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:

nano /etc/postfix/

then paste the following:

hosts =
 user = postfix
 password = <password1>
 dbname = postfix
 query = SELECT domain FROM domain WHERE domain='%s' and backupmx = 0 and active = 1


nano /etc/postfix/

then paste the following:

hosts =
 user = postfix
 password = <password1>
 dbname = postfix
 query = SELECT maildir FROM mailbox WHERE username='%s' AND active = 1


nano /etc/postfix/

then paste the following:

hosts =
 user = postfix
 password = <password1>
 dbname = postfix
 query = SELECT goto FROM alias WHERE address='%s' AND active = 1


nano /etc/postfix/

and paste the following:

hosts =
 user = postfix
 password = <password1>
 dbname = postfix
 query = SELECT domain FROM domain WHERE domain='%s' and backupmx = 1


nano /etc/postfix/sasl/smtpd.conf

and paste the following:

pwcheck_method: auxprop
 mech_list: plain login
 auxprop_plugin: sql
 sql_engine: mysql
 sql_user: postfix
 sql_passwd: <password1>
 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/ 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


Configure Gmail smart host relay:

Add this bit to /etc/postfix/

#Smart host relay stuff
 relayhost = []:587
 smtp_sasl_auth_enable = yes
 smtp_sasl_password_maps = hash:/etc/postfix/relay_passwd
 smtp_sasl_security_options = noanonymous

create password map: /etc/postfix/relay_passwd


Then issue this command:

Postmap /etc/postfix/relay_passwd

For instructions how to setup a SMTP relay with see this post

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= dbname=postfix user=postfix password=<password1>
 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:

Install Milters

apt-get install milter-greylist 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 -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:

 OPTIONS="--create-prefs --max-children 5 --helper-home-dir=/var/lib/spamassassin -u spamd -g spamd"

Update rules and restart the daemon:

 service spamassassin restart

Tell Postfix to use new milter:

postconf -e 'smtpd_milters =unix:/spamass/spamass.sock'
 postfix reload



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:


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:/spamass/spamass.sock'
 postfix reload


Install RoundCube

wget ''
 mv roundcubemail-0.9.5.tar.gz\?use_mirror=heanet roundcubemail-0.9.5.tar.gz
 tar -zxvf roundcubemail-0.9.5.tar.gz
 mv roundcubemail-0.9.5 webmail
 chown -R 1005.1005 webmail


mysql -r -p


 GRANT ALL PRIVILEGES ON roundcube.* TO roundcube@localhost IDENTIFIED BY '<password9>';

Add initial tables and data:

cd /home/clients_ssl/
 mysql -u roundcube -p < SQL/mysql.initial.sql

Go to
See that your environment is ok and click Next.
On the ‘Create config’ page, you may want to change the following values:

product_name: Webmail
database name: roundcube
database password: <password9>
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 and under /home/clients_ssl/
Remove installer folder:

mv installer ../../

Open RoundCube at


Testing delivery

If you’d like to test out your setup, you can use the following:

apt-get install swaks
swaks --server=localhost
ls -l /home/vmail/   # You should see the delivered mail there.


Testing mail retrieval with Dovecot

And now we should be able to test a connection. There’s no quick and handy tool for testing this out, so brace yourselves: we’ll have to make an IMAP session manually (it’s not very complicated, really). From your computer, or another point which should have acces to the IMAP server:

openssl s_client -connect youhost.domain:143 -starttls imap
[... you'll see a bunch of info about the SSL certificate bein printed out]
a login something
[... list of capabilities]
a select inbox
[... if you did at least one test in the last step, you should see 1 EXISTS in the output]
a fetch 1 rfc822.text
[... message body]
a logout

Let’s try logging in without encryption to see if we get through (we shouldn’t !). If the server responds that login was successful there’s a problem somewhere.

telnet localhost 143
. login something
* BAD [ALERT] Plaintext authentication not allowed without SSL/TLS, but your client did it anyway. If anyone was listening, the password was exposed.
. logout


Testing the spam filter

For testing this, we’ll use the special string from GTUBE. This string triggers a special rule that sets the score to a very high value so that SpamAssassin flags the mail as spam without a doubt.

On your computer, download a text file with the GTUBE signature line and use it as the body of a test email:

wget -O /tmp/gtube.txt swaks --from some_existing@email.address --server=your.domain --body=/tmp/gtube.txt

The email should be blocked with the message:

<** 550 5.7.1 Blocked by SpamAssassin


Testing Greylist

If you want to have a better understanding of what’s going on, you can comment out the line “quiet” in /etc/milter-greylist/greylist.conf. This will make the rejection message specify how much time is left for the greylisting.

Send an e-mail to a user on the server in the same manner as you did above when testing delivery, although for this test you’ll need to send the e-mail from another computer (since we whitelisted


You should get rejected with a message looking like this:

<** 451 4.7.1 Greylisting in action, please come back in 00:23:33

Wait until that period is elapsed and re-try sending your mail. You should now be accepted.

Make sure you go back to the config file and comment out the “quiet” line again so that you don’t tell spammers how much time they need to wait.


nano /etc/nginx/sites-available/MyDomain.net_ssl

and edit it so it looks like the one below:

#Wordpress stuff
 # Upstream to abstract backend connection(s) for php
 upstream php {
 server unix:/tmp/php-cgi.socket;
 #End WordPress stuff
 server {
 ssl on;
 ssl_certificate        /etc/nginx/certs/;
 ssl_certificate_key    /etc/nginx/certs/;

 root /home/clients_ssl/;
 index index.php index.html index.htm;
location ~ \.php$ {

 fastcgi_pass unix:/etc/php5/fpm/socks/;
 include fastcgi_params;
 fastcgi_param HTTPS on;
 #Wordpress stuff
 #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
 fastcgi_intercept_errors on;
 fastcgi_pass php;
 #End WordPress stuff
 location ~ /\. {
 deny all;

 ##Wordpress stuff
 location = /favicon.ico {
 log_not_found off;
 access_log off;
location = /robots.txt {
 allow all;
 log_not_found off;
 access_log off;
 location / {
 # This is cool because no php is touched for static content.
 # include the "?$args" part so non-default permalinks doesn't b$
 try_files $uri $uri/ /index.php?$args;
 location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
 expires max;
 log_not_found off;
 #End WordPress stuff

 access_log /home/clients_ssl/;
 error_log /home/clients_ssl/;
 error_page 404 /404.html;


 Download and Extract WordPress

I will be setting up two blogs: one called: blog1, second: blog2
Download the latest wordpress source files then extract the downloaded archive:

cd /home/client_ssl/
 tar -xvzf latest.tar.gz
 mv wordpress blog1
 tar -xvzf latest.tar.gz
 mv wordpress blog1


 Configure MySQL

The next step is to configure MySQL for use with WordPress. WordPress needs a database and user, and permissions set correctly for access. Start the mysql config:

mysql -u root -p

Enter the root MySQL password, then arrive at the mysql prompt


Create a database for WordPress, create a user for the database, and set password set the permissions:

CREATE DATABASE wordpress_blog1;
 CREATE DATABASE wordpress_blog2;
 CREATE USER 'wordpressuser'@'localhost' IDENTIFIED BY '<password5>';
 grant all privileges on wordpress_blog1.* to wordpressuser@localhost with grant option;
 grant all privileges on wordpress_blog2.* to wordpressuser@localhost with grant option;

test the credentials:

mysql -u wordpressuser -p

Now create a new wordpress configuration based on the sample:

sudo cp /var/www/wordpress/wp-config-sample.php /var/www/wordpress_blog1/wp-config.php

And open it up for edit in an editor:

sudo nano /var/www/wordpress_blog1/wp-config.php

Repeat the step for blog2.

Change this:

/** The name of the database for WordPress */
 define(‘DB_NAME’, ‘database_name_here’);
/** MySQL database username */
 define(‘DB_USER’, ‘username_here’);
/** MySQL database password */
 define(‘DB_PASSWORD’, ‘password_here’);

to this (substituting password_here with your own from above):

/** The name of the database for WordPress */
 define(‘DB_NAME’, ‘wordpress_blog1’);
/** MySQL database username */
 define(‘DB_USER’, ‘wordpressuser’);
/** MySQL database password */
 define(‘DB_PASSWORD’, ‘<password5>’);

and do the same thing for the second blog.

To test the go to

Install FTP

apt-get install proftpd

 mkdir /etc/proftpd
 cd /etc/proftpd
 openssl req -new -x509 -days 4000 -nodes -out ftpd-rsa.pem -keyout ftpd-rsa-key.pem
 nano proftpd.conf

and add

<IfModule mod_tls.c>
 TLSEngine on
 TLSLog /var/log/proftpd-tls.log
 TLSProtocol TLSv1

 # Are clients required to use FTP over TLS when talking to this server?
 TLSRequired off

 TLSRSACertificateFile    /etc/proftpd/ftpd-rsa.pem
 TLSRSACertificateKeyFile /etc/proftpd/ftpd-rsa-key.pem
 # Authenticate clients that want to use FTP over TLS?
 TLSVerifyClient off


Service proftpd restart


Install Webmin and dependencies

sudo apt-get install libapt-pkg-perl libnet-ssleay-perl libauthen-pam-perl libio-pty-perl apt-show-versions
 sudo dpkg --install webmin_1.590_all.deb

Once webmin is install you should be able to access it via: login with your linux account and if necessary update to the latest available version from the main screen.

Password protect Nginx folder

Now I create admin folder where I will host my website with links to admin consoled. But first let’s set it up:

mkdir /home/clients_ssl/
Cd /etc/nginx/sites-available
 nano MyDomain.net_ssl

and add:

location ~ /admin {
 root /home/clients_ssl/;
 auth_basic "Restricted";
 auth_basic_user_file /path/to/your/htpass/file/htpasswd;

Passwords must be encoded by the crypt(3) function. I used a web based utility to generate my htpasswd file