ActiveSync on Linux using z-push, nginx and an imap backend

  Saturday, April 14, 2012 » Linux

Want to extend your private IMAP server with push email functionality for your smartphone? Then Z-Push might be exactly what you need.

Z-Push is an open source ActiveSync implementation. Currently the default Z-Push packages includes four different backends.

  1. Zarafa (Supporting Emails, Contacts, Calendar and Task synchronization)
  2. Any IMAP Server (for Email synchronization only)
  3. maildir (Email synchronization only)
  4. vCard (Contact synchronization only)

Of course, it is possible to write your own backends. Some have already done that and thus created a Zimbra backend.

So how do you go about getting Z-Push installed on your server? For Debian there is a re-branded package in the repository called d-push.

Unfortunately I wasn’t able to get that working. So I went with the original z-push package available from their download page.

Although probably not advised, I tried the 2.0beta2 version. The Installation manual is also available on the same page, but following this blog post you probably won’t need it.

Z-Push configuration

I extracted the package into /var/www/zpush/ and made sure that the www-data user has enough permissions for the folder. If the webserver is running under a different user on your machine, you’ll have to use that instead.

# cd /var/www
# chown -R www-data.www-data zpush
# chmod 775 zpush/state

Adapt the z-push config file for your needs:

# vim /var/www/zpush/config.php

Change the time zone:

// Defines the default time zone, change e.g. to "Europe/London" if necessary
define('TIMEZONE', 'Europe/Vienna');

The STATE_DIR

 *  Default FileStateMachine settings
  */       
  define('STATE_DIR', '/var/www/zpush/state/');

And the log settings

 *  Logging settings
 */
    define('LOGFILEDIR', '/var/log/z-push/');
    define('LOGFILE', LOGFILEDIR . 'z-push.log');
    define('LOGERRORFILE', LOGFILEDIR . 'z-push-error.log');
    define('LOGLEVEL', LOGLEVEL_INFO);

Don’t forget to create the /var/log/z-push directory and change the permissions so that the www-data user can read and write. Until you get z-push up and running you might want to change the LOGLEVEL to LOGLEVEL_DEBUG in order to get a more verbose log file.

And finally, set the BACKEND_PROVIDER:

*  Backend settings
 */
     // The data providers that we are using (see configuration below)
         define('BACKEND_PROVIDER', "BackendIMAP");

Depending on the backend you choose, it might be necessary to tune the backend specific settings too. In my case that wasn’t necessary for imap.

At this point z-push should be configured appropriately.

To see if everything is working so far you might invoke php in the command line:

# php /var/www/zpush/index.php

You should see some html markup containing an access denied error message.

nginx configuration

All that’s left is the nginx configuration which is pretty straightforward.

You can of course also use apache or lighttpd. The default manual even assumes that you’re going to use apache, so consult that for more information about how to configure apache.

server {
    listen 443;
    server_name mail.example.com;

    ssl on;
    ssl_certificate         /path/to/ssl.crt;
    ssl_certificate_key     /path/to/ssl.key;


    root    /var/www/zpush;
    index   index.php;

    # not necessary, but might help
    #client_max_body_size 4M;
    #client_body_buffer_size 128k;

    location / {
            try_files $uri $uri/ index.php;
    }

    location /Microsoft-Server-ActiveSync {
            rewrite ^(.*)$  /index.php last;
    }

    location ~ .php$ {
            include fastcgi_params;
            fastcgi_index index.php;
            fastcgi_param HTTPS on;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

            
            # change this if necessary
            fastcgi_pass unix:/var/run/php-fpm.sock;
    }

Restart nginx and try to access https://mail.example.com/Microsoft-Server-ActiveSync You should be prompted for a username and password.

At this point the server side is done. Now configure your smartphone and see if everything works. Instead of using IMAP you can now tell your smartphone to connect with an Exchange server. As Autodiscovery is not supported yet, use the advanced configuration wizard and point it to your servers hostname manually.

Appendix: The trouble with certificates on WP7

WP7 happens to be very serious about certificates. It doesn’t trust self signed certificates and only a handful certificate authorities.

For example StartSSL isn’t trusted by default.

You can check if yours is trusted by visiting your page (the one that uses the certificate) in the Internet Explorer. If you are greeted with a warning page it isn’t trusted. If you see your page, be happy, you don’t need to continue reading this post.

In order to get WP7 to trust your certificate, you’ll need to export the whole certificate chain and install all the certificates in the chain on the phone.

To export them:

  • visit the https page in your browser of choice
  • click the https symbol
  • view certificate
  • for every certificate in the Cerficiate Hierarchy view, export the certificate (choose the x.509 Certificate (DER) filetype and save the file with a .cer extension)

To get them onto your phone, setup regular IMAP on the smartphone (Luckily WP7 is more relaxed about the untrusted certificate when using IMAP) and mail yourself the certificates.

To install the certificates on the phone, all you need to do is open them and click install. Once you’ve got all of them installed, reboot the phone and see if the Exchange synchronization finally works. If not, start swearing and consult google for additional help.