HowTo build your own OpenChange/SOGo appliance


This document describes the complete creation process of a ZEG (Zero Effort Groupware) appliance.
This installation guide focuses on providing a test environment similar to the one used by OpenChange engineers for development and testing.

While your ZEG could be deployed using any operating system, we have chosen to build it using Ubuntu server.

Ubuntu Server

Minimal Installation

This guide assumes you have a fresh installed Linux Server distribution. For the purpose of this guide, we rely on latest Ubuntu Server. You may install either x86 32-bit or 64-bit edition depending on your hardware and environment.

The version of the Ubuntu server chosen for this guide is: Our ZEG host will be configured with the following parameters:
  • hostname: oczeg
  • IP address:

Feel free to adjust values to match your requirements. However, when configuring the domain name during OS installation, it is very important NOT to choose a realm which length is more or equal to 15 characters. This is a limit on Windows domain side which may result in connectivity issues.

We will assume the main user is:
  • Login: openchange
  • Full Name: OpenCHange User
  • Password: openchange
  • Password (sudo): openchange

OpenSSH service has been installed during setup to provide more consistent remote access than local virtualized environment. *DNS service was also installed for further Samba and Kerberos setup.

The followign apt-get commands have been run after first launch of the operating system to update to latest software versions and kernel updates.

# apt-get update && apt-get upgrade

OpenChange Installation


First, install the dependencies needed to build both OpenChange and Samba4 as superuser:

$ sudo su
# apt-get install build-essential autoconf2.59 ccache pkg-config python
python-dev git flex bison docbook-xsl xsltproc libpopt-dev
libical-dev libsqlite3-dev libmagic-dev libboost-thread-dev zlib1g-dev

Source code

As openchange user, checkout the source from OpenChange master:

$ cd
$ mkdir openchange
$ cd openchange
$ git clone git://

Environment Setup

OpenChange installs OpenChange and Samba4 binaries and libraries in non-standard locations, mostly to avoid any potential conflicts with Samba3 installation which may come by default with the system. While this is not a requirement for current install, we will anyway set this up. This requires telling the system and dynamic linker about these location:

# Teach about the non standard location of samba4 libraries
$ sudo echo '/usr/local/samba/lib' > /etc/’
$ sudo echo 'PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/samba/lib/pkgconfig; export PKG_CONFIG_PATH' > /etc/profile.d/
$ sudo echo 'PYTHONPATH=$PYTHONPATH:/usr/local/samba/lib/python2.7/site-packages;export PYTHONPATH' >> /etc/profile.d/
$ . /etc/profile.d/

Once the environment is set, use the samba target to build and install samba4. This requires internet access from the host since it fetches the source code tarball from the samba web site. These commands can be run as normal user with sudo access. The current code in trunk works with samba4-4.0.0alpha18 release. This is defined in script/

$ cd trunk
$ make samba
$ sudo ldconfig

At this stage, we have a working Samba4 environment.
However, we want to rebuild Samba4 core (samba4/source4) in order to add TLS support.

  1. As superuser, install gnutls development library:
    # apt-get install libgnutls-dev
  2. Run configure and build process again
    $ ./configure.developer --prefix=/usr/local/samba --enable-tls
    $ make
    $ sudo make install
    $ sudo ldconfig

Build OpenChange

Launch the configure script in openchange/trunk directory:

$ ./
$ ./configure --prefix=/usr/local/samba

You should have an output similar to the following:

OpenChange Configuration (Please review)

       * OpenChange Libraries:
         - libmapi (C library):     yes
                  Thread support:   yes (pthread)
         - libmapi++ (C++ library): yes
         - libmapiadmin:            yes
         - libocpf:                 yes

       * OpenChange Server:
         - mapiproxy:               yes

       * OpenChange mapistore backends:
         - backends dependencies goes here

       * OpenChange Tools:
         - openchangeclient:        yes
         - mapiprofile:             yes
         - openchangepfadmin:       yes
         - exchange2mbox:           yes
         - exchange2ical:           yes
         - mapitest:                yes
         - openchangemapidump:      yes
         - schemaIDGUID:            yes

       * subunit format (mapitest): no

       * OpenChange Documentation:  yes

       * Coverage Tests:            no

       * OpenChange Bindings:
         - Python:                  no
         - Qt4:                     no

       * Installation prefix:       /usr/local/samba


Compile and install OpenChange

$ make
$ sudo make install
$ sudo ldconfig

SOGo Installation


Install the dependencies needed to build SOGo as superuser:

$ sudo su
# apt-get install monotone gnustep-make gnustep-base-runtime devscripts
debhelper libgnustep-base-dev gobjc libxml2-dev libldap2-dev libssl-dev
zlib1g-dev libmysqlclient-dev libmemcached-dev memcached libpq-dev

This will pull in postfix, simply select Local only for local mail only or use Internet site with smarthost if you want to relay mail through another smtp server. For the purpose of this guide, we will set it as Local site and configuration Postfix as our SMTP server.

When it comes to enter the system mail name, make sure to select the FQDN that will match your AD configuration. In our case, we will use oc.test for the DOMAIN and REALM, so our System mail name is: oczeg.oc.test.

Source code

As the openchange user, checkout the latest SOGo sources:

$ git clone git://
$ git clone git://

Install SOPE

SOPE has to be installed first since SOGo depends on it:

$ cd SOPE
$ ./configure --with-gnustep --enable-debug --enable-strip
$ make
$ sudo make install

Install SOGo

Compile and install SOGo:

$ cd /home/openchange/SOGo
$ ./configure --enable-debug --disable-strip
$ make
$ sudo make install

Install SOGo OpenChange plugin

$ cd /home/openchange/SOGo/OpenChange
$ make
$ sudo PKG_CONFIG_PATH=$PKG_CONFIG_PATH make install

Additional Services

To run the appliance, we need to install and configure additional services:
  • Postgresql
  • OpenLDAP
  • Dovecot
  • Postfix
  • Apache

Database Installation: Postgresql

Install the dependencies

$ sudo apt-get install postgresql-8.4

Create database and schema

Create the database user and schema using the following commands (as superuser)

# su - postgres
$ createuser --no-superuser --no-createdb --no-createrole --encrypted --pwprompt openchange
(Specify openchange as password)
$ createdb -O openchange openchange

Adjust permissions

Adjust the access rights to the database. To do so, modify the configuration file /etc/postgresql/8.4/main/pg_hba.conf in order to add the following line at the very beginning of the file:

host     oczeg     oczeg     md5

OpenLDAP Installation

Install dependencies

$ sudo apt-get install -y slapd ldap-utils
(Specify openchange as password when asked)

In previous Ubuntu releases (10.04 and below), it was required to provision the schema (cosine, nis, inetorgperson) and the backend. Starting with 11.04 Natty, these steps are not mandatory anymore.

Provision the frontend

Create a file named frontend.ldif:

dn: ou=users,dc=oc,dc=test
objectClass: organizationalUnit
ou: users
dn: ou=groups,dc=oc,dc=test
objectClass: organizationalUnit
ou: groups

Provision the server with the following command as a superuser:

# ldapadd -x -D cn=admin,dc=oc,dc=test -W -f frontend.ldif

Create additional users

Create a file named johndoe.ldif:

dn: uid=JohnDoe,ou=users,dc=oc,dc=test
objectClass: top
objectClass: inetOrgPerson
objectClass: person
objectClass: organizationalPerson
objectClass: posixAccount
uid: JohnDoe
cn: JohnDoe Account
uidNumber: 5000
gidNumber: 5000
mail: JohnDoe@oc.test
sn: JohnDoe
givenName: JohnDoe
homeDirectory: /var/mail

Provision the server with this file and set the password to JohnDoe as a superuser:

# ldapadd -f johndoe.ldif -x -w openchange -D cn=admin,dc=oc,dc=test
# ldappasswd -h localhost -x -w openchange -D cn=admin,dc=oc,dc=test uid=JohnDoe,ou=users,dc=oc,dc=test -s JohnDoe

Create other accounts (Administrator etc.)

Follow the same steps than previous section and replace JohnDoe occurrences with Administrator or any other account name you want to create.

Change default LDAP port

Finally we need to change default LDAP service port. Samba4 provides its own LDAP service running on tcp/389 and if slapd service remains unchanged, it will result in NT_ALREADY_ASSOCIATED_PORT error raised and prevent from using Kerberos service.

In /etc/default/slapd file, change SLAPD_SERVICES to:

SLAPD_SERVICES="ldap://localhost:3389 ldapi:///" 

Dovecot setup with LDAP authentication and deliver support

Install dependencies

$ sudo apt-get install dovecot-common dovecot-imapd dovecot-dev dovecot-ldap

Configure dovecot

Edit /etc/dovecot/dovecot.conf to match the following configuration:

disable_plaintext_auth = no
log_path = /var/log/dovecot.message
log_timestamp = "%Y-%m-%d %H:%M:%S " 
mail_location = maildir:/var/mail/%u
mail_privileged_group = mail
passdb {
  args = /etc/dovecot/dovecot-ldap.conf
  driver = ldap
passdb {
  driver = pam
protocols = imap
service auth {
  unix_listener auth-master {
    group = vmail
    mode = 0600
    user = vmail
  unix_listener auth-userdb {
    user = vmail
  user = root
ssl_cert = </etc/ssl/certs/dovecot.pem
ssl_key = </etc/ssl/private/dovecot.pem
userdb {
  args = /etc/dovecot/dovecot-ldap.conf
  driver = ldap
userdb {
  driver = passwd
protocol lda {
  hostname = oc.test
  log_path = /var/log/dovecot.message
  postmaster_address = postmaster@oc.test

protocol pop3 {
  pop3_uidl_format = %08Xu%08Xv

Configure dovecot LDAP

Edit /etc/dovecot/dovecot-ldap.conf and match the following configuration:

uris = ldap://localhost:3389
dn = cn=admin,dc=oc,dc=test
dnpass = openchange
tls = no
ldap_version = 3
base = dc=oc,dc=test
scope = subtree
user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid
user_filter = (uid=%u)
pass_attrs = uid=user,userPassword=password
pass_filter = (uid=%u)

It is also recommended to adjust DEBUG_LOGIN variable to 2 and ensure everything is setup and working properly before resetting it to 0.


Create the virtual user

# groupadd –g 5000 vmail
# useradd –m –u 5000 –g 5000 –s /bin/bash –d /var/mail vmail
# adduser vmail mail

Create Maildir for LDAP users

This is a bit of a misconfiguration here as it should be created automatically. Updates are expected for this part in a short future.
  1. WARNING Ubuntu 12, we doesn't found maildirmake, the command is maildirmake.dovecot and not maildirmake –f Drafts
  2. but cd johndoe\@oc.test and mkdir Drafts...
    # cd /var/mail
    # maildirmake johndoe@oc.test
    # maildirmake –f Drafts johndoe@oc.test
    # maildirmake –f Sent johndoe@oc.test
    # maildirmake –f Trash johndoe@oc.test
    # ln –s johndoe@oc.test JohnDoe
    # ln -s johndoe@oc.test johndoe
    # maildirmake administrator@oc.test
    # maildirmake –f Drafts administrator@oc.test
    # maildirmake –f Sent administrator@oc.test
    # maildirmake –f Trash administrator@oc.test
    # ln –s administrator@oc.test Administrator
    # ln -s administrator@oc.test administrator
    # chown –R vmail:vmail *

Restart services and test setup

# service dovecot start

To test authentication, we can use telnet:

root@oczeg:/etc/courier# telnet localhost 143
Connected to localhost.
Escape character is '^]'.
1 LOGIN GoodAdmin GoodAdmin
telnet> quit
Connection closed.

Postfix setup

Install dependencies

While we already have postfix installed, LDAP map support for postfix is required along with deliver for LDA mail delivery to dovecot

# apt-get install postfix-ldap

Configure postfix

By default postfix doesn't bind on all interfaces, we will update the inet_interfaces_ parameter and change it from *loopback-only to all in /etc/postfix/ file.

We also need to remove default_transport and relay_transport default values and replace them with expected dovecot deliver values. Our final file should looks like the dump below. Also note that we have adjusted the virtual_alias_maps parameter detailed later.

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no
append_dot_mydomain = no
readme_directory = no

# TLS parameters
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls = yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = oczeg.oc.test
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = oczeg.oc.test, localhost.oc.test, localhost
relayhost = 
mynetworks = [::ffff:]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all 
relay_transport = ldap:/etc/postfix/people.ldap  
smtpd_sasl_auth_enable = no
smtpd_sasl_type = cyrus
smtpd_sasl_path = smtpd
smtpd_sasl_authenticated_header = no
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = 
broken_sasl_auth_clients = no
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination
smtpd_sender_restrictions = 
mailbox_command = 
smtp_use_tls = no
smtpd_tls_received_header = no
smtpd_tls_mandatory_protocols = SSLv3, TLSv1
smtpd_tls_mandatory_ciphers = medium
smtpd_tls_auth_only = no
tls_random_source = dev:/dev/urandom

dovecot_destination_recipient_limit = 1
virtual_mailbox_domains = oc.test
virtual_transport = dovecot

We now create the /etc/postfix/people.ldap file:

version = 3
server_host = localhost
server_port = 3389
timeout = 60
search_base = ou=people,dc=oc,dc=test
query_filter = (mail=%s)
result_attribute = uid
bind = yes
bind_dn = cn=admin,dc=oc,dc=test
bind_pw = openchange
debuglevel = 2

Finally we edit /etc/postfix/ and add a dovecot deliver line:

dovecot    unix -       n       n       -       -       pipe
   flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${user}

Restart postfix service:

# /etc/init.d/postfix restart

Configure Apache

  1. Copy SOGo-debian.conf from your SOGo/Apache/ source directory into /etc/apache2/conf.d/
    # cp ~openchange/SOGo/Apache/SOGo-debian.conf /etc/apache2/conf.d/SOGo.conf
  2. Edit /etc/apache2/conf.d/SOGo.conf:
    1. replace path to GNUstep from /usr/lib to /usr/local/lib for all occurrences.
    2. Change yourhostname to your IP address and change from https to http for RequestHeader fields:
      RequestHeader set "x-webobjects-server-name" "" 
      RequestHeader set "x-webobjects-server-url" "" 
  3. Turn a2enmod and restart apache
    # a2enmod proxy
    # a2enmod proxy_http
    # a2enmod proxy_html
    # a2enmod headers
    # a2enmod rewrite
    # /etc/init.d/apache2 restart

SOGo additional configuration

Run under the user account that will run SOGo server (in our case the openchange user):

$ defaults write sogod SOGoTimeZone "Europe/Paris" 
$ defaults write sogod SOGoProfileURL "postgresql://openchange:openchange@localhost/openchange/sogo_user_profile" 
$ defaults write sogod OCSFolderInfoURL "postgresql://openchange:openchange@localhost/openchange/sogo_folder_info" 
$ defaults write sogod OCSSessionsFolderURL "postgresql://openchange:openchange@localhost/openchange/sogo_sessions_folder" 
$ defaults write sogod SOGoUserSources '({CNFieldName = cn; IDFieldName = uid; UIDFieldName = uid; IMAPHostFieldName =; baseDN =
"ou=users,dc=oc,dc=test"; bindDN = "uid=Administrator,ou=users,dc=oc,dc=test"; bindPassword = Administrator; canAuthenticate = YES; displayName = "Shared Addresses"; hostname = "localhost"; id = public; isAddressBook = YES; port = 3389})'
$ defaults write sogod WONoDetach YES
$ defaults write sogod WOLogFile -
$ defaults write sogod WOPidFile /tmp/

Configure Samba4

Provision Samba4

As the openchange user, go into /home/openchange/openchange/trunk/samba4/source4 directory and run:

$ sudo PYTHONPATH=$PYTHONPATH ./setup/provision --domain=OC --realm=OC.TEST --adminpass='#1OpenChange' --server-role='domain controller'

Add JohnDoe user to Samba4

By default the Administrator account is setup, we'll just have to extend it in OpenChange. However we need to create other users:

$ sudo PYTHONPATH=$PYTHONPATH /usr/local/samba/bin/samba-tool user add JohnDoe JohnDoe
User JohnDoe created successfully

Configure DNS service

As superuser go to /etc/bind directory:

# cd /etc/bind
# mkdir samba
# cp /usr/local/samba/private/named.* samba/
# cp –rfi /usr/local/samba/private/dns samba/

  1. Edit /etc/bind/samba/named.conf and replace /usr/local/samba/private occurrences with /etc/bind/samba.
  2. Edit /etc/bind/named.conf.local and add at the bottom of the file:
    include "/etc/bind/samba/named.conf";
  3. Restart bind service
    # /etc/init.d/bind9 restart

We can now edit our /etc/resolv.conf file to pointer to local DNS and test our configuration:

# cat /etc/resolv.conf
search oc.test
# host -t SRV _ldap._tcp.oc.test.
_ldap._tcp.oc.test has SRV record 0 100 389 oczeg.oc.test.
# host -t SRV _kerberos._udp.oc.test.
_kerberos._udp.oc.test has SRV record 0 100 88 oczeg.oc.test.
# host -t A oczeg.oc.test.
oczeg.oc.test has address

Configure Kerberos

Install krb5-user package:

# apt-get install krb5-user

  1. Save the original /etc/krb5.conf to /etc/krb5.conf.orig
  2. Copy /usr/local/samba/share/setup/krb5.conf to /etc/krb5.conf
  3. Edit /etc/krb5.conf and replace ${REALM} with OC.TEST

Before testing Kerberos authentication, we need to run Samba4 service. As superuser (and in another console) run:

$ sudo PYTHONPATH=$PYTHONPATH /usr/local/samba/sbin/samba -d5 -i -M single

Then in previous console, run:

# kinit administrator@OC.TEST
Password for administrator@OC.TEST:
Warning: Your password will expire in 41 days on Mon Sep 12 14:32:51 2011
# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: administrator@OC.TEST

Valid starting
08/01/11 15:01:04 08/02/11 01:01:04
renew until 08/02/11 15:01:00

Configure OpenChange

Provision Samba4 AD with OpenChange schema

As the openchange user, go into /home/openchange/openchange/trunk directory and run:

$ sudo PYTHONPATH=$PYTHONPATH ./setup/openchange_provision
[+] Step 1: Register Exchange OIDs
[+] Step 2: Add Exchange attributes to Samba schema
[+] Step 3: Add Exchange auxiliary classes to Samba schema
[+] Step 4: Add Exchange objectCategory to Samba schema
[+] Step 5: Add Exchange containers to Samba schema
[+] Step 6: Add Exchange *sub* containers to Samba schema
[+] Step 7: Add Exchange CfgProtocol subcontainers to Samba schema
[+] Step 8: Add Exchange mailGateway subcontainers to Samba schema
[+] Step 9: Add Exchange classes to Samba schema
[+] Step 10: Add possSuperior attributes to Exchange classes
[+] Step 11: Extend existing Samba classes and attributes
[+] Step 12: Exchange Samba with Exchange configuration objects

Create openchangedb database

Create the openchangedb database

$ sudo PYTHONPATH=$PYTHONPATH ./setup/openchange_provision --openchangedb
Setting up openchange db
[+] Public Folders
* Public Folder Root            72057594037927937
* IPM_SUBTREE                   144115188075855873
* NON_IPM_SUBTREE               216172782113783809
* EFORMS REGISTRY               288230376151711745
* OFFLINE ADDRESS BOOK          360287970189639681
* /o=First Organization/cn=addrlists/cn=oabs/cn=Default Offline Address Book 432345564227567617
* SCHEDULE+ FREE BUSY           504403158265495553
* EX:/o=First Organization/ou=Exchange Administrative Group (OCZEG)     576460752303423489
* Events Root                   648518346341351425

Create OpenChange users

$ sudo PYTHONPATH=$PYTHONPATH ./setup/openchange_newuser --create JohnDoe
[+] User JohnDoe extended and enabled

Perform the same steps for the Administrator user:

$ sudo PYTHONPATH=$PYTHONPATH ./setup/openchange_newuser --create Administrator
[+] User GoodAdmin extended and enabled

Edit Samba configuration file

We now need to tell Samba4 about OpenChange server. Edit /usr/local/samba/etc/smb.conf and add the following parameters to the [global] section:

### Configuration required by OpenChange server ###
dcerpc endpoint servers = +mapiproxy
dcerpc_mapiproxy:server = true
dcerpc_mapiproxy:interfaces = exchange_emsmdb, exchange_nsp, exchange_ds_rfr
### Configuration required by OpenChange server ###

Give root access to openchange GNUStep environment

# ln -s ~openchange/GNUStep /root/

Run Services

If not already done, run sogod as the openchange user:

$ sogod

Run samba4 as superuser:

$ sudo PYTHONPATH=$PYTHONPATH /usr/local/samba/sbin/samba -d5 -i -M single

Frequently Asked Questions (FAQ)

/usr/local/samba/include/util/time.h:83: error

  • You encounter the following problem while compiling SOGo backend:
      Compiling file SOGoMAPIFSFolder.m ...
    In file included from SOGoMAPIFSFolder.m:43:
    /usr/local/samba/include/util/time.h:83: error: expected ‘=’, ‘,’, ‘;’, 
    ‘asm’ or ‘__attribute__’ before ‘null_time’
    /usr/local/samba/include/util/time.h:88: error: expected ‘=’, ‘,’, ‘;’, 
    ‘asm’ or ‘__attribute__’ before ‘null_nttime’
    /usr/local/samba/include/util/time.h:132: error: expected declaration 
    specifiers or ‘...’ before ‘bool’
    /usr/local/samba/include/util/time.h:139: error: expected declaration 
    specifiers or ‘...’ before ‘bool’
    /usr/local/samba/include/util/time.h:191: error: expected ‘=’, ‘,’, ‘;’, 
    ‘asm’ or ‘__attribute__’ before ‘timeval_is_zero’
    /usr/local/samba/include/util/time.h:241: error: expected ‘=’, ‘,’, ‘;’, 
    ‘asm’ or ‘__attribute__’ before ‘timeval_expired’
    /usr/local/samba/include/util/time.h:291: error: expected ‘=’, ‘,’, ‘;’, 
    ‘asm’ or ‘__attribute__’ before ‘nt_time_equal’
    /usr/local/samba/include/util/time.h:301: error: expected ‘=’, ‘,’, ‘;’, 
    ‘asm’ or ‘__attribute__’ before ‘null_timespec’
    make[3]: *** [obj/SOGoBackend.obj/SOGoMAPIFSFolder.m.o] Error 1
    make[2]: *** [internal-bundle-run-compile-submake] Error 2
    make[1]: *** [SOGoBackend.all.bundle.variables] Error 2
    make: *** [internal-all] Error 2
This is an include directive issue in SOGo backend (that may already be fixed in latest revision). Solving this issue is easy:
  • Solution 1: Add
    #include <stdbool.h>
    before any reference to
    #include <util/time.h>
    in SOGo backend sources. This fix is time consuming as you may have to reproduce it for each file affected by this issue - furthermore it may be reverted with further SOGo revision - but that's the most appropriate solution.
  • Solution 2: You need to add the following directive at the top of /usr/local/samba/include/util/time.h:
    #include <stdbool.h>

    This solution would solve at once this issue in entire OpenChange's SOGo backend but is not recommended.