Child pages
  • Serversetup multi-tenant Zarafa+Postfix+SASL+Dspam+Clamav+openLDAP (Ubuntu 10.04 LTS)

Versions Compared


  • This line was added.
  • This line was removed.
  • Formatting was changed.




This guide is deprecated as of 2014-12-26 in favor of a new one:

Serversetup multi-tenant Zarafa+Postfix+SASL+SpamAssassin+Clamav+openLDAP (Ubuntu 14.04 LTS)


See further below for the old guide. Thank you for your attention.





































Zarafa Groupware and dependent infrastructure setup guidelines.


Gliffy Diagram



As nearly all online guides about setting up a useable zarafa server lack in one or another detail, here comes another attempt of describing the process. Throughout the guide only lines in config files that need to be changed are shown.
This guide assumes:


  • Note:
    • This is NOT a copy-and-paste how-to!
    • The domain '' is used, replace all instances with your own domain (in ldap too, like: dc=example,dc=com).
    • The external interface is assumed to have the IP Replace with your own external interface address.
    • The internal interface is assumed to have the IP Replace with your own internal interface address.
    • The password 'secret' will be used for all passwords. Replace with DIFFERENT, STRONG passwords accordingly!
    • This setup assumes a local MySQL database. If you use a remote, dedicated database you will need to change the database settings and grants in various config files or the database itself. 


  • Distro: Ubuntu 10.04 LTS 64bit
    • Zarafa 7.0 from
    • MySQL 5.1 (or 5.5), openLDAP, postfix, dspam from Ubuntu Repository
    • phpldapadmin, z-push from source


For this setup two different certificates are needed. One for the Webserver ( and one for the mail server ( It is advised to use official certificates, however for testing purposes you can create your own ones with openssl.

  • Note:
    • The web certificates will be called 'web.crt' and 'web.key'. Replace with your own certificate filenames.
    • The mail certificates will be called 'mail.crt' and 'mail.key'. Replace with your own certificate filenames.

Install Packages

Grab packages from the zarafa-site, install per their instructions. Also install postfix, dspam, clamav, slapd and mysql. The zarafa packages should have already installed apache2. If not, something is definitely wrong...

Code Block
~# aptitude install postfix postfix-ldap dspam libdspam7 libdspam7-drv-mysql mysql-server-5.1 slapd ldap-utils php5-ldap clamav clamav-freshclam sasl2-bin


MySQL Setup

Not much to do here, just create databases, users and permissions for zarafa and dspam:

Code Block
~# mysql -uroot -p
mysql> create database zarafa;
mysql> create database dspam;
mysql> grant all on zarafa.* to 'zarafa'@'localhost' identified by 'secret';
mysql> grant all on dspam.* to 'dspam'@'localhost' identified by 'secret';
mysql> flush privileges;


LDAP Setup

LDAP Server Setup

Probably the part that generates the most head-scratching. Although the latest Ubuntu LTS server already uses the 'cn=config' format zarafa admin guide still works with the old 'slapd.conf' format, so we stick with that too.
First adjust the default-file:


  • Hint: If the server throws an error change the log level to '8' or '4', this should output enough info to give you an idea what is wrong. LDAP logs to syslog in Ubuntu.

LDAP Admin Setup

Create a .ldif file to load into LDAP:


Code Block
~# ldapadd -x -W -D cn=admin,dc=example,dc=com -f /tmp/admin.ldif


Install phpldapadmin

Grab the latest .tar.gz from sourceforge and unzip to '/var/www/'. Create a symlink for easier management, fix permissions too. It's ok to give it to 'root', apache only needs 'o+rX' on the files.

Code Block
~# tar xzvf phpldapadmin.tar.gz -C /var/www
~# cd /var/www
~# ln -s phpldapadmin-w.x.y.z phpldapadmin
~# chown -R root: phpldapadmin-w.x.y.z
~# cp phpldapadmin/config/config.php.example phpldapadmin/config/config.php


Configure phpldapadmin

The config is somewhat big but most are comments and defaults that need not to be modified. Again only lines that were modified are shown.


No Format
# The userPassword by default can be changed
# by the entry owning it if they are authenticated.
# Others should not be able to see it, except the
# admin entry below
# These access lines apply to database #1 only
access to attrs=userPassword,shadowLastChange
        by dn="cn=admin,dc=example,dc=com" write
        by anonymous auth
        by self write
        by * none

# !! NEW !! #
access to *
        by dn="uid=zarafaservice,dc=example,dc=com" read
# !! NEW !! #

# The admin dn has full write access, everyone else
# can read everything.
access to *
        by dn="cn=admin,dc=example,dc=com" write
        by * read


Install Zarafa phpldapadmin templates

Download the templates and extract the content to /var/www/phpldapadmin.

Create a Company, User and Alias

With the templates in place, log into phpldapadmin again and:


This user and the mailalias will be needed later for testing the functionality of the server.

Zarafa Server Setup

Be sure to read the admin guide, this will cover only what needs to be changed so zarafa will work in this specific setup. All Zarafa server configuration files are stored in '/etc/zarafa'.
Zarafa v.7 Administrator Manual

zarafa-server and ldap.conf

The option 'enable_hosted_zarafa' will switch on multi-tenancy. If you don't want this feature set it to 'false'.


No Format
ldap_bind_user = userid=zarafaservice,dc=example,dc=com

# LDAP bind password
# Optional, default = empty (no password)
ldap_bind_passwd = secret

# Top level search base, every object should be available under this tree
ldap_search_base = dc=example,dc=com

# attribute name which is/(should: was) used in ldap_user_search_filter
ldap_object_type_attribute = objectClass
ldap_user_type_attribute_value = zarafa-user
ldap_group_type_attribute_value = zarafa-group
ldap_contact_type_attribute_value = zarafa-contact
ldap_company_type_attribute_value = organizationalUnit
ldap_addresslist_type_attribute_value = zarafa-addresslist
ldap_dynamicgroup_type_attribute_value = zarafa-dynamicgroup

# Optional, default = empty (match everything)
# For active directory, use:
#   (objectCategory=Person)
# For LDAP with posix users:
#   no need to use the search filter.
ldap_user_search_filter = (objectClass=zarafa-user)

# unique user id for find the user
# Note: contacts also use this field for uniqueness. If you change this,
# you might need to update the zarafa.schema file too, and change
# the MUST uidNumber to whatever you set here.dnl
ldap_user_unique_attribute = entryUUID

# Type of unique user id
# default: text
# For active directory, use:
#               binary
# For LDAP with posix user, use:
#               text
ldap_user_unique_attribute_type = text

# If set to bind, users are authenticated by trying to bind to the
# LDAP tree using their username + password.  Otherwise, the
# ldap_password_attribute is requested and checked.
ldap_authentication_method = bind

# unique company id for find the company
# Active directory: objectGUID
# LDAP: ou
ldap_company_unique_attribute = ou

# Optional, default = ou
# Active directory: ou
# LDAP: ou
ldap_companyname_attribute = ou

# Mapping from the quota attributes to a number of bytes.  Qmail-LDAP
# schema uses bytes (1), ADS uses kilobytes (1024*1024).
# We need to ajust this to 1MB in Bytes so we can use MB in phpldapadmin,
# otherwise quota won't work!
ldap_quota_multiplier = 1048576



This is the service which talks to postfix and delivers mails to zarafa postboxes. The dagent must be enabled in zarafa's default file. We adjust some values for spam management here that will later tie in nicely with dspam.


No Format
# drop privileges and run the process as this user
run_as_user             = zarafa

# drop privileges and run the process as this group
run_as_group            = zarafa

# Login to the Zarafa server using this SSL Key
sslkey_file = /etc/zarafa/ssl/mail.crt

# The following e-mail header will mark the mail as spam, so the mail
# is placed in the Junk Mail folder, and not the Inbox.
spam_header_name = X-DSPAM-Result

# If the above header is found, and contains the following value
# the mail will be considered as spam.
spam_header_value = Spam



This service talks pop(s) and imap(s) to the outside world.

No Format
# Set this value to a name to show in the logon greeting to clients.
# Leave empty to use DNS to find this name.
server_hostname =

# Whether to show the hostname in the logon greeting to clients.
server_hostname_greeting = yes

# drop privileges and run the process as this user
run_as_user             = zarafa

# drop privileges and run the process as this group
run_as_group            = zarafa

# default connection to the Zarafa server
# Please refer to the administrator manual or manpage why HTTP is used rather than the UNIX socket.
server_socket =

# enable/disable POP3, and POP3 listen port
pop3_enable     =       yes
pop3_port       =       110

# enable/disable Secure POP3, and Secure POP3 listen port
pop3s_enable    =       yes
pop3s_port      =       995

# enable/disable IMAP, and IMAP listen port
imap_enable     =       yes
imap_port       =       143

# enable/disable Secure IMAP, and Secure IMAP listen port
imaps_enable    =       yes
imaps_port      =       993

# File with RSA key for SSL
ssl_private_key_file    =       /etc/zarafa/ssl/mail.key

#File with certificate for SSL
ssl_certificate_file    =       /etc/zarafa/ssl/mail.crt



This is the iCal / CALDAV Server. The preferred method is CALDAV though.

No Format
# wether normal connections can be made to the ical server
ical_enable = yes

# drop privileges and run the process as this user
run_as_user             = zarafa

# drop privileges and run the process as this group
run_as_group            = zarafa

# port which the ical server listens on for normal connections
ical_port = 8080

# default connection to the Zarafa server
# Please refer to the administrator manual or manpage why HTTP is used rather than the UNIX socket.
server_socket =

# wether ssl connections can be made to the ical server
icals_enable = yes

# port which the ical server listens on for ssl connections
icals_port = 8443

# File with RSA key for SSL
ssl_private_key_file = /etc/zarafa/ssl/web.key

# File with certificate for SSL
ssl_certificate_file = /etc/zarafa2/ssl/web.crt



This service delivers mail to postfix to be sent into the intertubes. Luckily nothing must be adjusted here except the user and group settings.

No Format
# drop privileges and run the process as this user
run_as_user             = zarafa

# drop privileges and run the process as this group
run_as_group            = zarafa


Z-Push Setup

Easy. Just get the source and unpack to '/var/www'. Create a symlink as we did with phpldapadmin before and you are done. (The same company that develops zarafa also develops z-push so all the defaults fit for the zarafa deployment). The directory 'state' has to be writeable by the webserver, so don't forget to chown it to the www-data-user. We also need to set up an apache alias so mobile devices that use Active Sync work correctly:


Code Block
 Alias /Microsoft-Server-ActiveSync /var/www/z-push/index.php


Apache2 Setup

We have to enable the rewrite and ssl modules and disable the default website. Also ports.conf has to be adjusted a little, otherwise apache barfs at startup.


Code Block

  RewriteEngine   On
  RewriteCond     %{HTTPS}        off
  RewriteRule     ^(.*)$          https://%{SERVER_NAME}%{REQUEST_URI} [L,R]




 SSLEngine              on
 SSLCertificateFile     /etc/zarafa/ssl/web.crt
 SSLCertificateKeyFile  /etc/zarafa2/ssl/web.key

 DocumentRoot           /var/www

 Alias /phpldapadmin    /var/www/phpldapadmin
 Alias /webaccess       /usr/share/zarafa-webaccess

  <Directory /usr/share/zarafa-webaccess/>
    DirectoryIndex index.php
    Options -Indexes +FollowSymLinks
    AllowOverride Options

    Order allow,deny
    Allow from all


Syncing LDAP data to Zarafa

Every time you change things in LDAP you have to sync those changes to the Zarafa DB. Invoke the command 'zarafa-admin --sync' to do so. The option '-l' displays all users, use this to test if the synchronization worked.


That's it. Now you should be able to log in to the Zarafa Webaccess with the user we configured with phpopenldap before.

postfix, sasl, dspam and clamav setup

postfix must be configured to do ldap user lookups which is done via and Futher and need to be adjusted to scan mail for spam and viruses and deliver them to dagent via lmtp in the end. To authenticate users who are sending mails from external addresses we will use SASL with the remote IMAP (rimap) method, which basically performs a IMAP-login to check if the supplied password is correct.


This postfix config also contains enhanced recipient restrictions and mailq timeouts. If you do not know what they do you shouldn't use them.

No Format
smtpd_banner            = $myhostname ESMTP NO UCE
myhostname              =
biff                    = no
append_dot_mydomain     = no
mynetworks              =,
recipient_delimiter     = +
inet_interfaces         = all
myorigin                = $myhostname
mydestination           = $myhostname, localhost

virtual_mailbox_domains =,,
virtual_mailbox_maps    = ldap:/etc/postfix/
virtual_alias_maps      = ldap:/etc/postfix/
virtual_transport       = lmtp:

smtpd_sasl_auth_enable          = yes
broken_sasl_auth_clients        = yes

# TLS encryptiion
smtpd_tls_security_level        = may
smtpd_tls_auth_only             = yes
smtpd_tls_cert_file             = /etc/postfix/keys/postfix.crt
smtpd_tls_key_file              = /etc/postfix/keys/postfix.key
smtpd_tls_CAfile                = /etc/postfix/keys/postfix.pem
smtpd_tls_loglevel              = 0
smtpd_tls_received_header       = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source               = dev:/dev/urandom

# check incoming mail for 'stuff'
smtpd_recipient_restrictions =

smtpd_data_restrictions =

# client restrictions
smtpd_client_restrictions =
        check_client_access pcre:/etc/postfix/dspam_filter_access

# anybody out there?
smtpd_helo_restrictions =

# who may send
smtpd_sender_restrictions =

# deferred mail intervals

# (default: 300 seconds; before Postfix 2.4: 1000s)
# How often the queue manager scans the queue for deferred mail.
queue_run_delay                 = 900

# (default: 300 seconds; before Postfix 2.4: 1000s)
# The minimal amount of time a message won't be looked at, and the minimal amount of time to stay away from a "dead" destination.
minimal_backoff_time            = 450

# (default: 4000 seconds)
# The maximal amount of time a message won't be looked at after a delivery failure.
maximal_backoff_time            = 1800

# (default: 5 days)
# How long a message stays in the queue before it is sent back as undeliverable. Specify 0 for mail that should be returned immediately after the first unsuccessful delivery attempt.
maximal_queue_lifetime          = 14

# (default: 5 days, available with Postfix version 2.1 and later)
# How long a MAILER-DAEMON message stays in the queue before it is considered undeliverable. Specify 0 for mail that should be tried only once.
bounce_queue_lifetime           = 14

# (default: 20000)
# The size of many in-memory queue manager data structures. Among others, this parameter limits the size of the short-term, in-memory list of "dead" destinations. Destinations that don't fit the list are not added.
qmgr_message_recipient_limit    = 1000000

# max message size (15M)
message_size_limit              = 15360000

The master transport file. Transport decisions are made here, in our case:
internet -> smpt:postfix -> socket:dspam -> socket:clamav -> dspam -> smtp:postfix -> lmtp:dagent


No Format
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       -       -       -       smtpd
 -o content_filter=lmtp:unix:/var/run/dspam/dspam.sock
submission inet n       -       -       -       -       smtpd
 -o content_filter=lmtp:unix:/var/run/dspam/dspam.sock
smtps     inet  n       -       -       -       -       smtpd
 -o smtpd_tls_wrappermode=yes
 -o smtpd_sasl_auth_enable=yes
pickup    fifo  n       -       -       60      1       pickup
cleanup   unix  n       -       -       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       -       1000?   1       tlsmgr
rewrite   unix  -       -       -       -       -       trivial-rewrite
bounce    unix  -       -       -       -       0       bounce
defer     unix  -       -       -       -       0       bounce
trace     unix  -       -       -       -       0       bounce
verify    unix  -       -       -       -       1       verify
flush     unix  n       -       -       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       -       -       -       smtp
# When relaying mail as backup MX, disable fallback_relay to avoid MX loops
relay     unix  -       -       -       -       -       smtp
        -o smtp_fallback_relay=
#       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq     unix  n       -       -       -       -       showq
error     unix  -       -       -       -       -       error
retry     unix  -       -       -       -       -       error
discard   unix  -       -       -       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       -       -       1       anvil
scache    unix  -       -       -       -       1       scache

# dspam inet    n       -       n       -       -       smtpd
        -o content_filter=
        -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
        -o smtpd_helo_restrictions=
        -o smtpd_client_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o mynetworks=
        -o smtpd_authorized_xforward_hosts=


ldap users and aliases

These files control ldap user and alias lookups


No Format
server_host     = localhost
search_base     = dc=example,dc=com
version         = 3
bind            = yes
bind_dn         = uid=zarafaservice,dc=example,dc=com
bind_pw         = secret
scope           = sub
query_filter    = (zarafaAliases=%s)
result_attribute        = mail


Test LDAP connectivity

Test your setup by issuing the following commands. In both cases the email address of the user should be displayed.

Code Block
~# postmap -q <insert-username-here> ldap:/etc/postfix/
~# postmap -q <insert-user-alias-here> ldap:/etc/postfix/



We have to add postfix to the sasl group and edit two files to make it work:


No Format
titleadd postfix to sasl
~# gpasswd -a postfix sasl
~# service postfix restart
~# service saslauthd restart


DSpam and ClamAV

DSpam can pass mails on the fly to clamav for virus scanning, all it need is a socket to pump the mails into. Therefore we need to adjust clamav a little. In the end we also set up 'group'-file for dspam so all users share a 'merged' anti-spam database. Furthermore we will integrate dspam with the Zarafa webinterface, so users can mark messages as spam or ham themselves.


No Format
titleexample dspam database setup
~# mysql -uroot -p dspam < /usr/share/doc/libdspam7-drv-mysql/mysql_objects-speed.sql



No Format
# --- MySQL ---
MySQLServer     /var/run/mysqld/mysqld.sock
MySQLPort         3306
MySQLUser       dspam
MySQLPass       secret
MySQLDb         dspam
MySQLConnectionCache    20
MySQLUIDInSignature    on


No Format
# Everything beginning with either ham or spam avoids the filter
/^(spam|ham)@.*$/ OK
# The rest is redirected to be filtered
/./ FILTER dspam:dspam


Webaccess DSpam Integration

First get the plugin from the community page. Unzip it directly into the webaccess/plugins folder, adjust the config a little and fix some permissions on the dspam config files (dspam complains otherwise). To activate the plugin's debug log, set the parameter 'dspam_log' to a path instead of 'false'.


Now purge your browser cache. A new 'Junk/No Junk' item should appear in the right-click menu. Marking elements as junk will move them into the 'Trash' folder and inject them into dspam, training it as spam. Unmarking will leave the message as it is, but train it as ham. Check if the plugin is working correctly in the debug log.


No Format
LocalSocket /var/run/clamav/clamd.ctl
FixStaleSocket true
LocalSocketGroup clamav
LocalSocketMode 666
User clamav
AllowSupplementaryGroups true
ScanMail true
ScanArchive true
ArchiveBlockEncrypted false
MaxDirectoryRecursion 15
FollowDirectorySymlinks false
FollowFileSymlinks false
ReadTimeout 180
MaxThreads 12
MaxConnectionQueueLength 15
LogSyslog true
LogFacility LOG_LOCAL6
LogClean false
LogVerbose false
PidFile /var/run/clamav/
DatabaseDirectory /var/lib/clamav
SelfCheck 3600
Foreground false
Debug false
ScanPE true
ScanOLE2 true
ScanHTML true
DetectBrokenExecutables false
ExitOnOOM false
LeaveTemporaryFiles false
AlgorithmicDetection true
ScanELF true
IdleTimeout 30
PhishingSignatures true
PhishingScanURLs true
PhishingAlwaysBlockSSLMismatch false
PhishingAlwaysBlockCloak false
DetectPUA false
ScanPartialMessages false
HeuristicScanPrecedence false
StructuredDataDetection false
CommandReadTimeout 5
SendBufTimeout 200
MaxQueue 100
ExtendedDetectionInfo true
OLE2BlockMacros false
StreamMaxLength 25M
Bytecode true
BytecodeSecurity TrustSigned
BytecodeTimeout 60000
OfficialDatabaseOnly false
CrossFilesystems true
TCPSocket 3310


Regular Maintenance

Drop this file into '/etc/cron.d'. It's pretty self-explanatory, however you might want adjust the values and/or intervals.

No Format
# minute (0-59),
# |     hour (0-23),
# |     |       day of the month (1-31),
# |     |       |       month of the year (1-12),
# |     |       |       |       day of the week (0-7 with 0=7=Sunday).
# |     |       |       |       |       user
# |     |       |       |       |       |       command

# sync LDAP to Zarafa regularly
*/15    *       *       *       *       root    /usr/bin/zarafa-admin --sync

# purge soft-deleted items after 30 days
3       30      *       *       *       root    /usr/bin/zarafa-admin --purge-softdelete 30


Testing / Verifying the setup

  • Send Mails via
    • WebAccess
    • pop/pops
    • imap/imaps
  • Deliver mails
    • check MTA logs
    • check dspam information in mailhaeders
    • check dspam mail (dspam_stats -H)



Various readers for proofreading and pointing out errors and/or ambiguous statements. 

This page has been viewed  times.


Additions, comments, critisicm? mail to: b2c[at]