Setting up mod_dav to share iCal.app calendars
As long as you don't need multiple clients accessing one calendar file (eg write access from iCal.app and a web interface) or need to have multiple people editing a single calendar, a full fledged groupware server like OpenGroupware.org might be overkill.
For people who just want to have a simple single-writer / multi-reader
calendar sharing
there is a very simple solution if you use an
iCalendar based native application:
Apache mod_dav.
This article tries to give some background information and instructions
on how to setup iCal calendar sharing on
Debian Sarge.
Table of contents:
- Background
- Important: Shortcomings
- Install Overview
- Special Case: FreeBusy Publish / Subscribe
- File Sharing a.k.a iDisk
Background
Most of the available OpenSource calendaring clients
(KDE Kontact,
Mozilla Sunbird,
Novell Evolution)
as well as the
Apple iCal application
use the so called
iCalendar
standard
(RFC 2445)
to store their calendaring data in a file.
All of them allow you to retrieve such iCalendar entities using
HTTP, that is, from a webserver. This is often called an
iCalendar subscription.
Most of the clients further allow you to publish calendar files
to a website which supports the
WebDAV
protocol (an extension of HTTP).
We call this "protocol" iCalendar-over-HTTP. Actually this is not specified in any RFC but is a rather simple application of HTTP / WebDAV which got popular by the Apple iCal.app (though it was by no means the first application supporting this!) in combination with public web services providing a variety of calendars. Examples include the service of Apple or iCalShare.
Besides this, there are other emerging protocols like CalDAV or GroupDAV. Those protocols attempt to fix the shortcomings of iCal-over-HTTP to allow improved calendar sharing but are not the topic of this article.
Sidenote: Most full fledged groupware servers also support the iCal-over-HTTP protocol. In the case of OpenGroupware.org this is done by the so called ZideStore server. But: most servers do not store a verbatim copy of the iCal entities and might not provide all iCal events provided by the client and therefore can lack some capabilities.
.MAC:
Apple provides a $$$ service called .MAC which allows calendar sharing
among other things (email, picture and file sharing, etc).
We are reproducing part of the functionalities with this article.
Important: Shortcomings
It is very important to understand the issues of
iCal-over-HTTP
as you might otherwise lose data through incorrect
usage!
Basically the thing which is not possible in a useful way is
using either multiple clients, computers or users to publish
(in other words: edit) a calendar.
Read-only calendar sharing is no issue (subscription).
The reason for that is that iCal-over-HTTP transfers
a full calendar
and provides no event-level granularity.
That means that if you for example delete a single appointment in your
calendar, the client will remove the event from its local iCalendar file
and then retransmit the full calendar to the server.
The same goes for editing a single event, adding new events etc.
It will always result in the full calendar being transmitted.
To illustrate the problem a small sequence of operations:
- User A subscribes a calendar with two events, the client fetches the calendar from the webserver
- User B subscribes the same calendar
- User A adds a new event to the calendar and makes the client publish the change to the webserver
- User B changed one of the two events and also publishes
Sidenote: There are some HTTP mechanisms (e.g. HTTP etags in combination with if-modified headers) which can be used to detect changes to calendars prior writing. Yet this is supported by few (none?) of the clients and even if it is supported, it doesn't resolve the issue of granularity (you can only really choose between rejecting all of your changes or overwriting all of the server changes unless the client is really smart and provides a cool tool to merge changes - none does :-)
Some clients improve the situation by refreshing the cache more often,
e.g. prior each attempt to write, but this doesn't really change the
issue.
The only real solution is provided by the Apple iCal.app by limiting the
user interface.
For each calendar you must choose whether it is subscribed or published.
You can't have a writable calendar subscription nor can you automatically
fill a writable calendar (which in turn can be published) from a
webserver.
Note that you can actually workaround that by exposing the same calendar
file under different URLs but this is strongly discouraged as
you will run into all the issues described!
All other clients do not put write limits on iCalendar subscriptions
and therefore can quickly result in major data loss as described above
unless you are very careful.
Summary: only allow one user and client write access to a calendar file stored on a WebDAV server. Otherwise you will run into havoc sooner or later. This is usually no problem with Apple iCal.app but an issue with all other iCal apps.
Install Overview
The installation itself can be done in less than 15 minutes assuming that you already have an Apache server running on a Debian Sarge system.
Steps:
- Install Apache mod_dav
- Setup a directory for the calendars on the server
- Configure Apache to use WebDAV for the directory
- Test the installation
- Configure your iCal.app
- Optional: Install PHP iCalendar for read-only web-access
Install Apache mod_dav
First thing to do is to install the Apache mod_dav module. This is a simple call on Debian:
apt-get install libapache-mod-dav
Thats it. Relevant files:
# ls /etc/apache/conf.d/libapache-mod-dav /etc/apache/conf.d/libapache-mod-dav
Setup a directory for the calendars on the server
While you can enable WebDAV for the whole website, we recommend that you create a single directory for the calendars. We called ours 'davcal':
# ls -lad /var/www/davcal/ drwxr-xr-x 3 www-data root 4096 Nov 6 17:32 /var/www/davcal/
To create the directory, run:
# mkdir /var/www/davcal/ # chown www-data /var/www/davcal/
Important: Do not forget the chown call! If the directory is not writable by the Apache daemon, you won't be able to publish calendars to the server and get 403 Forbidden errors.
Configure Apache to use WebDAV for the directory
To enable WebDAV on the given calendar folder edit the /etc/apache/conf.d/libapache-mod-dav using your favorite text editor (e.g. Emacs or VIM). It should look like:
# cat /etc/apache/conf.d/libapache-mod-dav <IfModule mod_dav.c> DAVLockDB /var/lock/DAV/apache # Below is a sample configuration. # The configuration could e.g. also be at VirtualHosts # # Please read the documentation to the security risks before # enabling WebDAV! <Location /davcal> DAV On #<LimitExcept GET OPTIONS> # require user 1234 #</LimitExcept> </Location> </IfModule>
Note that "DAV On" is uncommented and that the Location is set to our calendar folder (/davcal). Per default the whole website is enabled for WebDAV.
After configuration you need to restart Apache:
# apachectl restart
Important: The above configuration allows read/write access for everyone able to reach the site! So you probably want to limit access to this directory using the standard Apache control mechanisms (eg htpasswd). You can also use access control to ensure that users only edit their own files to avoid iCal-over-HTTP editing conflicts (by allowing GET access for all or some but PUT access only for the file owner).
TODO: describe htpasswd to protect the folder for certain users
Test the installation
We recommend that you first test your WebDAV server using a low level tool, more exactly Cadaver. Its easy to install on Debian:
apt-get install cadaver
Then run the tool and use 'edit' to check whether publishing is going to work:
# cadaver http://localhost/davcal/
dav:/davcal/> edit test.txt
Locking `test.txt': succeeded.
Downloading `/davcal/test.txt' to /tmp/cadaver-edit-o55etq.txt [..] failed:
404 Not Found
Running editor: `vi /tmp/cadaver-edit-o55etq.txt'...
[VI pops up here, optionally edit some text, then exist with ":wq!"]
Changes were made.
Uploading changes to `/davcal/test.txt'
Progress: [=============================>] 100.0% of 4 bytes succeeded.
Unlocking `test.txt': succeeded.
dav:/davcal/> ls
Listing collection `/davcal/': succeeded.
test.txt 4 Nov 6 20:44
dav:/davcal/>
If this doesn't work, check you Apache error logfile (/var/log/apache/error_log).
Configure your iCal.app
To publish a file open iCal.app and select a local calendar you want
to share. The following instructions are for iCal.app of OSX 10.4.3,
its similiar on older OSX versions.
In the "Calendar" menu select the "Publish..." item which will popup
the publishing dialog sheet. In the "Publish on:" popup select
"a Private Server".
The "Base URL" is "http://yourserver/davcal/". Do not specify a filename,
iCal.app automatically derives that from the calendar name in the first
textfield of the sheet.
Provide some Login/Password. Anything will do unless you have already
protected the directory in the Apache server (using htaccess or
something).
Fill out the other options as you wish and press the "Publish" button.
Thats it! Other people should now be able to subscribe the calendar in their iCal.
TODO: add instructions for other clients.
Optional: Install PHP iCalendar for read-only web-access
PHP iCalendar is a PHP script to display an iCalendar file stored on a server as an HTML page. Basically the same thing is provided as part of .MAC.
Add those lines to your Debian /etc/apt/sources.list:
deb http://cgi.sfu.ca/~jdbates/debian/ . . deb-src http://cgi.sfu.ca/~jdbates/debian/ . .
and run as root:
# apt-get update # apt-get install phpicalendar # apachectl restart
This will place files in:
# ls /usr/share/phpicalendar/ admin error.php includes month.php rss week.php calendars functions index.php preferences.php search.php year.php day.php images languages print.php templates # ls /etc/phpicalendar/ apache.conf config.inc.php # ls /etc/apache/conf.d/phpicalendar /etc/apache/conf.d/phpicalendar # (link to /etc/phpicalendar/apache.conf) # ls /var/lib/phpicalendar/calendars/ Home.ics US Holidays.ics Work.ics
You can check out the default calendars by following this URL:
http://localhost/phpicalendar/index.php.
As usual replace "localhost" with your server name.
To configure your own directory of WebDAV enabled calendars you need to edit /etc/phpicalendar/config.inc.php. Set this option:
$calendar_path = '/var/www/davcal';
Thats it! You can access the calendars using:
http://localhost/phpicalendar/index.php.
There are plenty of other things you can configure, please refer to the PHP iCalendar website for more information.
Note: As usual for PHP scripts PHP iCalendar might not be the most secure thing on Earth ... security advisory.
Special Case: FreeBusy Publish / Subscribe
Besides full calendar sharing using iCal-over-HTTP even more clients - including Microsoft Outlook - support accessing and publishing iCalendar freebusy files. A freebusy file is similiar to an iCalendar calendar but only contains the time when an event starts and when an event ends, no further details on the event (like the title, description or attendees).
TODO: show how FB publish works in Outlook and Kontact.
TODO: find some tool which extracts freebusy information from full iCalendar files, run it periodically via cron and push the info to same public webserver section.
File Sharing a.k.a. iDisk
Using the instructions above you should now be capable to setup
arbitary webserver directories for file sharing over WebDAV / HTTP.
Somewhat similiar to what is provided by the Apple iDisk.
You can also access such WebDAV shares from Windows (using WebFolders)
or Linux (e.g. using Konqueror or Nautilus).
At least on MacOSX the difference is that Apple iDisk synchronizes files with the local disk while the Finder WebDAV support only provides "online access" to the files stored on the server (if you are offline, you can't access the files). You can use tools like Unison to add offline capabilities on top of that.
Thats it
May the source be with you!
TODO: well, everything could be described much better. Patches are welcome! ;-)