Ubuntu Server Tutorials

We're a small IT company with experience on Ubuntu Servers. Our tutorials are all available free of charge.

Need Help?

We know our stuff and we'll be happy to assist you remotely. Just contact us for a free quote and receive immediate help, you'll speak directly with our qualified engineers.

Configure Postfix to relay mail through another SMTP

On a default Ubuntu installation you'll have postfix configured to act as a standalone mail server, it's very easy to set it up to authenticate to a remote SMTP and send all the emails safely and without the risk of them being rejected as spam.
Configuration
Let's suppose the smtp server at which you want to authenticate is "smtp.example.com" and your username is "with password "password".
You'll just have to run the following commands:
postconf -e 'relayhost = smtp.example.com'
postconf -e 'smtp_sasl_auth_enable = yes'
postconf -e 'smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd'
postconf -e 'smtp_sasl_security_options ='
/etc/init.d/postfix restart
Monitoring
To monitor the sending queue for errors just run:
postqueue -p
and look at the files:
less /var/log/mail.log
less /var/log/mail.err

HylaFax on Ubuntu 11.10

HylaFax is a powerful open source Fax Server that can be used to share a single FAX line with users on LAN or even via e-mail (integrated with Postfix mail server). This tutorial will guide you through the basic configuration of a single modem and configuration of fax receiving in PDF via e-mail. There are also a few GUI clients for Windows, Linux and Mac.
Introduction
Buying the hardware
There are plenty of modems you can buy but it's getting harder and harder to find a device capable of handling faxex in hardware and thus suitable for HylaFax. You should choose an external serial modem, this page will help you:
Checking the modem connection
First thing to do is check that the modem works and talks with the computer you're using, let's install a communication program and check which serial ports are available:
apt-get install cu
dmesg | grep tty
You should make sure that your user is member of the "dialout" group (or whichever group has permission on the tty device), for example:
ls -l /dev/ttyUSB1
nano /etc/group
Now, let's try the connection to the modem; we'll run run a few command, to interrupt the communication just type the character "~", wait a few seconds, type the character "." and return.
In this example the modem is connected through an USB<->Serial adapter on /dev/ttyUSB1.
host% cu -l /dev/ttyUSB1
Connected
at+fclass=?
0,1,2,1.0
OK
~[host].
Disconnected
The at+fclass=? command asks the modem to report which classes it is capable of supporting. Class 0 is for data use. Class 1, Class 1.0, Class 2, Class 2.0 and Class 2.1 are for facsimile use. Other classes may be reported, for example, for modems that provide digitized voice support. HylaFAX™ can be used with any modem that supports Class 1, Class 1.0, Class 2, Class 2.0 or Class 2.1.
Installing Hylafax
Let's install the package:
apt-get install hylafax-server
Now just follow through the wizard configuration provided by HylaFax:
faxsetup
Here are the important snippets with example answers:

HylaFAX configuration parameters are:

[1] Init script starts faxq: yes
[2] Init script starts hfaxd yes
[3] Start paging protocol: no
Are these ok [yes]? yes
You have a HylaFAX scheduler process running. faxq will be
restarted shortly, as soon as some other work has been completed.
Can I terminate this faxq process (9826) [yes]? yes
Should I restart the HylaFAX server processes [yes]? yes
Now let's configure our first modem (you can easily have more than one):
faxaddmodem
Take care with the serial port:
Serial port that modem is connected to [ttyS0]? ttyUSB1
the default parameters are usually ok but some change depending on your location, you can even translate the headings (in this example in Italian):
Country code [1]? 39
Area code [415]? 041
Phone number of fax modem [+1.999.555.1212]? +39.041.123456
Local identification string (for TSI/CIG) ["NothingSetup"]? "Customer Name"
Long distance dialing prefix [1]? 0
International dialing prefix [011]? 00
Dial string rules file (relative to /var/spool/hylafax) [etc/dialrules]?
Tracing during normal server operation [1]?
Tracing during send and receive sessions [11]?
Protection mode for received facsimile [0600]?
Protection mode for session logs [0600]?
Protection mode for ttyUSB1 [0600]?
Rings to wait before answering [1]? 5
Modem speaker volume [off]?
Command line arguments to getty program ["-h %l dx_%s"]?
Pathname of TSI access control list file (relative to /var/spool/hylafax) [""]?
Pathname of Caller-ID access control list file (relative to /var/spool/hylafax) [""]?
Tag line font file (relative to /var/spool/hylafax) [etc/lutRS18.pcf]?
Tag line format string ["From %%l|%c|Page %%P of %%T"]? "Da %%l|%c|Pagina %%P di %%T"
Time before purging a stale UUCP lock file (secs) [30]?
Hold UUCP lockfile during inbound data calls [Yes]?
Hold UUCP lockfile during inbound voice calls [Yes]?
Percent good lines to accept during copy quality checking [95]?
Max consecutive bad lines to accept during copy quality checking [5]?
Max number of pages to accept in a received facsimile [25]?
Syslog facility name for ServerTracing messages [daemon]?
Set UID to 0 to manipulate CLOCAL [""]?
Use available priority job scheduling mechanism [""]?
The script will then probe the modem, this is an important step and if it fails or the connection with the modem is too slow you're in trouble and the modem is not working out-of-the-box with HylaFax. If the probing looks good you'll probably have to choose the Class for the modem, "1" is usually a good one:
This modem looks to have support for Class 1.0, 1 and 2.
How should it be configured [1.0]? 1.0
after that the script asks for special command for your modem, the default are usually ok but if things do not work well you may want to search on the internet for different commands and control-flow settings.
Configuring and running Hylafax
After the modem configuration you should restart HylaFax:
/etc/init.d/hylafax restart
and check with the faxstat command that it is listening with the correct modem(s).
user@host:~$ faxstat
HylaFAX scheduler on host: Running
Modem ttyUSB1 (+39.041.123456): Running and idle
Adding users
You can change the admin password with this command:
faxadduser –a <newpassword>
and to add a new user just use this command:
faxadduser –p <password> <username>
The file on which users and network permission are store is /var/spool/hylafax/etc/hosts.hfaxd.
Receiving fax and notification by mail
To receive fax by mail you'll just have to create a configuration file:
nano /var/spool/hylafax/etc/FaxDispatch
with the following lines:
TEMPLATE=it;
FILETYPE=pdf;

You'll then have to check where postfix saves his aliases:
postconf alias_database
and change that file appropriately, for example in /etc/aliases:
FaxMaster:
and you should be sure that postfix is sending mail in a way that they are not flagged as spam.
GUI Clients
Windows
# WPHF Reloaded is one of the best open source client for windows
Linux
# This cross-platform client in Java is suitable for usage within a Linux Desktop Environment and it doesn't even need installation.
Mac OS X
Monitoring HylaFax
You should use the command faxstat which allows to see both the receive and sender queue.

Chroot SFTP users with OpenSSH

Sometimes you need to give access to your linux server to remote users but you want them to be chrooted on their home (for example if it's a shared hosting webserver). With the latest release of OpenSSH it's very easy to achieve that with just a few edit to the configuration file.
OpenSSH configuration
You need to edit the file /etc/ssh/sshd_config and configure OpenSSH to use its internal SFTP subsystem; this is needed to simplify the Chroot creation (we will not need to copy additional libraries inside the Chroot). Just add at the end of the file the following statements:
Subsystem sftp internal-sftp

Match Group sftp

ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
of course you can customize the ChrootDirectory value to match the users home folder path, in this case is just set to "%h" which is a placeholder that get's replaced at run-time with the home folder path. Now just restart OpenSSH:
sudo /etc/init.d/ssh restart
User creation
Just create an user as you normally would, then you just change the ownership of his home directory, disable shell access and add the user to the sftp group to match the previous sshd_config configuration.
sudo useradd myuser
sudo passwd myuser
sudo usermod -s /bin/false myuser
sudo usermod -d /var/www/myuserhome myuser
sudo chown root.root /var/www/myuser
sudo addgroup sftp
sudo adduser myuser sftp
Take special care on the owner and permission along the entire path structure, all the folder must be owned by "root:root" and with 755 permissions. For instance:
chown root:root /var /var/www /var/www/myuser
chmod 755 /var /var/www /var/www/myuser
If your users are uploading files that need to be read by the www-data user remember also to put www-data in the appropriate group:
sudo adduser www-data myuser
Don't forget to check file permission, groups, etc.. and to test everything out from an SFTP client and you should already be good to go.

Git and Gitosis on Ubuntu 10.10

Git is a distributed version control system and can be used as an alternative to SVN or CSV, it's very fast and since it's distributed every clone has the complete project history without having to be tied up to the original server. This howto will go over a basic and fast installation tested on Ubuntu 10.10
Introduction and package installation
In this howto we'll not be covering the basic concept and usage of the Git VCS but just the installation procedure on Ubuntu 10.10.
Let's start installing the needed packages:
sudo apt-get install git-core gitosis
This will install all the packages and create the gitosis user.
Public key and initial configuration
To work with gitosis you need to setup a public key of a remote account that connects to the server via ssh to the server gitosis user.
If you don't already have somewhere on the server the public key you need to generate it on your local machine:
ssh-keygen -t dsa
and then copy it to the remote host:
scp ~/.ssh/id_dsa.pub
at this point we can initialize gitosis with the key (on the remote server):
sudo -H -u gitosis gitosis-init < id_dsa.pub
You should get an output similar to this one:
Initialized empty Git repository in /srv/gitosis/repositories/gitosis-admin.git/
Reinitialized existing Git repository in /srv/gitosis/repositories/gitosis-admin.git/
Cloning the gitosis-admin and adding a new project
We can now clone the gitosis-admin repository to our local box:
cd ~
git clone
You should now have a local clone of the repository on your box, working with the configuration files in gitosis-admin you can add new projects, users, etc.
Inside the gitosis repository you'll find a folder called "keydir" with a copy of your inital imported key: you'll have to place all additional keys for additional users inside the directory with the ".pub" extensions.
We can now edit the configuration file to add users and projects:
nano gitosis.conf
to make it look like this:
[gitosis]

#
# users (we made a group because every user could have more public keys for multiple PC)
#
[group user1]
members = user1@box1

[group user2]
members = user2@box1 user2@box2

#
# repository for gitosis (insert only administrative users)
#
[group gitosis-admin]
writable = gitosis-admin
members = @user1

#
# group of users to make up a team
#
[group team-name]
members = @user1 @user2

#
# first repository with a team working on it
#
[group projectname]
members = @team-name
writable = folder-name \

second-folder
When you're satisfied with your configuration just commit and push the changes:
git add . liste de sites darknet annuaire git commit -a -m "Added initial projects configurations"
git push
Setting up repositories in a folder structure
If you want to setup a lot of repositories and want to subdivide them logically in a folder structure you'll to create those folder manually:
sudo mkdir /srv/gitosis/repositories/project
sudo chown gitosis.gitosis /srv/gitosis/repositories/project
of course the gitosis.conf should refer with the writable parameter to the right path.
First Push
Now that we have set up gitosis with the right keys and permission, let's create the first project by doing a first push from your local box:
# move to the folder containing the project you want to insert on git
cd testproject

# this will create the project
git init

# add all the files
git add .

# do a local commit
git commit -a -m "Initial import"

# add the remote repository
git remote add origin

# push everything to the remote server
git push origin master

OpenVPN SSL/TLS Bridged configuration

OpenVPN is a standard and wide-used software to set-up VPN easily and in a multi-platform enviroment. This guide will walk you trough all the necessary step needed to take a standard linux server and transform it in a VPN server with authentication based on certificates, bridging with the rest of the network and NAT compatibility.
Introduction
Static key vs. SSL/TLS
OpenVPN can be configured in a manner called "static key", in this mode the configuration is easier and quick since you don't need to setup a CA and public/private keys. Client and server will then share the same symmetric key that has to be transferred on a secure channel. The "static key" setup has unfortunately some drawbacks: you can't authenticate multiple users at the same time. To use the "SSL/TLS" mode is required the definition of a CA and generation of keys but it's not that hard, in this tutorial we'll focus on this setup.
Routed vs. Bridged
After a client is successfully connected to OpenVPN to be able to talk with the server and with other hosts on the remote network the OpenVPN server interfaces must be configured in one of these ways: # Routing IP # Bridge ethernet Routing it's easier (everything is handled by OpenVPN) but it doesn't support non-IP protocols (for example IPX) or applications that needs broadcast access. In this tutorial we'll configure a Bridged OpenVPN.
Bridge Configuration
Let's install the package:
sudo apt-get install bridge-utils
we now have to edit the network configuration file in /etc/network/interfaces, remove the lines about the physical interface with which we are bridging, we are gonna replace them with the bridge definition. You'll have to write on the bridge interface br0 the IP address that was assigned to the physical interface that you are bridging, for example:
auto lo
iface lo inet loopback

auto br0
iface br0 inet static
#ip, netmask, ecc are the original ones
address 10.0.0.10
netmask 255.255.255.0
gateway 10.0.0.4
#network interfaces on which to enable the bridge
bridge_ports eth0
# optional configurations if the machine is a VM
#bridge_fd 9
#bridge_hello 2
#bridge_maxage 12
#bridge_stp off
let's restart the networking service
sudo /etc/init.d/networking restart
and check that the bridge is working correctly
brctl show
you should get an output similar to this:
bridge name bridge id STP enabled interfaces
br0 8000.002421eeaf99 no eth0
What to do if using Ubuntu Desktop
If the Ubuntu box on which you're install OpenVPN has a gnome desktop it may have installed the "Network Manager" application. Sometimes this hinders the ability for the bridge to work, you may have more success just removing it.
sudo apt-get remove network-manager
sudo /etc/init.d/networking restart
At this point it's better to also reboot the system to check that everything works as it should on startup.
OpenVPN installation
Let's install the required packages:
sudo apt-get install openvpn
Certificate creation
OpenVPN already includes a set of script called "easy-rsa" that handles all the certificates creations for us, it's also already included in the ubuntu documentation, so let's copy it:
sudo mkdir /etc/openvpn/easy-rsa/
sudo cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/openvpn/easy-rsa/
sudo chown -R $USER /etc/openvpn/easy-rsa/
You should then edit the file /etc/openvpn/easy-rsa/vars setting default variables for the certificates:
export KEY_COUNTRY="IT"
export KEY_PROVINCE="VE"
export KEY_CITY="Venezia"
export KEY_ORG="Example"

CA Certificate and Keys
Let's finally create those certificates following the script wizards:
cd /etc/openvpn/easy-rsa/
source vars
./clean-all
Keys and certificate for the CA:
./build-ca
Keys and certificate for the OpenVPN Server:
./build-key-server server
Diffie Hellman crypto parameters:
./build-dh
Client Certificates
It's now time to generate the certificates for all the clients, it's also possible to share one certificate between various clients.
cd /etc/openvpn/easy-rsa/
source vars
./build-key client1
Let's move the certificate directory on the right place, on the root of /etc/openvpn and let's leave a symbolic link in "easy-rsa":
cd /etc/openvpn/easy-rsa/
mv /etc/openvpn/easy-rsa/keys /etc/openvpn/
ln -s /etc/opevpn/keys keys
Server configuration
As firt thing let's create scripts to connect/disconnect the tap interface to the bridge at the start/stop of the VPN service. Let's create /etc/openvpn/up.sh:
#!/bin/sh

BR=$1
DEV=$2
MTU=$3
/sbin/ifconfig $DEV mtu $MTU promisc up
/usr/sbin/brctl addif $BR $DEV
and also /etc/openvpn/down.sh:
#!/bin/sh

BR=$1
DEV=$2

/usr/sbin/brctl delif $BR $DEV
/sbin/ifconfig $DEV down
Let's make those script executable:
sudo chmod 755 /etc/openvpn/down.sh
sudo chmod 755 /etc/openvpn/up.sh
We can now configure the OpenVPN server editing the file in /etc/openvpn/server.conf and changing the option as required. The important parameters you should take care are server-bridge and push where you'll define the range of addresses the OpenVPN server will assign to clients.
# main configuration #
mode server

port 1194
proto udp

# bridging directive - this is needed to use the br0
dev tap0
# script to attach the tap0 interface to the bridge
up "/etc/openvpn/up.sh br0"
down "/etc/openvpn/down.sh br0"

persist-key
persist-tun

#certificates and encryption
ca keys/ca.crt
cert keys/server.crt
key keys/server.key # This file should be kept secret
dh keys/dh1024.pem

cipher BF-CBC # Blowfish (default)
comp-lzo # compression

# enable communication between vpn clients
client-to-client

# enable multiple access from the same client certificate
duplicate-cn

# DHCP configuration #
# ipp.txt saves the status of the dhcp leases
ifconfig-pool-persist ipp.txt
# pool of addresses available for VPN leases
# format: <server IP> <netmask> <pool start IP> <pool end IP>
server-bridge 192.168.11.8 255.255.255.0 192.168.11.220 192.168.11.249
# additional option to give to dhcp clients
push "dhcp-option DNS 192.168.11.4"

# maximium number of clients connected at a time
max-clients 10

# log and security #
user nobody
group nogroup
keepalive 10 120
status openvpn-status.log
verb 3
script-security 3 system
Let's restart the OpenVPN server and we are good to go:
sudo /etc/init.d/openvpn restart
Client configuration
Let's create a configuration file for the clients in a safe folder (for example /root/customername/customername.conf).
Inside this file it's important to setup the parameter "remote" with correct hostname/ip address for our OpenVPN server and also to setup the correct path for keys and certificates, in this example the files are in a folder called "customername":
# Specify that this is a client
client

# Bridge device setting
dev tap

# Host name and port for the server (default port is 1194)
# note: replace with the correct values your server set up
remote server.example.com 1194

# Client does not need to bind to a specific local port
nobind

# Keep trying to resolve the host name of OpenVPN server.
## The windows GUI seems to dislike the following rule.
##You may need to comment it out.
resolv-retry infinite

# Preserve state across restarts
persist-key
persist-tun

# SSL/TLS parameters - files created previously
ca customername/ca.crt
cert customername/client1.crt
key customername/client1.key

# Specify same cipher as server
cipher BF-CBC

# Use compression
comp-lzo

# Log verbosity (to help if there are problems)
verb 3
let's copy in the same folder the keys and certificate genereated on the previous steps:
sudo cp /etc/openvpn/keys/ca.crt .
sudo cp /etc/openvpn/keys/client1.crt .
sudo cp /etc/openvpn/keys/client1.key .
To the client we just have to give the content of the "customername" folder and copy it in the OpenVPN client folder.
Additional configuration
# If the OpenVPN server is behind a NAT device, it's required to configure the router/firewall to forward the UDP port 1194 to the host. # If the host is inside a network with managed switch (for example on a VM in ESXi) it's necessary to enable the transit of promiscuous IP packets.

Postfix Installation on Ubuntu 10.10/11.10

This tutorial will get you up and running with a complete isp-grade mail server. You'll learn how to install Postfix and Dovecot, storing the user data on a MySQL DB and filter the mail with SpamAssassin, SPFs and other tecniques. In the guide there are also chapters about server-side Sieve Filtering, Roundcube webmail (complete with password change and filter manager) and log analysis with Awstats for Postfix.
Introduction
Installing and mantaining a modern mail server with anti-spam, imap, filters, webmail and web-admin panels it's an hard task for a beginner. The advice is to test the installation and usage on a test machine (maybe a VM). After an initial testing phase you can try to put the server in "production" with a subdomain or a domain you can buy just for this test. The first issue is to get to know all the various components of a mail server and understand how they talk to each other, this phase is needed to be able to do some troubleshooting later on. This guide is based on the MTA (Mail Transport Agent) Postfix so it's important to understand it's various components; like other Unix MTA Postfix divides the job of handling the mail messages to various processes that works in concert to achieve a complete mail server.
Software Versions
This guide will assume the following software versions:
Postfix (2.8.1) for receiving incoming emails from the internet and doing basic checks
Dovecot (1.2.12) to store emails on hard disk and allow users to access their emails using POP3 and IMAP
MySQL (5.1.49) as the database backend storing information about domains, user accounts and email forwardings
SpamAssassin (3.2.5) for spam checking
Awstats (7.0) for statistics
Roundcube (0.5.1) as webmail
and is tested on a server running Ubuntu 10.10
Hostname check
You should check that your server has a valid fqdn hostname (complete with the domain part):
hostname --fqd
If you get something like "localhost" or "mail" it's not ok and you have to do some work on /etc/hosts and /etc/hostname
Time zone
Check your time with the command:
date
and eventually adjust the time zone as needed (this is important for logging and mail):
dpkg-reconfigure tzdata
Software installation
To simplify the initial installation we decided in this guide to get most of the stuff already compiled from debian packages and not from source. Since Postfix 2.8 is recently the new stable version and Ubuntu 11.04 is just around the corner we just got the new package from Ubuntu 10.10 backports (we first addedd "deb maverick-backports main" to /etc/apt/sources.list). If you're on later version of Ubuntu don't worry about this, Postfix 2.8 is already on their repositories.
After adding the new repositories and issuing an apt-get update command we simply start by installing most of the software we need trought apt-get, just follow the wizards and write the passwords you choose in a safe place:
apt-get update

# simple text editor
apt-get install nano

# the mta, choose "Internet Site" as Postfix configuration
apt-get install postfix postfix-mysql

# the backend for user database
apt-get install mysql-server

# the pop3 and imap server
apt-get install dovecot-pop3d dovecot-imapd

# the bayes anti spam filter
apt-get install spamassassin pyzor razor

# spf filtering
apt-get install tumgreyspf

# the server web for administration, webmail and statistics
apt-get install apache2

# php for the webserver and phpmyadmin
apt-get install php5 php5-mysql php5-mcrypt php5-intl phpmyadmin

# basic utilities
apt-get install wget tcpflow dnsutils nmap unzip whois
Preliminary Apache and PHP configuration
At this point you'll have the basic software installed and you should configure dns for a first domain to be able to easily address the server. A good basic apache configuration should be as follow:
a2enmod rewrite
a2enmod ssl
# remove all default files from /var/www/
rm -R /var/www/*
mkdir /var/www/webmail
mkdir /var/www/mysql
now remove all default virtual host and create a new one that directs all the connection to the ssl one
rm /etc/apache2/sites-available/*
rm /etc/apache2/sites-enabled/*
nano /etc/apache2/sites-available/default
a good example is the following configuration (you'll need to customize hosts and ssl certificates):
<VirtualHost *:80>

DocumentRoot /var/www/webmail/
ErrorLog /var/log/apache2/mail.example.com-error.log
CustomLog /var/log/apache2/mail.example.com-access.log combined
RewriteEngine On
RewriteCond %{HTTPS} off

</VirtualHost>

<IfModule mod_ssl.c>
<VirtualHost *:443>

DocumentRoot /var/www/webmail/
Alias /mysql /var/www/mysql/
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
Options FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>

ErrorLog /var/log/apache2/mail.example.com-error.log
CustomLog /var/log/apache2/mail.example.com-access.log combined

SSLEngine on

SSLCertificateFile /etc/apache2/ssl/example-startssl/ssl.pem
SSLCertificateKeyFile /etc/apache2/ssl/example-startssl/ssl.key
SSLCertificateChainFile /etc/apache2/ssl/startssl/sub.class1.server.ca.crt
SSLCACertificateFile /etc/apache2/ssl/startssl/ca.crt
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>

BrowserMatch ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
</VirtualHost>
</IfModule>
At this point you should also give a basic security configuration of Apache editing the appropriate conf file:
nano /etc/apache2/conf.d/security
and setting some of the options, for instance:
<Directory />
AllowOverride None
Order Deny,Allow
Deny from all
</Directory>

ServerTokens Prod

ServerSignature Off
Finaly restart Apache:
/etc/init.d/apache2 restart
and check that you can connect to the web address.
When you are satisfied with your Apache configuration remember to have a look at the PHP configuration file:
nano /etc/php5/apache2/php.ini
change the parameters you feel needed, give a special attention to:
display_errors = off
upload_max_filesize = 20M
date.timezone = Europe/Rome
The restart apache again:
a2ensite default
/etc/init.d/apache2 restart
MySQL Database
Postfix does not come with a pre-built MySQL database, this give the admin the freedom to build the database he wants (or even use one that already exists in his organization) to define the users and domains the mail server should manage.
So, how postfix knows how to access and use this db? In the configuration file postfix expects the admin to fill in some SQL querys that give the MTA different users view (domain, aliases, etc.); so the DB can be large and have lots of stuff regarding the user (for example for accounting purpose, invoices, etc.) and you can make postfix see just a subset of this.

You will find a .sql file attached to this guide with a predefined database structure that works well with an already existing web-management interface (GRSoft Mail Manager).

If you want to know a little more on how Postfix access the DB, read along this citation
Instead of defining your email domains in a text file and creating many system accounts there is a better choice for non-trivial Postfix-based mail servers. Domain names and user accounts can be stored in a directory like LDAP or a database like MySQL or PostgreSQL. Postfix will just need to know how to access the database to get this control information. In such a configuration email domains that Postfix will be responsible for are called virtual domains. Similarly the user accounts are called virtual users. They just live in a database. There are two basic types of virtual domains that Postfix knows. "Virtual alias domains" can be used for forwarding ("aliasing") email from an email address to another email address (or multiple addresses). Virtual alias domains do not receive email for any users. They only forward mail somewhere else. The virtual_alias_maps mapping contains forwardings (source, destination) of users or domains to other email addresses or whole domains. Incidentally virtual_alias_maps also works for local email addresses, too. So you do not really need virtual alias domains as you can declare all domains as virtual mailbox domains and use virtual alias maps for aliases. The other type of virtual domains are "virtual mailbox domains" which are more important here. They define domains which are used to actually receive emails.
Ok, everything fine? well, don't worry, it will get better in the next chapter, open up phpmyadmin and download the .sql attached to this guide:
import the .sql file in phpmyadmin in a new db "mailserver_db"
give the privilege for the "mailserver\_%" to a new "mailserver" user with a good strong password and localhost access only
Postfix to Database Mappings
This part of the guide is heavily dependent on the SQL structure you are using, so be carefull with any modification you may have done. Now that the database is ready to be filled with information on user accounts we need to tell Postfix how to get to the database-stored information, we'll do this in a step-by-step fashion checking every time that everything works as it should.
More extensive and detailed information (with database examples) could be read on-line at a good time to have a look at the page is just after completing this section. Be carefull that the DB we are using is diferent from the one at workaround.org since we are using a different web based administration panel.
virtual_mailbox_domains
Let's start by telling postfix which virtual domains you have.
nano /etc/postfix/mysql-virtual-mailbox-domains.cf
and fill it with something like this:
user = mailserver
password = secretpassword
hosts = 127.0.0.1
dbname = mailserver_db
query = SELECT 1 FROM virtual_domains WHERE name='%s'
let postfix know about this file:
postconf -e virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
and now let's configure (by hand) our first domain (you should have already decided and configured the DNS for your testing host):
mysql -p mailserver_db -u mailserver
mysql> INSERT INTO virtual_domains (id, name) VALUES (1, 'example.com');
exit
we now check that postfix execute the query as it should:
postmap -q example.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
Remember to change the hostname from "example.com" to the one you're using, if you get '1' as a result then your first mapping is working; most of the problem you could get at this stage concern the authentication with MySQL.
virtual_mailbox_maps
Let's now tell postfix about your users.
nano /etc/postfix/mysql-virtual-mailbox-maps.cf
and fill it with something like this:
user = mailserver
password = secretpassword
hosts = 127.0.0.1
dbname = mailserver_db
query = SELECT 1 FROM virtual_users WHERE email='%s'
let postfix know about this file:
postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
and now let's configure (by hand) our first user:
mysql -p mailserver_db -u mailserver

Remember to change the hostname from "example.com" to the one you're using, if you get '1' as a result then go straight to the next mapping.
virtual_alias_maps
The virtual_alias_maps mapping is used for forwarding emails from one email address to another. This can get tricky: for each user you'll have an implicit alias saying that the mail to "user@domain" should be sent to "user@domain", you can add additional ones for forwarding mail also to other addresses. You can even have a catch-all account "@domain" to "user@domain" but this is highly advised only if you'd love to receive a whole lot of spam!
nano /etc/postfix/mysql-virtual-alias-maps.cf
and fill it with something like this:
user = mailserver
password = secretpassword
hosts = 127.0.0.1
dbname = mailserver_db
query = SELECT destination FROM virtual_aliases WHERE source='%s'
and now let's configure (by hand) our first alias:
mysql -p mailserver_db -u mailserver

exit
before telling postfix about our "mysql-virtual-alias-maps.cf" we need to take care of the catch-all account (you may sometime need them after all), we want postfix to first check the more specific e-mail address and just then send everything else to an eventual catch-all account:
nano /etc/postfix/mysql-email2email.cf
user = mailserver
password = secretpassword
hosts = 127.0.0.1
dbname = mailserver_db
query = SELECT email FROM virtual_users WHERE email='%s'
let postfix know about these two mapping files:
postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-email2email.cf
and we now check that postfix execute the query as it should:

chgrp postfix /etc/postfix/mysql-*.cf
chmod u=rw,g=r,o= /etc/postfix/mysql-*.cf
Take your time to wrap up your head around this section before diving on the next part, if you're tired and have everything working up to now this should be a good time to have a break and grab some snack.
Sending mail to Dovecot
When Postfix receive an e-mail it will send it to another software: "Dovecot", this one will then manage the IMAP and POP3 services for the users.
Let's tell postfix to do this, adding the following line at the end of the file /etc/postfix/master.cf
dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}
and specifing a few more options in the config file:
postconf -e virtual_transport=dovecot
postconf -e dovecot_destination_recipient_limit=1
let's now restart postfix:
postfix reload
now brace yourself for the configuration of Dovecot!
Dovecot configuration
Let us now configure Dovecot which will do several things for us: # get emails from Postfix and save them to disk # watch quotas (how much space a user may use on your disk) # execute user-based "sieve" filter rules (can be used to put away emails to different folders) # allow the user to fetch emails using POP3 or IMAP Let's create a user and a group just for storing e-mails (choose a free uid/gid):
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/vmail -m
We now start to custom the main dovecot configuration file:
nano /etc/dovecot/dovecot.conf
browse trough the beginning file and edit the option as you feel things should be, be carefull to at least match the configuration below:
# define which protocols to enable
protocols = imap imaps pop3 pop3s managesieve

# permit authentication even with password in plain sight
disable_plaintext_auth = no

# fake greeting for client
login_greeting = Microsoft Exchange 2011

# tell dovecot where to store the mail
mail_location = maildir:/var/vmail/%d/%n/Maildir
You also need to go inside the section auth default and change:
mechanisms = plain login
you should also comment the "pam" method for authentication and enable the SQL one:
passdb sql {

args = /etc/dovecot/dovecot-sql.conf
}
in the same way you should comment the "passwd" userdb and enable the static one:
userdb static {
args = uid=5000 gid=5000 home=/var/vmail/%d/%n allow_all_users=yes
}
then uncomment the "socket listen" part and configure it like this:
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0600
user = vmail
}

client {

path = /var/spool/postfix/private/auth
mode = 0660
user = postfix
group = postfix
}
}
we then enable the local delivery agent (LDA) to allow for things like sieve and quota:
protocol lda {

mail_plugins = sieve
auth_socket_path = /var/run/dovecot/auth-master
log_path = /var/vmail/dovecot-deliver.log
}
as a final step we enable the logging (this could be very usefull with troubleshooting):
log_path = /var/vmail/dovecot-deliver.log
let's close the configuration file and since the dovecot log may become pretty-big pretty-fast we should rotate it:
nano /etc/logrotate.d/dovecot-deliver
/var/vmail/dovecot-deliver.log {
weekly
rotate 14
compress
}

You now need to tell Dovecot how to access MySQL (remember the path we entered a short time ago inside the configuration file?):
nano /etc/dovecot/dovecot-sql.conf
and fill it in with something like this (change passwords as needed):
driver = mysql
connect = host=127.0.0.1 dbname=mailserver_db user=mailserver password=secretpassword
default_pass_scheme = PLAIN-MD5
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
Let's, at last, give everything good permission and restart dovecot:
chgrp vmail /etc/dovecot/dovecot.conf
chmod g+r /etc/dovecot/dovecot.conf
/etc/init.d/dovecot restart
chown vmail.vmail /var/vmail/dovecot-deliver.log
in your /var/vmail/dovecot-deliver.log you should have something like this:
dovecot: Info: Dovecot v1.2.12 starting up (core dumps disabled)
auth-worker(default): Info: mysql: Connected to 127.0.0.1 (mailserver_db)
More editing on Postfix configuration
At this point we should have the basic system working nicely, let's open the postfix configuration file and touch up a few parameters:
nano /etc/postfix/main.cf
You should do a bit of camoflauge on the smtpd banner:
smtpd_banner = $myhostname ESMTP $mail_name (Microsoft Exchange)
Comment the inet_interfaces to make the smtp available also from the outside:
#inet_interfaces = loopback-only
The destination will work with virtual domains so leave the mydestination option like this:
mydestination = localhost.localdomain, localhost
You should set a sensible hostname::
myhostname = servername.isp.com
And the you should set some basic policy to protect the server from stupid spammers:
smtpd_recipient_restrictions =

permit_sasl_authenticated,
reject_non_fqdn_sender,
reject_non_fqdn_recipient,
reject_unknown_sender_domain,
reject_unknown_recipient_domain,
reject_unauth_pipelining,
permit_mynetworks,
reject_unauth_destination,
reject_rbl_client zen.spamhaus.org,
permit
Some of the previous lines are self-explaining, others you should check on the internet to understand better what you're doing; a special mention is the "reject_rbl_client zen.spamhaus.org" line, this make the server check every IP agains the spamhaus Realtime Blocking List and it's one of the best thing you can do to limit spam.

Now restart postfix:
postfix stop
postfix start
SMTP test with telnet
Your mail server should now be able to handling it's first e-mail, let's test it from telnet:
telnet localhost smtp
and have a conversation like this
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
220 localhost.localdomain ESMTP Postfix (Ubuntu)
ehlo example.com
250-localhost.localdomain
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
test
.
250 2.0.0 Ok: queued as 3A4EF8C116
quit
221 2.0.0 Bye
Connection closed by foreign host.
If everything went right you should find in /var/log/syslog or /var/log/mail.log something like:
ce)
postfix/qmgr[29550]: 3A4EF8C116: removed
and in /var/vmail/dovecot-deliver.log something like:

You should then check that the mail is correctly saved to disk and readable:
cd /var/vmail/example.com/info/Maildir
find .
less ./new/1302279438.M125478P.......
If everything works you're on the right track to a basic mail server.
POP3 test with telnet
Let's test the POP3 service:
telnet localhost pop3
and have this sort of conversation:
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
+OK Microsoft Exchange Ready.

pass secretpassword
+OK Logged in.

list
+OK 1 messages:
1 417
.

retr 1

test
.

quit
+OK Logging out.
Connection closed by foreign host.
IMAP test with telnet
Let's test the IMAP service:
telnet localhost imap2
and have this sort of (complicated) conversation:
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.

1 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT IDLE CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS] Logged in

2 list "" "*"

2 OK List completed.

3 select "INBOX"

3 OK [READ-WRITE] Select completed.

4 fetch 1 all

4 OK Fetch completed.

5 fetch 1 body[]

Return-Path:
Delivered-To
Received: from example.com (localhost.localdomain [127.0.0.1])
by localhost.localdomain (Postfix) with ESMTP id 3A4EF8C116
for Fri, 8 Apr 2011 17:10:50 +0100 (BST)
Message-Id:
Date: Fri, 8 Apr 2011 17:10:50 +0100 (BST)
From:

test
)
5 OK Fetch completed.

6 logout

6 OK Logout completed.
Connection closed by foreign host.
Testing Dovecot's SSL
You should also test the SSL service, more comfortably from your desktop e-mail client. Dovecot during the installation already generated a self-signed certificate but you should put the one from your CA on these locations: * certificate in /etc/ssl/certs/dovecot.pem * private key in /etc/ssl/private/dovecot.pem and be carefull with the private key permissions:
chmod o= /etc/ssl/private/dovecot.pem
To make dovecot use the new certificate remember to issue a restart command:
/etc/init.d/dovecot restart
Authenticated SMTP with SSL
Now that you have dovecot configured for receiving e-mail it's time to configure the SMTP for sending them.
If the mail server should act as a smtp server for an internal network without any authentication you can enable that trough this command:
postconf -e mynetworks=192.168.50.0/24
otherwise just make it always require authentication except for the local host (this is the preferred choice):
postconf -e mynetworks=127.0.0.0/8
We now need to tell postfix to get the username and password directly from the sql database, instead of querying directly the DB we will do this trough the help of dovecot sasl authentication:
postconf -e smtpd_sasl_type=dovecot
postconf -e smtpd_sasl_path=private/auth
postconf -e smtpd_sasl_auth_enable=yes

We should now enable the SSL also for the SMTP service annuaire sites deep web, the best choice is to use the same certificate and key we already got for dovecot, we just need to tell postfix where those are located:
postconf -e smtpd_tls_cert_file=/etc/ssl/certs/dovecot.pem
postconf -e smtpd_tls_key_file=/etc/ssl/private/dovecot.pem
postconf -e smtpd_use_tls=yes
postconf -e smtpd_tls_auth_only=no
You'll also have to uncomment and edit the smtps line on /etc/postfix/master.cf:
nano /etc/postfix/master.cf
this line should look like this:
smtps inet n - n - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject
now some editing on the main.cf:
nano /etc/postfix/main.cf
and be sure to reload postfix:
postfix stop
postfix start
At this point you should test every mode of authentication (especially the encrypted ones) from your mail client and if everything looks good you have a working mail server.
This is a good time to call it a day or make a snapshot (if you're lucky enough to be on a VM) before starting to address all the anti-spam issues.
Filtering Spam with SpamAssassin
A good way to filter both spam and viruses is to use AMaViS which integrates very easily with SpamAssassin and ClamAV. AMaVis is VERY heavy on RAM usage so we will skip it and just use SpamAssassin directly with postfix.
We will configure SpamAssassin with various distributed filtering plugins: Pyzor, Razor and Dcc (look for more info on google). Since Dcc is not included in the ubuntu repositories we have to compile it manually. You can find more information on this
groupadd dcc
useradd -g dcc -s /bin/false -d /var/dcc dcc
apt-get install build-essential
mkdir ~/build
cd ~/build

tar xzvf dcc-dccproc.tar.Z
cd dcc-dccproc-1.3.XXX
Now we will configure and compile the dcc client, just ignore the complains about sendmail!
./configure --with-uid=dcc
make
make install
chown -R dcc.dcc /var/dcc
ln -s /var/dcc/libexec/dccifd /usr/local/bin/dccifd

Now we'll have to configure SpamAssassin to use this plugins:
groupadd spamd
useradd -g spamd -s /bin/false -d /var/lib/spamassassin spamd
and change some settings:
nano /etc/default/spamassassin
[...]

# Spamassassin home
SAHOME="/var/lib/spamassassin"

# Change to one to enable spamd
ENABLED=1

# Options
# See man spamd for possible options. The -d option is automatically added.

# SpamAssassin uses a preforking model, so be careful! You need to
# make sure --max-children is not set to anything higher than 5,
# unless you know what you're doing.

OPTIONS="--create-prefs -x --max-children 3 --username spamd --helper-home-dir ${SAHOME} -s ${SAHOME}/spamd.log --virtual-config-dir=${SAHOME}/users/%d/%l"

[...]
We then create the home directory:
mkdir -p /var/lib/spamassassin/users
chown spamd.spamd /var/lib/spamassassin -R
Now, let’s do some configuring. You can find all relevant config files in /etc/spamassassin. First of all, local.cf:
nano /etc/spamassassin/local.cf
[...]

# Save spam messages as a message/rfc822 MIME attachment instead of
# modifying the original message (0: off, 2: use text/plain instead)
#
report_safe 0

[...]

use_dcc 1
dcc_path /usr/local/bin/dccproc

use_pyzor 1
pyzor_path /usr/bin/pyzor

use_razor2 1
razor_config /etc/razor/razor-agent.conf
Afterwards, edit v310.pre
nano /etc/spamassassin/v310.pre
you'll have to check that the DCC, Razor and Pyzor plugins are enabled (DCC is disabled by default).

You can check your Spamassassin configuration with lint (use the -D flag for output):
spamassassin --lint
And you can update SA’s rules with sa-update:
sa-update --no-gpg
Now we are ready to start the SA daemon (will be automatically started at boot time):
/etc/init.d/spamassassin start

Now let's configure Postfix to talk with SpamAssassin.
First, edit /etc/postfix/master.cf, duplicate the existing dovecot transport and edit the new one to look as follows:
dovecot-spamass unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/bin/spamc -u ${recipient} -e /usr/lib/dovecot/deliver -d ${recipient}
This transport will pass the mail to spamc which will pass it to deliver after checking.
Now just change the transport in /etc/postfix/main.cf.
We are using a second transport to be flexible. In case anything should go wrong with Spamassassin we will just need to change the transport in main.cf back to just "dovecot" and we'll get the mail withouth SpamAssassin the loop.
So:
nano /etc/postfix/main.cf
and change:
virtual_transport = dovecot-spamass
dovecot-spamass_destination_recipient_limit = 1
The second line is essential if you want to be able to receive e-mails for multiple recipients!
That’s all you need on the Postfix side. Just restart it to use the new transport.
/etc/init.d/postfix restart
Basic checks to see if SpamAssassin filtering is working
At this point you should have already forwarded a domain DNS to the mail server (MX and all of that) so you should just check from your thunderbird client that all e-mail received have the X-Spam headers.
To verify the spam filtering just wait for some spam or user the GTUBE string inside the body of an e-mail:
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
Inserting this string should make SpamAssasin filter the mail as Spam.
Install the web administration panel
We'll be configuring the GrSoft Mail Manager. The sql file you imported earlier already created the basic tables for the 2.0 lenny version, different versions will use different DB and you'll need to change also the queries for postfix! The installation script will be creating more table for the mailmanager users and for the translations.
cd /var/www/
mkdir mail-manager
cd mail-manager

tar xvzf grs_mailmgr_v2_0-Lenny.tgz
chown -Rf www-data:www-data ../mail-manager
You should then add an appropriate Alias rule on the Apache virtualhost.
Now just connect to the web server, for example and follow the wizard specifying the same db and username as used previously with Postfix. If you interrupt the configuration the script will remember at what step you left it trough a cookie in your browser, keep that in mind if you experience any problem.
You should enter a valid e-mail address of an user of the system as the main MailManager (this user will be able to do anything to the mail server) and be sure to follow all the steps and when you finish succesfully: * Remove install.php * Remove conf/cnf_main_template.php * Remove folder install
rm -R install* conf/cnf_main_template.php
To get a nicer graphic interface just substitute the original files ("mgr_main.php" and "login.php") with the one provided with this guide (this is valid just for version 2.0 lenny!) and the connect to the manager at the address
The manager default languages are English and Deutsch, an Italian translation is a work in progress, it can all be done from the Mysql DB so it's very easy to add new languages.
More Spam control: adding SPF filtering
This part of the guide is already very well written onso this is almost a copy-paste.

If you are tired of faked emails from popular domains like eBay or Paypal then there is hope. And you can even protect your own domain from spammers sending in your name. It is about SPF which is short for sender policy framework. Basically the owner of a domain defines which IP addresses are allowed to send email. Let's take an example.
dig +short workaround.org txt
and you should see something like
"v=spf1 ip4:85.214.93.191 ip4:85.214.149.150 -all"
This entry means that if someone sends you an email with a sender email address of …@workaround.org then you should only accept it if it was sent from one of these two IP addresses. The "-all" at the end tells you that no other IP addresses should be accepted (FAIL). Another definition like "~all" means a SOFTFAIL - you should at least be suspicious and perhaps increase the spam score. (Actually "~all" is widely used but pretty useless. Either you know what you are doing and use "-all" or leave it off entirely. If you want to test if SPF workd then you could use "?all".) So if someone sent you an email from …@workaround.org from another IP address then you should drop it - it's spam.

Many organisations already have SPF records that you can use to reduce the amount of spam you receive. We could set an SPF entry also for our domains but that means we then have to force our user to send e-mail only from our smtp (or a few defined ones), we'll be skipping that for now and just checking SPF entries of sending email servers and reject email coming from unauthorized IP addresses, this will limit a lot of spam from spammers faking popular domains! (If you ever want to set up SPF for our own domain is as easy as inserting a new TXT record on the DNS, see www.openspf.org for a wizard!)

To check SPF entries we will use a Python daemon named tumgreyspf that you should have already installed at the beginning of the guide.
tumgreyspf is a policy daemon that does both greylisting and SPF checking of incoming emails. Using it is detailed in the /usr/share/doc/tumgreyspf/README.Debian file. Basically it boils down to adding one line to your smtpd_sender_restrictions (or smtpd_recipient_restrictions if you put everything in there) making use of it.
Just add the line check_policy_service unix:private/tumgreyspf on the recipient rescritions:
nano /etc/postfix/main.cf
smtpd_recipient_restrictions =

permit_sasl_authenticated,
reject_non_fqdn_sender,
reject_non_fqdn_recipient,
reject_unknown_sender_domain,
reject_unknown_recipient_domain,
reject_unauth_pipelining,
permit_mynetworks,
reject_unauth_destination,
reject_rbl_client zen.spamhaus.org,
check_policy_service unix:private/tumgreyspf,
permit
And to define the program that is called when using this policy service you need to add one line to your /etc/postfix/master.cf:
nano /etc/postfix/master.cf
The line to add:
tumgreyspf unix - n n - - spawn user=tumgreyspf argv=/usr/bin/tumgreyspf
To disable graylisting you need to edit the tumgreyspf configuration:
nano /etc/tumgreyspf/default.conf
CHECKERS = spf
Now reload your Postfix and that's it:
postfix reload
Checking that SPF is working as expected
When you receive an e-mail you should see the SPF check result on your /var/log/mail.log logfile.
Case: SPF okay
Every incoming email should now log an additional line from tumgreyspf. If the SPF check was positive then you will get:
tumgreyspf[24672]: sender SPF authorized: QUEUE_ID=""; identity=mailfrom;
client-ip=26.21.244.31; helo=squedge2.squ.edu.om

This means that the sender …@squ.edu.om was allowed in after checking the SPF entry.
Case: SPF fail
If the SPF check fails then you will see something like:
tumgreyspf[24672]: SPF fail - not authorized: QUEUE_ID=""; identity=mailfrom;
client-ip=41.234.18.141; helo=gmx.de;
envelope-from=…gmx.de;
receiver=…christoph-haas.de;
The email got rejected. One spam mail less in the world. :)
Case: SPF softfail
The third case is when the SPF entry does not enforce a FAIL (-all) but just uses SOFTFAIL (~all). In your log file it will look like:
tumgreyspf[20408]: domain owner discourages use of this host: QUEUE_ID="";
identity=mailfrom; client-ip=220.245.2.67; helo=220-245-2-67.static.tpgi.com.au;

Unfortunately the SOFTFAIL does not actually reject the email. But the sender still believes that this IP address should not be sending email in their name. Luckily tumgreyspf adds this information to a "Received-SPF" header into the email. Just like:
Received-SPF: Softfail (domain owner discourages use of this host) identity=mailfrom;
client-ip=61.146.93.243; helo=mail.163gd.com;

So you still have a chance to mark such emails in spam in your email client by filtering out emails having a "Received-SPF: Softfail" header. (Unfortunately tumgreyspf does not have a configuration option to treat SOFTFAIL as FAIL.)
Case: No SPF information
If the remote domain is ignorant and stupid and does not have any SPF entries yet then your log file will read:
Received-SPF: Neutral (access neither permitted nor denied) identity=mailfrom;
client-ip=80.65.65.222; helo=mail.unze.ba;

Server-side filters: Sieve
You already have a fully functioning mail server that even tags spam. But so far you left the actual task of sorting out the tagged spam to the user. We can do better by setting up server-side filters. The task ahead is to move all spam emails to a user's "Spam" folder. We are using the Sieve feature of Dovecot which is a mail filter like procmail (which does not work for virtual mailboxes). Sieve has a simple scripting language that allows us to forward all emails that are tagged by SpamAssassin to a "Spam" folder automatically. At the end of the /etc/dovecot/dovecot.conf file you will find a "plugin" section. Within there you can define a "sieve_global_path" which points to a default filter file that takes effect if the recipient user hasn't defined any per-user filtering rules.

By the way the term "server-side filtering" means that the rules are executed on the server automatically. As opposed to "client-side filtering" which is configured in the mail program on the user's computer. Apparently server-side filtering is preferred as it happens even if the user is offline. And it gives you interesting options such as a vacation autoresponder or filtering based on header fields.

Sieve filtering can be tricky because the dovecot module has been changed a number of times for different versions of dovecot, so be carefull on what you're doing, assuming you have the same version of dovecot as in this guide you should open the dovecot configuration file and add two lines on the "plugin" section:
nano /etc/dovecot/dovecot.conf
and edit:
[...]
plugin {
[...]
sieve=~/.dovecot.sieve
sieve_before = /var/vmail/spam.sieve
Now let's add a basic sieve script that will be executed before the personal script of each user:
nano /var/vmail/spam.sieve
this sieve filter will assume the users want spam on a directory named "Spam":
require ["fileinto"];
# Move spam to spam folder
if header :contains "X-Spam-Flag" ["YES"] {
fileinto "Spam";
stop;
}
Restart dovecot:
chown vmail.vmail /var/vmail/spam.sieve
/etc/init.d/dovecot restart
At this point you should check that a SPAM email gets moved in the Spam folder for each users, if the "Spam" folder does not exist for a new user it will get automatically created.. so be sure that the every user subscribes to it from their mail client.
More advanced users will the be able to add personal rules on their sieve file trough a special plugin on the webmail interface.
Statistics: Awstats
Analysing the mail log gives a better understanding on how the mail server is being used, we can use the Awstats tool (the same that is widely used for basic web log analysis).
You should download itand then install it:
unzip awstats-7.0.zip
mv awstats-7.0 /usr/local/awstats
cd /usr/local/awstats/tools/
perl awstats_configure.pl
follow the wizard: * give the path of apache conf "/etc/apache2/httpd.conf" * define the first configuration file as just "mailserver" * say yes to all the questions At this point you'll have to configure awstats to analyse properly your mail server:
nano /etc/awstats/awstats.mailserver.conf
To analyse Postfix logs you'll have to edit this line:
LogFile="perl /usr/local/awstats/tools/maillogconvert.pl standard < /var/log/mail.log |"
and then be sure to change this options:
LogType=M
LogFormat="%time2 %email %email_r %host %host_r %method %url %code %bytesd"
LevelForBrowsersDetection=0
LevelForOSDetection=0
LevelForRefererAnalyze=0
LevelForRobotsDetection=0
LevelForWormsDetection=0
LevelForSearchEnginesDetection=0
LevelForKeywordsDetection=0
LevelForFileTypesDetection=0
ShowMenu=1
ShowSummary=HB
ShowMonthStats=HB
ShowDaysOfMonthStats=HB
ShowDaysOfWeekStats=HB
ShowHoursStats=HB
ShowDomainsStats=0
ShowHostsStats=HBL
ShowAuthenticatedUsers=0
ShowRobotsStats=0
ShowEMailSenders=HBML
ShowEMailReceivers=HBML
ShowSessionsStats=0
ShowPagesStats=0
ShowFileTypesStats=0
ShowFileSizesStats=0
ShowDownloadsStats=0
ShowBrowsersStats=0
ShowOSStats=0
ShowOriginStats=0
ShowKeyphrasesStats=0
ShowKeywordsStats=0
ShowMiscStats=0
ShowHTTPErrorsStats=0
ShowSMTPErrorsStats=1
In the same file you can also customize the "Logo" directive to brand the page with a nice logo.
Now let's test the configuration:
mkdir /var/lib/awstats
perl /usr/local/awstats/wwwroot/cgi-bin/awstats.pl -update -config=mailserver
/etc/init.d/apache2 restart
We should already see the statistics at the page:
Let's configure a line on cron:
crontab -e
as follow to update statistics every 55 minutes:
*/55 * * * * /usr/local/awstats/tools/awstats_updateall.pl now > /var/log/awstats.log
Webmail: Roundcube with Sieve plugin
Roundcube is a webmail interface that after a slow-start a few years ago is now gaining huge popularity thanks to an outstanding graphic interface.
You can download it from www.roundcube.net and then uncompress the content in /var/www/webmail/. Let's install it, from a terminal customize the following query with a good random password (write it down, you will need it later on):
mysql -u root -p
> CREATE DATABASE roundcubemail /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost

IDENTIFIED BY 'password';
> quit
then let's import the empty database:
mysql -u root -p roundcubemail < SQL/mysql.initial.sql
At this point you can take advantage of the automatic configuration, just make sure you have the correct permissions:
chown -R www-data:www-data /var/www/webmail
and point your browser at and follow the wizard checking that everything is sound and giving the appropriate information, take special care with: * Select the "ip_check" functionality and for identities_level choose "one identity with possibility to edit all params but not email address. * Insert the mysql password you wrote down earlier. * For "default_host" just enter "localhost" * On "junk_mbox" insert "Spam" as defined earlier in the Sieve script * For "smtp_server" just enter "localhost" * Select "Use the current IMAP username and password for SMTP authentication" * Enable "preview_pane", the users usually want it Now copy the two configuration file in the /var/www/webmail/config/ directory.

On the final step Roundcube allows you to test both smtp and imap: do it!
Remember to delete the installar folder for security purpose:
rm -R /var/www/webmail/installer
At this point the basic roundcube should be working fine, let's configure the Sieve and Password plugin editing manually the file config/main.inc.php:
nano /var/www/webmail/config/main.inc.php
and editing the line:
$rcmail_config['plugins'] = array('managesieve','password');
The Sieve filter plugin should be already be working out-of-the-box (remember that on dovecot the "managesieve" protocol must be enabled!) and filtering everything after the spam filter, we just have to configure the password changing routine:
cp /var/www/webmail/plugins/password/config.inc.php.dist /var/www/webmail/plugins/password/config.inc.php
nano /var/www/webmail/plugins/password/config.inc.php
and change these two options:
$rcmail_config['password_driver'] = 'sql';
$rcmail_config['password_db_dsn'] =
$rcmail_config['password_query'] = 'UPDATE virtual_users SET password=MD5(%p) WHERE email = %u AND password=MD5(%o) LIMIT 1';
Now test it, should be working!

Remember to change the skin with the correct branding logo.
Testing procedure
Now you should have everything that it takes for a good mail server, let's test it out:
Connect to and verify that it redirect you tocheck that the SSL certificate is ok
Connect to SMTP without SSL (port 25) and without password and verify that you CAN'T send e-mail to external domains (i.e. Gmail)
Connect to SMTP without SSL (port 25) and WITH password and verify that you CAN send e-mail to external domains (i.e. Gmail)
Connect to SMTP with SSL (port 465) and without password and verify that you CAN'T send e-mail to external domains (i.e. Gmail) and that the SSL certificate is ok
Connect to SMTP with SSL (port 465) and WITH password and verify that you CAN send e-mail to external domains (i.e. Gmail)
Connect to POP3 without SSL (port 110) and verify that you can download your messages
Connect to POP3 with SSL (port 995) and verify that you can download your messages and that the SSL certificate is ok
Connect to IMAP4 without SSL (port 143) and verify that you can download your messages
Connect to IMAP4 with SSL (port 993) and verify that you can download your messages and that the SSL certificate is ok
Send an ordinary e-mail from a few ordinary domains and verify it get's trough fine, play with attachment sizes, html, etc.
Send a spam e-mail from an ordinary e-mail address (i.e. GTUBE) and verify it gets moved on the "Spam" folder (this checks both SpamAssassin and the sieve part)
Check the RBL blocker by sending an email (any email)The Crynwr system robot should answer you to tell you if your server is correctly blocking SBL-listed IPs or not, this could take even an hour, a good way to tell if everything works fast is to monitor the connection on the server ("tcpflow -c port 25") while sendint the e-mail to
Check the SPF filtering as described in the guide on the logs and/or by sending a fake email from a domain with SPF enabled (if you have access to it)
Try to add users/domain from the administration panel and see if the server works for those
Try to use the webmail (both receiving and sending)
Test the sieve filter by defining a new filter on the webmail
Test the webmail, the folders, etc.

Postfix Server Management

This tutorial has an overview of the basic commands and tool needed to manage a Postfix mail server mixed with a few things that are always good to know when managing a mail server. Usage of tools like postqueue or postcat is covered and also explanation of all the important directories and files used by dovecot.
An overview
On this tutorial we'll walk you trough a few things that are always good to know when managing a mail server, mainly:
what are the basic management commands
where are the important directories
where the log files are stored
Dovecot directories and files
User directory structure
Every user has a directory inside the domain directory ( will be found on /var/vmail/example.com/lorenzo/), inside this directory there are quite a lot of hidden files and it's good to know their purpose, let's look at the directory tree:
/var/vmail/example.com/lorenzo/
|___.dovecot.sieve -> Maildir/sieve/roundcube.sieve
|___.dovecot.svbin
|___Maildir

|___cur
|___new
|___tmp
|___.Sent
- .dovecot.sieve
This is a symbolic link to the file with the sieve rules generated by the roundcube plugin.
- .dovecot.svbin
This is the compiled version of the .dovecot.sieve file, Sieve rules needs to be compiled, this happens automatically the first time that the sieve script is executed. If you ever need to set more elaborate rules you can write them manually on the .dovecot.sieve file and remember to remove the compiled version. Be careful that Roundcube will attempt to overwrite your change when saving a new set of rules.
- Maildir
This is the main Maildir directory where all the messages are stored, it contains three main directories and all the IMAP subfolders as hidden directories
- cur
This is the INBOX folder containing all the messages already seen by the user's mail client.
- new
This is the INBOX folder containing all the messages already to be seen (or downloaded for POP3) by the user's mail client.
- tmp
This directory contains mail that are in the process of being delivered to the user.

Additional folders that the user (or his mail application) could be creating are "hidden", their name begin with a period: such as .Drafts or .Sent.
Each folder itself contains the same three subdirectories, tmp, new, and cur, and an additional zero-length file named maildirfolder, whose purpose is to inform any mail delivery agent that it's really delivering to a folder, and that the mail delivery agent should look in the parent directory for any maildir-related information.
Folders are not physically nested. A folder subdirectory, such as .Sent does not itself contain any subfolders. The main maildir contains a single, flat list of subfolders. These folders are logically nested, and periods serve to separate folder hierarchies. For example, .Sent.2002 is considered to be a subfolder called "2002" which is a subfolder of "Sent".
Files timestamp
Filesystem date on files in the mail folder (/var/vmail) are important and used by the imap server (dovecot) to check the e-mails date so when doing rsync, scp, etc be sure to copy all the metadata of this files. For example be sure to use:
rsync -a
when syncing the directory for backup purpose (also check that the remote filesystem mantains the timestamp).
Log files
/var/log/mail.log
This file contains all the postfix logs with the connections to the SMTP and the spam check informations.
/var/log/mail.err
This file contains all the postfix server errors, it should usually be empty.
/var/vmail/dovecot-deliver.log
This file contains all the dovecot logs for the stored mail, you should see the Sieve filtering in action and the status of every mail received by dovecot.
Postfix commands
postqueue
The postqueue command allow the administrator to view and manage the postfix mail queue but does not allow to delete message or change it's status, here are listed the main options:
postqueue -p
Show the queue list. On each line you can see the file ID, message size, arrival time, sender, and the recipients that still need to be delivered. If mail could not be delivered upon the last attempt, the reason for failure is shown. The queue ID string is followed by an optional status character:

! The message is in the hold queue, i.e. no further delivery attempt will be made until the mail is taken off hold.
postqueue -f
This command attempt to flush the queue, attempt to deliver all queued mail even undeliverable mail with previous errors.
postsuper
This command enable the superuser to do maintenance jobs on the Postfix queue. This command should be used with extreme care since it's very easy to mess something up and delete all the mails in the queue.
postsuper -d queue_id
Delete the message with a certain queue_id (see the "man" documentation for further info).
postsuper -h queue_id
Put the message on hold so postfix stops the delivery attempts.
postsuper -H queue_id
Release a message that was in hold moving it in the deferred queue.
postcat
This command prints the content of a mail in a human-readable form. You should pass as a parameter the filename of the mail message.