Page tree
Skip to end of metadata
Go to start of metadata


It is important to realize that each and every environment has its own "recipe" for best performance.

This document is intended as a base to come up with a setup from which further enhancing / analyzing should be done.

As new insights are realized they will be added to this document.


In order to achieve better performance it is recommended to tune the Kopano server settings as well as other components such as MYSQL, LDAP and Apache


This document is intended to be used by experienced system administrators and engineers who have in-depth knowledge of both Linux and MySQL environments.


Use these suggestions at your own risk and only if you know what you are doing.

These instructions are intended as pointers and not as a definitive configuration, offering the best performance for each and every environment. 


These recommendations are valid for any Kopano server being used regardless if they function as a home server or archive server.

The so called zero user server sometimes used in conjunction with hosts running WebApp on a separate machine may need a different tuning.

We strongly recommend validating all parameters in a testing environment before deploying these in a production environment.

Kopano configuration

Kopano server.cfg
# requires to set the thread_stack to 512K in my.cnf
enable_sql_procedures = yes
# 8 threads is mostly sufficient for up to 500 users
# Other rule of thumb is to have 4 threads per cpu core
threads = 8

Things you can disable in the default configuration and instead run less frequently with a cronjob.

sync_gab_realtime = no
softdelete_lifetime = 0

Periodically run from a cronjob:

  • kopano-admin --sync (recommendation every 30 minutes, or manually when you just have made changes in LDAP)
  • kopano-admin --purge-softdelete 30 (recommendation daily outside of production hours)

The rest of the tunable parameters

Kopano's cache system is optimized for short sessions. If you encounter that your system is constantly swapping and you cannot put more ram in your server it might be better to reduce these caches, than to have ram of kopano-server and mysql put into swap.

Kopano server.cfg
# Should be set as high as you can afford to set it. As it is very important to the overall performance of Kopano. As a rule of thumb it should at least be set to 25% of your ram.
cache_cell_size = 2048M

# caches all objects and their folder hierarchy
cache_object_size = 100kb / user
# contains all unique id's of objects
cache_indexed_object_size = 512kb / user
# Up to 500 users per 1M
cache_quota_size = 1M
# 60 seconds is more than sufficient
cache_quota_lifetime = 1
# Up to 500 users per 1M
cache_acl_size = 1M

# Up to 500 users per 1M
cache_store_size = 1M
# 25M per 500 users
cache_userdetails_size = 25M

New proposed defaults

cache_object_size = 16+M

 cache_indexedobject_size = 32+M


Mysql configuration

In general we recommend to use mysql 5.6 or higher for performance reasons, and sugges to have the databases stored on either EXT4 or XFS filesystems.

Depending on the mysql version some of the settings below might not be available.

Warning: Changing settings like innodb_data_file_path and innodb_log_file_size require either a dump and restore or might require you to delete logfiles. Failure to do so will result in a non-working Mysql setup.

Mysql my.cnf
# This can be optionally uncommented. (check if supported on your mysql version)
transaction-isolation = READ-COMMITTED
# Careful this might also needs binlog_format=ROW if you are using a binlog.
#verify# if binlog_format=statement.

# Should be the minimum amount of kopano(server.cfg) threads(default 8) + thread_limit(default 40) + 9.
max_connections = 57

# Best value is 32M, for smaller environments 16M is ok too.
max_allowed_packet = 32M

# should not be set higher than this, since it has to be allocated before being used
tmp_table_size = 64M
max_heap_table_size = 64M

# max size 2M (regardless of size of environment)
sort_buffer_size = 2M
join_buffer_size = 2M

# Good value is mumber of threads configured + 1
# nice writeup about actual scaling of thread_cache_size
# #verify# number of threads to be dermineds
thread_cache_size = 4
# Only available on mysql 5.5 and higher as above. Good figure the amount is cores/2, depending of usage give read more threads.
innodb_write_io_threads = 4
innodb_read_io_threads = 4

# (Kopano tables + max mysql connections) * 10, for example (26 + 24) * 10
# #verify# can be checked for example with "mytop". when you have a low "key efficiency" table_cache has to be increased
# table_open_cache was known as table_cache in MySQL 5.1.2 and earlier.
table_open_cache = 500 # DO NOT SET IT TOO HIGH!

# In order to use enable_sql_procedures = yes in Kopano server.cfg 512K is needed at least.
thread_stack = 512K

# RHEL6 do no use any query cache size !! kills performance
query_cache_size = 64M
query_cache_limit = 2M

# On a shared system (running both Kopano 30% and Mysql 50% and 20% for system Apache etc.) only use 30% of total ram.
innodb_buffer_pool_size = 2G

# On slow storage 100M is recommended
# syntax is file_name:file_size[:autoextend[:max:max_file_size]]
innodb_data_file_path = ibdata1:50G:autoextend
# On fast like SSD storage or multipath innodb_data_file_path = ibdata1:100G;ibdata2:100G:autoextend
# increment ibdata with 1000MB each time (default is 4MB)
innodb_autoextend_increment = 1000
innodb_file_per_table = OFF
 # Be careful 1 second of log (high performance = 2 , normal = 1)
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 8M

# The threshold compared to innodb ( 25% of buffer pool size at max 1 GB) 
innodb_log_file_size = 100M
innodb_log_files_in_group = 3
innodb_lock_wait_timeout = 120
# in case of remote storage
innodb_flush_method = O_DIRECT 
# otherwise
innodb_flush_method = O_DSYNC

It is recommended to run only on a system that has been running for a few hours at least so every cache has been filled (warmed up).

Kopano-cachestat is shipped with Kopano Core

Example output;

Kopano Cache Statistics
  Server start time: Di Jan  6 12:37:40 2016
  Current time     : Fri Jan 30 09:49:52 2016
     Cache                Hit ratio                  Mem usage ratio
    uquota (      609624/      625300) (97%)   (         528/     1048576) ( 0%)
       obj (   525421997/   525531113) (99%)   (     5933808/    67108864) ( 8%)
    abinfo (    11857088/    11857152) (99%)   (        6888/    26214400) ( 0%)
    userid (    17280384/    18554192) (93%)   (        3608/     1048576) ( 0%)
     quota (     1256545/     1377896) (91%)   (         440/     1048576) ( 0%)
    server (           0/           0) (N/A)   (           0/     1048576) ( 0%)
      cell (   930698599/   932916096) (99%)   (   127201976/  2621440000) ( 4%)
    index2 (    65447307/    66177951) (98%)   (    27128446/   134217728) (20%)
    extern (     5987446/     6506413) (92%)   (        5104/     1048576) ( 0%)
    index1 (   297211484/   297487612) (99%)   (    25520646/   134217728) (19%)
     store (   331842593/   448856038) (73%)   (     1010640/     1048576) (96%)
       acl (      121527/      121858) (99%)   (       19536/     1048576) ( 1%)

Explanation of the fields

uquota = cache_quota_size
obj = cache_object_size
abinfo = cache_userdetails_size
userid / extern = cache_user_size
quota = cache_quota_size
server = cache_server_size
cell = cache_cell_size 
index1 / index2 = cache_indexedobject_size
extern = cache_user_size
acl = cache_acl_size


It is recommended to only have the Apache modules installed which are required.

At the time of writing we recommend to enable to following modules for WebApp;

  • mod_expires

  • mod_headers

  • mod_setenvif

  • mod_deflate


 You can use a PHP accelerator like php-apc, Xcache or OPCache to speed up WebApp and Z-Push.


In most Apache configurations this should already be enabled but it makes sense to check if the following is set.

Apache config
# Make sure it is enabled
KeepAlive  On

Apache config
# Should be higher or equal to the ping time as configured in the z-push/config.php (define('PING_INTERVAL', 30);)
KeepAliveTimeout 45
# This should be higher than the amount of concurrent users you expect.
MaxKeepAliveRequests 500

# Should be sufficiently high for all your users to connect.
MaxClients 500

When experiencing a high server load both values could be increased, as the 'push' will take place less often.

OpenLDAP optimization

(Debian / Ubuntu commands given and paths used in examples)

Attribute Indexing

 Create a file called optimize-index.ldif containing:

dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: cn eq
olcDbIndex: gidNumber eq
olcDbIndex: mail eq
olcDbIndex: memberUid eq
olcDbIndex: ou eq
olcDbIndex: uid eq
olcDbIndex: uidNumber eq
olcDbIndex: uniqueMember eq
olcDbIndex: kopanoAccount eq
olcDbIndex: kopanoAliases eq
olcDbIndex: kopanoViewPrivilege eq

Add the ldif to add the new indexes.

# cat optimize-index.ldif | ldapmodify -Y EXTERNAL -H ldapi:///

Check if our new olcDbIndex keys have been added.

# slapcat -b cn=config | grep olcDbIndex:

The output should be similar to below

olcDbIndex: objectClass eq
olcDbIndex: cn eq
olcDbIndex: gidNumber eq
olcDbIndex: mail eq
olcDbIndex: memberUid eq
olcDbIndex: ou eq
olcDbIndex: uid eq
olcDbIndex: uidNumber eq
olcDbIndex: uniqueMember eq
olcDbIndex: kopanoAccount eq
olcDbIndex: kopanoAliases eq
olcDbIndex: kopanoViewPrivilege eq

You could check your slapd logging for suggestion of additional candidates for indexation.

# cat /var/log/syslog |grep bdb_equality_candidates

Configuring OpenLDAP Database

Check if the DB_CONFIG settings in /var/lib/ldap/DB_CONFIG are sufficient for the amount of records in your OpenLDAP.

set_cachesize 0 2097152 0
set_lk_max_objects 1500
set_lk_max_locks 1500
set_lk_max_lockers 1500

These values should be increased to suit the size of your Ldap.

See the two paragraphs below for more information. 

OpenLDAP Database Caching 

Checking the current cache statistics 

# db_stat -m -h /var/lib/ldap ǀ head -n 16
2MB 520KB	Total cache size
1	Number of caches
1	Maximum number of caches
2MB 520KB	Pool individual cache size
0	Maximum memory-mapped file size
0	Maximum open file descriptors
0	Maximum sequential buffer writes
0	Sleep after writing maximum sequential buffers
0	Requested pages mapped into the process' address space
359827	Requested pages found in the cache (99%)
24	Requested pages not found in the cache
0	Pages created in the cache
24	Pages read into the cache
0	Pages written from the cache to the backing file
0	Clean pages forced from the cache
0	Dirty pages forced from the cache

OpenLDAP Database Locking

Checking the current locking statistics

# db_stat -c -h /var/lib/ldap/|head -n 16
84	Last allocated locker ID
0x7fffffff	Current maximum unused locker ID
9	Number of lock modes
1500	Maximum number of locks possible
1500	Maximum number of lockers possible
1500	Maximum number of lock objects possible
40	Number of lock object partitions
7	Number of current locks
46	Maximum number of locks at any one time
3	Maximum number of locks in any one bucket
0	Maximum number of locks stolen by for an empty partition
0	Maximum number of locks stolen for any one partition
12	Number of current lockers
23	Maximum number of lockers at any one time
7	Number of current lock objects
39	Maximum number of lock objects at any one time

Verifying tuning

The following tests can be done to analyze the the tuning results.
They should be performed on adequately warmed up systems compare the output of the the following commands before and after the tuning.


kopano-cachestat before and after the tuning.
kopano-stats --top check the rtt and qlen value

Here generally the values should be lower and also the duration of peaks should be shorter.


Use the script provided here (requires ldapsearch to be installed). 

This would mimic opening op the GAB 50 as an user does. 

Use the wrapper below to have it run a couple of times to get the average of that.
while [ $count -lt 50 ]
    ./ > /dev/null

Adjust the times variable to a value which makes it easier to compare later. 

# time ./


Compare the output ot the mysql tuning script being used before and after.

Use either one MySQLTuner-perl or mysql-tuning-primer scripts. 

Always keep in mind there will always be recommendations as tuning is an ongoing process.

Additional Tools / Information

These tools can be used to get some additional tuning recommendations, please only run this tools when the database(is warmed up)  has been up and running in production for some time days rather than hours.

Mysql's temp files on ramdisk using tmpfs, or on a ssd disk partition

It might be useful to run /tmp on tmpfs or instruct mysql to run its temp files somewhere on a tmpfs mountpoint, or an ssd disk partition  (YMMV).

Be very careful with this !!

Mysql my.cnf
tmpdir = /some/mountpoint

See the links below for more information.

More background information

How to calculate a more suitable innodb_log_file_size
Information regarding binlog_format=ROW is needed when using transaction-isolation = READ-COMMITTED

Nice writeup about actual scaling of thread_cache_size

Kopano administrator manual

kopano core administrator manual

Todo:  topic to take a look at use/switch to syslog

Notes on using virtualization

Do's and don'ts


  • Use paravirtualized drivers when available for both disk and network interfaces.
  • Plan your virtualization needs and size accordingly.


  • Use any of the following features of your virtualization platform as they adversely impact Kopano, MySQL or any program which actively use a lot of memory.
    • Ballooning
    • Scorecard
    • Compression
    • Page Sharing or Memory De-Duplication

    • Overcommit Memory, do not give out more memory as the host machine has, as this will cause swapping in the host system

  • Do not use virtualization just for the sake of it.

  • No labels