Back in my original 'calendarserver on Linux' posting, I wrote about how to set up Apple's Darwin Calendar Server (DCS) on Ubuntu Linux. At the time, I neglected to mention that was Ubuntu 8.10. This turns out to be important, because I have since built a new server using Ubuntu 9.10 and discovered some important differences in the new Ubuntu.
Ubuntu 9.10's calendarserver package is broken
First of all, the calendarserver package provided by Ubuntu is broken and uninstallable. It depends on the python-xml package, which has been removed.
[sudo] password for alex:
Reading package lists... Done
Building dependency tree
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:
The following packages have unmet dependencies:
calendarserver: Depends: python-xml but it is not installable
E: Broken packages
There are a few bugs open on this subject. You should check on these before going further. The calendarserver package may be fixed by this time, and you can simply install it rather than building the whole thing yourself as described in the remainder of this post.
https://bugs.launchpad.net/ubuntu/+source/calendarserver/+bug/426778
https://bugs.launchpad.net/ubuntu/+source/calendarserver/+bug/403349
Initial Setup
Install some packages DCS needs to run.
One caveat... I'm fairly sure this is not a complete list. Until I get another 9.10 VM started up to test my instructions, this is my best guess on prerequisite packages you'll need.
Create a user to run as. I added my user to the 'ssl-cert' group so I can access the system-wide self-signed certificate. You don't need this if you're not going to serve calendars over HTTPS, or if you have your own certificate stored elsewhere.
DCS uses filesystem extended attributes to store some data. You'll need to enable the 'user_xattr' flag on the filesystem which will host your calendaring data. See my previous post on DCS (linked above) for instructions on how to do this. That post also has more information on configuration you may find helpful.
Now get a copy of the source code. As of now, version 2.3 is the latest DCS release. You can check http://svn.calendarserver.org/repository/calendarserver/CalendarServer/t... to see if anything newer is now available.
sudo chown caldavd:caldavd /usr/local/src/caldavd
sudo su - caldavd
cd /usr/local/src/caldavd
svn co http://svn.calendarserver.org/repository/calendarserver/CalendarServer/tags/release/CalendarServer-2.3
Building and Installing
./run -h # this will show you what's possible.
./run -i /home/caldavd
DCS includes its own miniature build system which knows how to download all its prerequisites and build them for you. This command './run -i' will download all these various things (like memcached, PyXML, pydirector, Twisted, etc) to /usr/local/src/caldavd, build them, and install everything into the directory you specify. In my example, this all goes into /home/caldavd.
As you might have noticed, DCS uses memcached for caching. When starting up, caldavd starts its own instance of memcached to use, which you can see in the process list of a running DCS instance. Even though ./run -i will download and build memcached for you, DCS will not start that memcached binary. You'll still need to install the memcached package from Ubuntu. This was weird to me at first. I saw that memcache had been downloaded and complied, but my DCS log file was full of errors about memcache not being available.
Setup
I followed a file layout similar to that used by the existing Ubuntu/Debian calendarserver package. The difference is that I put everything in subdirectories of /home/caldavd rather than using system directories. For example, where the package uses /var/run, I used /home/caldavd/var/run.
I did this since I plan to install the Ubunutu calendarserver once it actually works, and I don't want to worry about file clashes between the two servers at that time. Also, user caldavd already has write access in /home/caldavd, so I don't have to go flitting about the filesystem chmoding in various places.
mkdir /home/caldavd/var/run
mkdir /home/caldavd/var/data
mkdir /home/caldavd/var/docroot
mkdir /home/caldavd/log
You need three configuration files to get DCS to run. There are examples of all three available in /usr/local/src/caldavd/CalendarSserver-2.3/conf.
- /usr/local/src/caldavd/CalendarServer-2.3/conf/caldavd.plist
- /usr/local/src/caldavd/CalendarServer-2.3/conf/sudoers.plist
- /usr/local/src/caldavd/CalendarServer-2.3/conf/auth/accounts.xml
cp /usr/local/src/caldavd/CalendarServer-2.3/conf/sudoers.plist /home/caldavd/usr/local/caldavd
cp /usr/local/src/caldavd/CalendarServer-2.3/conf/auth/accounts.xml /home/caldavd/usr/local/caldavd
caldavd.plist is the main configuration file. Here is the one I'm using... I think you should be able to use this as-is if you follow the file layout I described above. If not, it's pretty easy to read the file and change paths as desired.
<!--
Copyright (c) 2006-2007 Apple Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
<a href="http://www.apache.org/licenses/LICENSE-2.0</p>
<p>Unless" title="http://www.apache.org/licenses/LICENSE-2.0</p>
<p>Unless">http://www.apache.org/licenses/LICENSE-2.0</p>
<p>Unless</a> required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!--
Public network address information
This is the server's public network address, which is provided to
clients in URLs and the like. It may or may not be the network
address that the server is listening to directly, though it is by
default. For example, it may be the address of a load balancer or
proxy which forwards connections to the server.
-->
<!-- Network host name -->
<key>ServerHostName</key>
<string>grawp.dean</string>
<!-- HTTP port [0 = disable HTTP] -->
<key>HTTPPort</key>
<integer>0</integer>
<!-- SSL port [0 = disable HTTPS] -->
<!-- (Must also configure SSLCertificate and SSLPrivateKey below) -->
<key>SSLPort</key>
<integer>8443</integer>
<!--
Network address configuration information
This configures the actual network address that the server binds to.
-->
<!-- List of IP addresses to bind to [empty = all] -->
<key>BindAddresses</key>
<array><string></string></array>
<!-- List of port numbers to bind to for HTTP [empty = same as "Port"] -->
<key>BindHTTPPorts</key>
<array></array>
<!-- List of port numbers to bind to for SSL [empty = same as "SSLPort"] -->
<key>BindSSLPorts</key>
<array></array>
<!--
Data Store
-->
<!-- Data root -->
<key>DataRoot</key>
<!--<string>/var/run/caldavd</string>-->
<string>/home/caldavd/var/data</string>
<!-- Document root -->
<key>DocumentRoot</key>
<!--<string>/var/spool/caldavd</string>-->
<string>/home/caldavd/var/docroot</string>
<!-- User quota (in bytes) -->
<key>UserQuota</key>
<integer>104857600</integer><!-- 100Mb -->
<!-- Attachment size limit (in bytes) -->
<key>MaximumAttachmentSize</key>
<integer>1048576</integer><!-- 1Mb -->
<!--
Directory service
A directory service provides information about principals (eg.
users, groups, locations and resources) to the server.
A variety of directory services are available for use.
-->
<!-- XML File Directory Service -->
<key>DirectoryService</key>
<dict>
<key>type</key>
<string>twistedcaldav.directory.xmlfile.XMLDirectoryService</string>
<key>params</key>
<dict>
<key>xmlFile</key>
<string>/home/caldavd/usr/local/caldavd/accounts.xml</string>
</dict>
</dict>
<!-- Open Directory Service
<key>DirectoryService</key>
<dict>
<key>type</key>
<string>twistedcaldav.directory.appleopendirectory.OpenDirectoryService</string>
<key>params</key>
<dict>
<key>node</key>
<string>/Search</string>
<key>requireComputerRecord</key>
<true/>
</dict>
</dict>
-->
<!--
Special principals
These principals are granted special access and/or perform
special roles on the server.
-->
<!-- Principals with "DAV:all" access (relative URLs) -->
<key>AdminPrincipals</key>
<array>
<!-- <string>/principals/users/admin/</string> -->
</array>
<!-- Principals that can pose as other principals -->
<key>SudoersFile</key>
<string>/home/caldavd/usr/local/caldavd/sudoers.plist</string>
<!-- Create "proxy access" principals -->
<key>EnableProxyPrincipals</key>
<true/>
<!--
Authentication
-->
<key>Authentication</key>
<dict>
<!-- Clear text; best avoided -->
<key>Basic</key>
<dict>
<key>Enabled</key>
<false/>
</dict>
<!-- Digest challenge/response -->
<key>Digest</key>
<dict>
<key>Enabled</key>
<true/>
<key>Algorithm</key>
<string>md5</string>
<key>Qop</key>
<string></string>
</dict>
<!-- Kerberos/SPNEGO -->
<key>Kerberos</key>
<dict>
<key>Enabled</key>
<true/>
<key>ServicePrincipal</key>
<string></string>
</dict>
</dict>
<!--
Logging
-->
<key>Verbose</key>
<false/>
<!-- Apache-style access log -->
<key>AccessLogFile</key>
<string>/home/caldavd/log/access.log</string>
<key>RotateAccessLog</key>
<false/>
<!-- Server activity log -->
<key>ErrorLogFile</key>
<string>/home/caldavd/log/error.log</string>
<!-- Server statistics file -->
<key>ServerStatsFile</key>
<string>/home/caldavd/var/spool/stats.plist</string>
<!-- Server process ID file -->
<key>PIDFile</key>
<string>/home/caldavd/var/run/caldavd.pid</string>
<!--
SSL/TLS
-->
<!-- Public key -->
<key>SSLCertificate</key>
<string>/etc/ssl/certs/ssl-cert-snakeoil.pem</string>
<!-- Private key -->
<key>SSLPrivateKey</key>
<string>/etc/ssl/private/ssl-cert-snakeoil.key</string>
<!--
Process management
-->
<key>UserName</key>
<string>caldavd</string>
<key>GroupName</key>
<string>caldavd</string>
<key>ProcessType</key>
<string>Combined</string>
<key>MultiProcess</key>
<dict>
<key>ProcessCount</key>
<integer>1</integer> <!-- 0 = one per CPU core -->
</dict>
<!--
Non-standard CalDAV extensions
-->
<!-- Calendar Drop Box -->
<key>EnableDropBox</key>
<true/>
<!-- Drop Box Notifications -->
<key>EnableNotifications</key>
<true/>
<!--
Miscellaneous items
-->
<key>Twisted</key>
<dict>
<key>twistd</key>
<string>/home/caldavd/usr/local/bin/twistd</string>
</dict>
<key>PythonDirector</key>
<dict>
<key>pydir</key>
<string>/home/caldavd/usr/local/bin/pydir.py</string>
<key>ControlSocket</key>
<string>/home/caldavd/var/run/caldavd-pydir.sock</string>
</dict>
<!-- A unix socket used for communication between the child and master processes. -->
<key>ControlSocket</key>
<string>/home/caldavd/var/run/caldavd.socket</string>
<key>GlobalStatsSocket</key>
<string>/home/caldavd/var/run/caldavd-stats.sock</string>
<!-- Support for Content-Encoding compression options as specified in RFC2616 Section 3.5 -->
<key>ResponseCompression</key>
<true/>
</dict>
</plist>
Starting DCS
/home/caldavd/usr/local/bin/caldavd -X -f /home/caldavd/usr/local/caldavd/caldavd.plist -T /home/caldavd/usr/local/bin/twistd
This causes DCS to start up in the foreground (-X). You'll see the server starting up. Watch for any Python exceptions and other errors. As I said, I'm afraid I've not captured all the steps you may need to perform to get DCS running, and any omissions will probably show themselves at this point. Try browsing to https://your.server:8443/ and see what you get! Post comments if you run into errors. I'll be checking my own work soon, and will correct things as needed.
Getting an Init Script
mkdir debian
cd debian
apt-get source calendarserver
cd calendarserver-1.2.dfsg/debian
Have a look at calendarserver.init.d. This requires only very minimal modifications :
DAEMON=/home/caldavd/usr/local/bin/caldavd
RUNDIR=/home/caldavd/var/run/
SPOOLDIR=/home/caldavd/var/spool/
# add these
DAEMON_OPTS='-f /home/caldavd/usr/local/caldavd/caldavd.plist -T /home/caldavd/usr/local/bin/twistd'
export PYTHONPATH=/home/caldavd/usr/local/lib/python2.6:/home/caldavd/usr/local/lib/python2.6/dist-packages
I also removed the references to /etc/default/calendarserver, and the check_start_daemon() function. After copying the modified script to /etc/init.d/caldavd, I did
And now my caldavd will be started and stopped automatically when the machine starts and stops.
Hopefully, Ubuntu or Debian will just fix their package, and these kinds of shenanigans won't be necessary at all. But in case you're like me and want to use Ubuntu 9.10, but also really need DCS to work, I hope this is helpful.
