this is obsolete doc -- see http://doc.nethence.com/ instead

Building CalDAV with Apache 

draft in progress... 

 

Prerequesties 

We need the following packages available. For RHEL5/6, 

rpm -q gcc \
pkgconfig \
libxml2 libxml2-devel \
curl curl-devel \
glib2 glib2-devel \
libattr libattr-devel \
| grep ^package

for Slackware (tested with 13.1 64-bit), 

ls -1 /var/log/packages/gcc* \
/var/log/packages/pkg-config* \
/var/log/packages/libxml2* \
/var/log/packages/glib2* \
/var/log/packages/attr* \
/var/log/packages/curl* \
| grep 'No such file or directory'

 

We're now ready to compile apr, apr-util and httpd from source (patches are required). 

 

Preparing mod_dav_acl provided patches 

Get mod_dav_acl (http://sourceforge.net/projects/moddavacl/) and look for patches, 

wget http://downloads.sourceforge.net/project/moddavacl/moddavacl/0.1.6/mod_dav_acl-0.1.6.tar.gz
tar xzf mod_dav_acl-0.1.6.tar.gz
cd mod_dav_acl-0.1.6/
#less README
ls -l | grep .patch$
cd ../

Note there are three patches available. 

 

Patching and building apr 

Patch, build and install apr-1.2.7 (http://archive.apache.org/dist/apr/), 

wget http://archive.apache.org/dist/apr/apr-1.2.7.tar.gz
tar xzf apr-1.2.7.tar.gz
patch -p0 < mod_dav_acl-0.1.6/apr-1.2.7-ju1.patch
cd apr-1.2.7/
mkdir -p /opt/
./configure --prefix=/opt/caldav/
make
make install
cd ../

 

Building apr-util 

Build and install apr-util-1.2.7 (http://archive.apache.org/dist/apr/), 

wget http://archive.apache.org/dist/apr/apr-util-1.2.7.tar.gz
tar xzf apr-util-1.2.7.tar.gz
cd apr-util-1.2.7/
#./configure --with-apr=/usr/local/apr/
./configure --prefix=/opt/caldav/ --with-apr=/opt/caldav/bin/
make
make install
cd ../

 

Patching and building httpd 

Patch, build and install httpd-2.2.8 (http://archive.apache.org/dist/httpd/), 

wget http://archive.apache.org/dist/httpd/httpd-2.2.8.tar.gz
tar xzf httpd-2.2.8.tar.gz
patch -p0 < mod_dav_acl-0.1.6/httpd-2.2.8-ju.patch
cd httpd-2.2.8/
#./configure --help | less
#--with-apr=/usr/local/apr/
#--with-apr-util=/usr/local/apr
./configure --prefix=/opt/caldav/ \
--with-apr=/opt/caldav/bin/ \
--with-apr-util=/opt/caldav/bin/ \
--enable-dav \
--enable-dav-fs \
--enable-dav-lock \
--enable-auth-digest
make
make install
cd ../

Note. I am forcing the use of external apr and apr-util, not the included ones (which could otherwise also be forced by --with-included-apr). 

Note. auth-digest is required by caldav. 

 

Compiling mod_dav_acl 

Work around the mod_dav configure script, 

cd /opt/caldav/
ln -s conf etc
cd lib/
ln -s ../modules

 

Back to the build directory, mod_dav was already extracted before while looking for patches, 

cd mod_dav_acl-0.1.6/
export PKG_CONFIG_PATH=/opt/caldav/lib/pkgconfig
export PATH=/opt/caldav/bin:$PATH
#export PKG_CONFIG_PATH=/usr/local/apr/lib/pkgconfig
#export PATH=$PATH:/usr/local/apache2/bin
./configure --prefix=/opt/caldav \
--with-apache-module-subdir="modules" \
--with-apache-config-subdir="" \
--with-apache-include-subdir=""
make
make install
cd ../

Note. Changing the PATH to use the modified apache apxs tool (which is a Perl script) before system's one, if there is. 

Note. Using pkgconfig for apr. 

Note. It is using apxs1 pathes by default (/usr/local/{include,lib,etc}), not apxs2 (apache2/). 

 

Check that this command is now available. It will be used later on, 

#ls -l /usr/local/sbin/principals.sh
ls -l /opt/caldav/sbin/principals.sh

 

Compiling libical 

Get libical (http://sourceforge.net/projects/freeassociation/) and proceed, 

wget http://downloads.sourceforge.net/project/freeassociation/libical/libical-0.46/libical-0.46.tar.gz
tar xzf libical-0.46.tar.gz
cd libical-0.46/
#rpm -q autoconf automake libtool
#ls -1 /var/log/packages/autoconf* /var/log/packages/automake* /var/log/packages/libtool*
export MKDIR_P="/bin/mkdir -p"
autoreconf -i
./configure --prefix=/opt/caldav
make
make install
cd ../

 

Compiling mod_caldav 

Get mod_caldav (http://sourceforge.net/projects/modcaldav/) and proceed, 

wget http://downloads.sourceforge.net/project/modcaldav/modcaldav/0.1.10/mod_caldav-0.1.10.tar.gz
tar xzf mod_caldav-0.1.10.tar.gz
cd mod_caldav-0.1.10/
export PATH=/opt/caldav/bin:$PATH
export PKG_CONFIG_PATH=/opt/caldav/lib/pkgconfig
#export PATH=$PATH:/usr/local/apache2/bin
#export PKG_CONFIG_PATH=/usr/local/apr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/libical/lib/pkgconfig
./configure --prefix=/opt/caldav \
--with-apache-module-subdir="modules" \
--with-apache-config-subdir="" \
--with-apache-include-subdir=""
make
make install
cd ../

Note. Same as with mod_dav_acl for the PATH. 

Note. But this time I am using pkgconfig to work not only with apr, but also with mod_dav_acl and libical. 

 

Filesystem 

Enable XATTR and ACL on the file systems you want the CalDAV repository to rely on e.g., 

cd /etc/
vi fstab

change, 

#/dev/VolGroup00/LogVol00 / ext3 defaults,acl,user_xattr 1 1
/dev/sda3        /data            ext4        defaults,acl,user_xattr 1 2

note. 'acl' may be optional, as it may be enabled already, by default. 

apply, 

#mount -o remount /
mount -o remount /data

 

Environment 

Eventually add the (modified) apache binaries and principals.sh to your path before the other commands, 

cd ~/
vi .bash_profile

add, 

export PATH=/opt/caldav/sbin:/opt/caldav/bin:$PATH:$HOME/bin

apply, 

source .bash_profile

 

Apache and DAV modules configuration 

Tune apache and load the modules, 

#cd /usr/local/apache2/conf
cd /opt/caldav/conf/
mv httpd.conf httpd.conf.dist
sed '/^[[:space:]]*$/d; /^[[:space:]]*#/d;' httpd.conf.dist > httpd.conf.dist.clean
sed 's/you@example.com/YOUR_EMAIL/;
  s/Listen 80/Listen 8080/;
  s#/opt/caldav/htdocs#/data/caldav#' httpd.conf.dist.clean > httpd.conf
cat >> httpd.conf <<EOF9
DavLockDB /var/www/davlock
LoadModule dav_acl_module /usr/local/lib/httpd/modules/mod_dav_acl.so
LoadModule caldav_module /usr/local/lib/httpd/modules/mod_caldav.so
Include /usr/local/etc/httpd/conf.d/*.conf
EOF9

Note. The listening port, DocumentRoot and Directory rules are configured in the process. 

 

Allow web clients to connect on every Location, 

cd /opt/caldav/conf/
cat dav_acl.conf >> httpd.conf
cat caldav.conf >> httpd.conf
vi httpd.conf

uncomment/change, 

LoadModule dav_acl_module modules/mod_dav_acl.so
Alias /principals "/data/caldav/principals/"
(...)
   Dav on

Allow from all 

   Options None
(...)

AclPrincipals http://192.168.0.1/principals 

AclPrincipalDir /data/caldav/principals 

AuthUserFile /data/caldav/passwords 

# REMOVE THE WHOLE VIRTUAL HOSTS PART

 

LoadModule caldav_module modules/mod_caldav.so
Alias /caldav "/data/caldav/"
(...)
   Dav on

Allow from all 

   Options None
(...)

AuthUserFile /data/caldav/passwords 

Note. Change the hostname accordingly. 

 

Also add this for user locks, 

        DAVLockDB var/davlock.db

and create the folder for apache to write in it, 

cd /opt/caldav/
mkdir -p var/
chown daemon:daemon var/

 

Files and folders 

Create the needed directories and fix perms, 

cd /data/
#rm -rf caldav/
##mkdir -p caldav/caldav/
mkdir -p caldav/principals/
chown -R daemon:daemon caldav/

 

Although I forced DocumentRoot to point there, this symlink also makes things clear for later maintainance, 

#cd /usr/local/apache2
cd /opt/caldav/
mv htdocs/ htdocs.dist/
#ln -s /var/www htdocs
ln -s ../../data/caldav htdocs

 

Eventually prevent void useless errors in the logs, 

#cd /var/www/
cd /data/caldav/
touch favicon.ico
touch robots.txt

 

Start the service 

Check the apache configuration, 

which httpd
httpd -l | grep dav
httpd -l | grep digest
httpd -S
#apachectl configtest

 

Start the daemon, 

#cd /usr/local/apache2/logs/
cd /opt/caldav/logs/
apachectl start
tail -F error_log

Note. Apache runs as user and group 'daemon' by default. 

 

Enable at boot time, 

cd /etc/
vi rc.local

add, 

echo -n starting caldav...
#/usr/local/apache2/bin/apachectl start && echo done
/opt/caldav/bin/apachectl start && echo done

 

Digest authentication 

Create an admin user identity to manage principals (-c to create file), 

#cd /var/www/
cd /data/caldav/
htdigest -c passwords testing admin
htdigest passwords testing joppe
htdigest passwords testing joe

Note. admin, joppe and joe users are needed by the acl_tests script (mod_dav_acl). 

Note. Use the password 'password' for testing and to conform with the acl_tests script (mod_dav_acl). 

 

See if everything is just fine with the acl_tests script, 

cd mod_dav_acl-0.1.6/
mv acl_tests acl_tests.dist
sed 's/localhost:8080/192.168.0.1:8080/' acl_tests.dist > acl_tests
chmod +x acl_tests
./acl_tests

Note. Change the hostname accordingly. 

 

 

Configure DAV ACL principals 

Modify the ACL script, 

cd /usr/local/sbin
cp principals.sh principals.sh.dist
vi principals.sh

change, 

hostname=dav

 

Create a user identity, 

cd /var/www
htdigest passwords testing USERNAME
htdigest passwords testing USER2

create principals for that user, 

principals.sh

 

Create a DAV collection for that user, 

curl -X MKCALENDAR -u USERNAME:PASSWORD --digest http: //dav/caldav/USERNAME
curl -X MKCALENDAR -u USER2:PASSWORD --digest http: //dav/caldav/USER2

Note. change USERNAME & PASSWORD accordingly 

 

Ready to go 

You can now use Sunbird to connect to your CalDAV calendar, 

http: //dav/caldav/USERNAME
http: //dav/caldav/USER2

 

Troubbleshooting 

If you get this error while trying to compile httpd with apr and apr-util (got it with Slackware64 13.1), 

/opt/caldav/build-1/libtool --silent --mode=compile gcc -g -O2 -pthread    -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE    -I/root/caldav/httpd-2.2.8/srclib/pcre -I. -I/root/caldav/httpd-2.2.8/os/unix -I/root/caldav/httpd-2.2.8/server/mpm/prefork -I/root/caldav/httpd-2.2.8/modules/http -I/root/caldav/httpd-2.2.8/modules/filters -I/root/caldav/httpd-2.2.8/modules/proxy -I/root/caldav/httpd-2.2.8/include -I/root/caldav/httpd-2.2.8/modules/generators -I/root/caldav/httpd-2.2.8/modules/mappers -I/root/caldav/httpd-2.2.8/modules/database -I/opt/caldav/include/apr-1 -I/opt/caldav//include/apr-1 -I/root/caldav/httpd-2.2.8/modules/proxy/../generators -I/root/caldav/httpd-2.2.8/modules/ssl -I/root/caldav/httpd-2.2.8/modules/dav/main  -prefer-non-pic -static -c exports.c && touch exports.lo
exports.c:1094: error: redefinition of 'ap_hack_apr_allocator_create'
exports.c:180: note: previous definition of 'ap_hack_apr_allocator_create' was here

make sure there's no symlink anywhere in the path to that directory and work around it e.g., 

cd server/
mv -f export_files export_files.dist
make export_files
tmp=export_files_unsorted.txt
rm -f $tmp
for dir in `pwd`/../include `pwd`/../os/unix `pwd`/../modules/http; do
  ls $dir/*.h >> $tmp
done
prefix=/opt/caldav
ls $prefix/include/apr-1/apr.h >> $tmp
ls $prefix/include/apr-1/apu.h >> $tmp
ls $prefix/include/apr-1/apr_*.h >> $tmp
ls $prefix/include/apr-1/apu_*.h >> $tmp
sort $tmp > export_files
rm -f $tmp
ls -l export_files
unset tmp prefix
cd ../

Refs. 

http://mail-archives.apache.org/mod_mbox/httpd-users/200405.mbox/%3CPine.WNT.4.58.0405051438340.2148@HEC-4949%3E 

http://linuxscribbles.blogspot.fr/2012/06/configuring-httpd-on-rhel-6-centos-6.html 

 

If you get this error in the Apache logs, 

Digest: invalid nonce ... received - hash is not ...

your probably forgot to enable user's ACL, see DAV ACL principals chapter. 

 

If you get this error when running acl_tests, 

Entity: line 2: parser warning : xmlns:D: 'DAV:' is not a valid URI
<D:acl xmlns:D="DAV:">
                     ^

it seems it's caused by a libxml2 issue, but updating it on RHEL5 doesn't help, 

#yum update libxml2

 

References 

http://www.mail-archive.com/dev@httpd.apache.org/msg36321.html 

http://en.wikipedia.org/wiki/CalDAV 

http://caldav.calconnect.org/implementations/servers.html 

https://wiki.mozilla.org/Calendar:QA_CalDAV_Support 

http://blogs.nologin.es/rickyepoderi/index.php?/archives/14-Introducing-CalDAV-Part-I.html 

http://forums.mozillazine.org/