PIM

Architecture:

Radicale: CalDAV and CardDAV

Create new user:

$ groupadd vcal
$ useradd -g vcal vcal -d /srv/vcal -m

Create web root:

$ mkdir /srv/www/cal-example-com
$ chown vcal:vcal /srv/www/cal-example-com
$ chmod 755 /srv/www/cal-example-com

Create virtual env:

$ su - vcal
$ cd /srv/www/cal-example-com
$ virtualenv --no-site-packages venv
$ source venv/bin/activate
$ pip install --upgrade
$ pip install radicale

Create WSGI file /srv/www/cal-example-com/radicale.wsgi:

import radicale
import site
site.addsitedir('/srv/www/cal-example-com/venv/lib/python2.6/site-packages')
radicale.log.start()
application = radicale.Application()

Create configuration /etc/radicale/config:

[acl]
type = None

[storage]
type = filesystem
filesystem_folder = /srv/vcal/collections

[logging]
debug = False

Create configuration /etc/radicale/logging:

[loggers]
keys = root

[handlers]
keys = file

[formatters]
keys = full

[logger_root]
level = INFO
handlers = file

[handler_file]
class = FileHandler
args = ('/var/log/radicale.log',)
formatter = full

[formatter_full]
format = %(asctime)s - %(levelname)s: %(message)s

create logratate configuration /etc/logrotate.d/radicale:

/var/log/radicale.log {
    weekly
    rotate 4
    compress
    missingok
    create 0640 vcal adm
}

TODO: is postrotate required?

Create initial logfile:

$ touch /var/log/radicale.log
$ chown vcal:adm /var/log/radicale.log

Apache WSGI + AuthN

Note: As Apache is only used internally it only listens on localhost on a high port.

$ apt-get install apache2
$ apt-get install libapache2-mod-wsgi
$ a2enmod authnz_ldap
$ a2enmod rewrite

Create /etc/apache2/sites-available/cal-example-com:

<VirtualHost 127.0.0.1:7080>
    ServerName cal.example.com

    ErrorLog ${APACHE_LOG_DIR}/cal-example-com.error.log
    CustomLog ${APACHE_LOG_DIR}/cal-example-com.access.log combined

    WSGIDaemonProcess radicale user=vcal group=vcal threads=1
    WSGIScriptAlias / /srv/www/cal-example-com/radicale.wsgi

    <Directory /srv/www/cal-example-com>
        WSGIProcessGroup radicale
        WSGIApplicationGroup %{GLOBAL}

        AllowOverride None
        Order allow,deny
        allow from all

        AuthType Basic
        AuthName "Authentication"
        AuthBasicProvider ldap
        AuthLDAPURL ldap://127.0.0.1:389/dc=example,dc=com?uid,mail?one
        Require valid-user

        RewriteEngine On
        RewriteCond %{PATH_INFO} ^/shared/.*
        RewriteRule .* - [Last]
        RewriteCond %{ENV:AUTHENTICATE_mail}%{PATH_INFO} !^([^/]+/)\1
        RewriteRule .* - [Forbidden]
    </Directory>
</VirtualHost>

Enable site:

$ a2ensite cal-example.com
$ a2dissite default

Configure /etc/apache2/ports.conf:

NameVirtualHost 127.0.0.1:7080
Listen 127.0.0.1:7080
<IfModule mod_ssl.c>
    Listen 127.0.0.1:7443
</IfModule>
<IfModule mod_gnutls.c>
    Listen 127.0.0.1:7443
</IfModule>

Nginx reverse proxy + SSL

server {
  listen                  443;
  server_name             cal.example.com;
  server_name_in_redirect off;
  ssl                     on;
  ssl_certificate         /etc/ssl/certs/cal-example-com.pem;
  ssl_certificate_key     /etc/ssl/private/cal-example-com.pem;
  access_log              /var/log/nginx/cal-example-com.access.log;
  error_log               /var/log/nginx/cal-example-com.error.log;
  root                    /srv/www/cal-example-com;
  index                   index.html;
  error_page              404 /index.html;
  location / {
    proxy_pass            http://localhost:7080;
  } 
}

Sources: