Skip to content

Instantly share code, notes, and snippets.

@essandess
Last active September 24, 2020 01:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save essandess/4c9b5d906896ff4aef6170fc18f2c293 to your computer and use it in GitHub Desktop.
Save essandess/4c9b5d906896ff4aef6170fc18f2c293 to your computer and use it in GitHub Desktop.
CalendarServer Server.app Migration [WIP]

CalendarServer Server.app Migration [WIP]

Create the calendarserver account, password, install directories

# choose a free uid < 500; uid 350 is used here
dscl . -list /Users UniqueID | sort -n -k2

sudo bash <<CREATE_SYSTEM_USER
dscl . -create /Users/calendarserver RealName calendarserver
dscl . -create /Users/calendarserver NFSHomeDirectory /private/var/calendarserver
dscl . -create /Users/calendarserver UserShell /bin/bash
dscl . -create /Users/calendarserver UniqueID 350
dscl . -create /Users/calendarserver PrimaryGroupID 20
dscl . -create /Users/calendarserver Password "calendarserver@host.domain.tld's password"
CREATE_SYSTEM_USER

# /var/calendarserver is calendarserver's $HOME, ~/Library/CalendarServer is ccs-calendarserver's install dir
sudo bash <<CREATE_CALENDARSERVER_HOME
mkdir -p /private/var/calendarserver/Library/CalendarServer
chown -R calendarserver /private/var/calendarserver
chmod 0750 /private/var/calendarserver
CREATE_CALENDARSERVER_HOME

Add passwords to the server's keychain and test with the code used by getPasswordFromKeychain(). Change the account calendarserver's password to a strong password and save to the Keychain. Grant access to all services. Note that the "account" in the keychain must be in the form of calendarserver@host.domain.tld, which is what the code looks for.

sudo bash <<ADD_PASSWORD_TO_SYSTEM_KEYCHAIN
/usr/bin/security add-generic-password -a calendarserver@host.domain.tld -s org.calendarserver -w "calendarserver's password" -A /Library/Keychains/System.keychain
ADD_PASSWORD_TO_SYSTEM_KEYCHAIN

# test with ccs-calendarserver code
sudo -u calendarserver /usr/bin/security find-generic-password -a calendarserver -g

Clone and install ccs-calendarserver

Clone the latest from Apple. Apple working build on 10.14: Use MacPorts openssl as the system openssl for the calendarserver build, but do not use MacPorts Python binaries or libraries. Also, account calendarserver will not and should not be a sudoer.

As sudoer:

sudo sh -x <<INSTALL_DEPENDENCIES
# macOS-native Python needs the pip module
/usr/bin/easy_install pip

# MacPorts openssl, virtualenv-2.7, postgresql
port -pN install openssl py27-virtualenv virtualenv_select py27-pip pip_select postgresql96-server postgresql_select
port select --set virtualenv virtualenv27
port select --set postgresql postgresql96
# in case macOS-native `easy_install pip` breaks in the future, like `easy_install virtualenv` does now
port -pN install py27-pip pip_select
port select --set pip pip27
INSTALL_DEPENDENCIES
which virtualenv

Build and install CalendarServer as the user calendarserver:

sudo -iu calendarserver

mkdir /var/calendarserver/Library/CalendarServer
echo "source /var/calendarserver/Library/CalendarServer/environment.sh" > ~/.profile

git clone https://github.com/apple/ccs-calendarserver.git
# git clone -b release/CalendarServer-9.3 https://github.com/apple/ccs-calendarserver.git

cd ccs-calendarserver

# /opt/local is deprecated, but included for openssl, virtualenv
sh -x <<PACKAGE_CALENDARSERVER
(
    export USE_OPENSSL=1  # Don't use SecureTransport
    export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/opt/local/bin:/opt/local/sbin:/usr/local/bin
    export C_INCLUDE_PATH=/usr/include:/usr/local/include:/opt/local/include
    export LD_LIBRARY_PATH=/usr/lib:/usr/local/lib:/opt/local/lib:/opt/local/lib/openssl-1.0
    export CPPFLAGS='-I/usr/include -I/usr/local/include -I/opt/local/include'
    export LDFLAGS='-L/usr/lib -L/usr/local/lib -L/opt/local/lib -L/opt/local/lib/openssl-1.0'
    export DYLD_LIBRARY_PATH=/usr/lib:/usr/local/lib:/opt/local/lib:/opt/local/lib/openssl-1.0

    ./bin/package -F /private/var/calendarserver/Library/CalendarServer 1> ~/ccs-calendarserver.log 2>&1
)
PACKAGE_CALENDARSERVER

Create site-specific directories, configurations, set permissions

As calendarserver:

# Configuration
mkdir -p /var/calendarserver/Library/CalendarServer/Config
chgrp _calendar /var/calendarserver/Library/CalendarServer/Config
chmod 0750 /var/calendarserver/Library/CalendarServer/Config

# Logs
mkdir -p /var/calendarserver/Library/CalendarServer/logs
chgrp _calendar /var/calendarserver/Library/CalendarServer/logs
chmod 0750 /var/calendarserver/Library/CalendarServer/logs

# PostgreSQL
mkdir -p /var/calendarserver/Library/CalendarServer/Data/Database
chgrp -R _calendar /var/calendarserver/Library/CalendarServer/Data
chmod -R 0700 /var/calendarserver/Library/CalendarServer/Data

# calendarserver config file
vi /var/calendarserver/Library/CalendarServer/Config/calendarserver.plist

# nginx reverse proxy configuration
mkdir -p /var/calendarserver/Library/CalendarServer/etc
vi /var/calendarserver/Library/CalendarServer/etc/nginx.conf
mkdir -p /var/calendarserver/Library/CalendarServer/etc/nginx_root
vi /var/calendarserver/Library/CalendarServer/etc/nginx_root/default.html  # unused, but nginx root is here
openssl dhparam -out /var/calendarserver/Library/CalendarServer/etc/dhparam.pem 4096

# Launch daemons
mkdir -p /var/calendarserver/Library/CalendarServer/Config/LaunchDaemons
vi /var/calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.calendarserver.plist
vi /var/calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.nginx_proxy.plist

# ccs-calendarserver's postgres code points to `PSQL = "../postgresql/_root/bin/psql"`
mkdir -p /var/calendarserver/Library/CalendarServer/postgresql
ln -s /opt/local /var/calendarserver/Library/CalendarServer/postgresql/_root

As sudoer:

sudo sh -x <<CALENDARSERVER_SPECIFICS
mkdir /var/run/caldavd
chown -R calendarserver:_calendar /var/run/caldavd
chmod 0770 /var/run/caldavd
mkdir /var/run/caldavd_requests
chown -R calendarserver:_calendar /var/run/caldavd_requests
chmod -R 0770 /var/run/caldavd_requests
CALENDARSERVER_SPECIFICS

Launch it all

As sudoer:

sudo sh -x <<LAUNCH_CALENDARSERVER
install -m 0644 /var/calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.calendarserver.plist /Library/LaunchDaemons
install -m 0644 /var/calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.nginx_proxy.plist /Library/LaunchDaemons

launchctl load -w /Library/LaunchDaemons/org.calendarserver.calendarserver.plist
launchctl load -w /Library/LaunchDaemons/org.calendarserver.nginx_proxy.plist
LAUNCH_CALENDARSERVER

# there should be the right stuff in these places:
ls -laR /var/run/caldavd /var/run/caldavd /var/run/caldavd_requests /var/calendarserver/Library/CalendarServer/logs

open -a Safari https://host.domain.tld:8443

TODO: APNS

Debugging, Experimentation History

Following these instructions, adding my own configuration preferences:

sudo -iu calendarserver
git clone https://github.com/apple/ccs-calendarserver.git
  echo "source CalendarServer/environment.sh" > .profile
cd ccs-calendarserver
export USE_OPENSSL=1 # Don't use SecureTransport
./bin/package /Users/calendarserver/CalendarServer
cd /Library/Server/

Create the calendarserver account and Keychain items

Use dscl to create a calendarserver system account akin to Server.app's com.apple.calendarserver account. References: man dscl, sysadminctl --help, https://www.jamf.com/jamf-nation/discussions/17674/createuserscript

Server.app server:

dscl . read Users/com.apple.calendarserver

dsAttrTypeNative:IsHidden: 1
dsAttrTypeNative:record_daemon_version: 4850000
AppleMetaNodeLocation: /Local/Default
GeneratedUID: UUID
NFSHomeDirectory: /var/empty
Password: 
PrimaryGroupID: 20
RealName: com.apple.calendarserver
RecordName: com.apple.calendarserver
RecordType: dsRecTypeStandard:Users
UniqueID: 250
UserShell: /usr/bin/false

New server. Give calendarserver a uid of 350 because the original account uid was 250; this is unused on a new Mojave system, but there's a block of uid's around this number, and it probably isn't a good idea to step into an area Apple may use in the future. Note: sudo log show --last 60s | less shows that the here document (with a password) does not appear in the system logs.

# choose a free uid < 500
dscl . -list /Users UniqueID | sort -n -k2

sudo bash <<CREATE_SYSTEM_USER
dscl . -create /Users/calendarserver RealName calendarserver
dscl . -create /Users/calendarserver NFSHomeDirectory /private/var/calendarserver
dscl . -create /Users/calendarserver UserShell /bin/bash
dscl . -create /Users/calendarserver UniqueID 350
dscl . -create /Users/calendarserver PrimaryGroupID 20
dscl . -create /Users/calendarserver Password "calendarserver@host.domain.tld's password"
CREATE_SYSTEM_USER

# /var/calendarserver is calendarserver's $HOME, ~/Library/CalendarServer is ccs-calendarserver's install dir
sudo bash <<CREATE_CALENDARSERVER_HOME
mkdir -p /private/var/calendarserver/Library/CalendarServer
chown -R calendarserver /private/var/calendarserver
chmod 0750 /private/var/calendarserver
CREATE_CALENDARSERVER_HOME

Add passwords to the server's keychain and test with the code used by getPasswordFromKeychain(). Change the account calendarserver's password to a strong password and save to the Keychain. Grant access to all services. Note that the "account" in the keychain must be in the form of calendarserver@host.domain.tld, which is what the code looks for.

sudo bash <<ADD_PASSWORD_TO_SYSTEM_KEYCHAIN
/usr/bin/security add-generic-password -a calendarserver@host.domain.tld -s org.calendarserver -w "calendarserver's password" -A /Library/Keychains/System.keychain
ADD_PASSWORD_TO_SYSTEM_KEYCHAIN

# test with ccs-calendarserver code
sudo -u calendarserver /usr/bin/security find-generic-password -a calendarserver -g

Note: sysadminctl doesn't work for system account uid's < 500

# doesn't work for uid's < 500
# sysadminctl -addUser calendarserver -fullName calendarserver -UID 250 -shell /usr/bin/false -home /var/empty
# sudo dscl . -change /Users/calendarserver UniqueID 512 250

# *does* work to delete the user
# sudo sysadminctl -deleteUser calendarserver -keepHome

Clone and install ccs-calendarserver

Latest from Apple:

sudo -iu calendarserver
mkdir -p ~/Source/github
cd ~/Source/github
mkdir apple
cd  ~/Source/github/apple
git clone https://github.com/apple/ccs-calendarserver.git
# git clone -b release/CalendarServer-9.3 https://github.com/apple/ccs-calendarserver.git

Copy the repo into a build directory.

mkdir ccs-calendarserver.build
rsync -a --exclude '.git*' --delete-excluded --del ccs-calendarserver/ ccs-calendarserver.build
echo "source /var/calendarserver/Library/CalendarServer/environment.sh" > ~/.profile
cd ccs-calendarserver.build

Follow the quickstart guide to get a basic working example

See https://www.calendarserver.org/QuickStart.html

Create a login keychain for calendarserver:

/usr/bin/security create-keychain ~/Library/Keychains/login.keychain-db
/usr/bin/security login-keychain ~/Library/Keychains/login.keychain-db
/usr/bin/security default-keychain ~/Library/Keychains/login.keychain-db

Run the develop code, start the server:

export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Server.app/Contents/ServerRoot/usr/bin:/Applications/Server.app/Contents/ServerRoot/usr/sbin:/opt/local/bin:/opt/local/sbin

unset USE_OPENSSL
unset C_INCLUDE_PATH
unset LD_LIBRARY_PATH
unset CPPFLAGS
unset LDFLAGS
unset DYLD_LIBRARY_PATH

bin/develop

bin/run -n

Browse to https://localhost:8443, https://localhost:8843. Works. No server on [?]:

Package modifications

export USE_OPENSSL=1 # Don't use SecureTransport
# ./bin/package /private/var/calendarserver/Library/CalendarServer

Apple working build on 10.14: Use MacPorts openssl as the system openssl for the calendarserver build, but do not use MacPorts Python binaries or libraries:

# macOS-native Python needs the pip module
sudo /usr/bin/easy_install pip

# /opt/local is deprecated, but included for openssl
sh -x <<PACKAGE_CALENDARSERVER
(
    export USE_OPENSSL=1  # Don't use SecureTransport
    export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/opt/local/bin:/opt/local/sbin:/usr/local/bin
    export C_INCLUDE_PATH=/usr/include:/usr/local/include:/opt/local/include
    export LD_LIBRARY_PATH=/usr/lib:/usr/local/lib:/opt/local/lib:/opt/local/lib/openssl-1.0
    export CPPFLAGS='-I/usr/include -I/usr/local/include -I/opt/local/include'
    export LDFLAGS='-L/usr/lib -L/usr/local/lib -L/opt/local/lib -L/opt/local/lib/openssl-1.0'
    export DYLD_LIBRARY_PATH=/usr/lib:/usr/local/lib:/opt/local/lib:/opt/local/lib/openssl-1.0

    ./bin/package -F /private/var/calendarserver/Library/CalendarServer 1> ~/ccs-calendarserver.log 2>&1
)
PACKAGE_CALENDARSERVER

WIP: Use MacPorts openssl as the system openssl for the calendarserver build,, but do not use MacPorts Python binaries or libraries:

First attempt to use more recent dependecies:

# Use this repo for more recent versions
cd ~/Source/github
mkdir essandess
cd  ~/Source/github/essandess
git clone -b essandess_specific https://github.com/essandess/ccs-calendarserver.git

mkdir ccs-calendarserver.build
rsync -a --exclude '.git*' --delete-excluded --del ccs-calendarserver/ ccs-calendarserver.build
echo "source /var/calendarserver/Library/CalendarServer/environment.sh" > ~/.profile
cd ccs-calendarserver.build
export USE_OPENSSL=1 # Don't use SecureTransport

# /opt/local is prioritized
sh -x <<PACKAGE_CALENDARSERVER
(
    export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
    export C_INCLUDE_PATH=/opt/local/include:/usr/include:/usr/local/include
    export LD_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/openssl-1.0:/usr/lib:/usr/local/lib
    export CPPFLAGS='-I/opt/local/include -I/usr/include -I/usr/local/include'
    export LDFLAGS='-L/opt/local/lib -L/opt/local/lib/openssl-1.0 -L/usr/lib -L/usr/local/lib'
    export DYLD_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/openssl-1.0:/usr/lib:/usr/local/lib

    ./bin/package -F /private/var/calendarserver/Library/CalendarServer 1> ~/ccs-calendarserver.log 2>&1
)
PACKAGE_CALENDARSERVER

First successful execution (after configuration below), but Python errors with the later packages:

export PYTHON=/var/calendarserver/Library/CalendarServer/bin/python
export PATH=/var/calendarserver/Library/CalendarServer/bin:/var/calendarserver/Library/CalendarServer/virtualenv/bin:/opt/local/bin:/opt/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
sudo -E /var/calendarserver/Library/CalendarServer/bin/caldavd -X -R kqueue -o FailIfUpgradeNeeded=False -f /var/calendarserver/Library/CalendarServer/Config/calendarserver.plist

File "/private/var/calendarserver/Library/CalendarServer/virtualenv/src/twextpy/twext/enterprise/dal/parseschema.py", line 724, in significant
return (not isinstance(token, Comment) and not token.is_whitespace())
TypeError: 'bool' object is not callable

This needs more work to use later libraries. See apple/ccs-calendarserver#536.

Cleaning after experiments:

ls -A1 ../ccs-calendarserver.build/ | xargs rm -fr --
rsync -a --exclude '.git*' --del ../ccs-calendarserver/ ../ccs-calendarserver.build

Configure CalendarServer and its Reverse Proxy

Configure the files /Library/LaunchDaemons/org.calendarserver.calendarserver.plist and ~/Library/CalendarServer/Config/calendarserver.plist. Server.app v5.7 reference configuration files are:

  • sudo launchctl list | fgrep -i calendar
  • /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.calendarserver.calendarserver.plist
  • /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.calendarserver.agent.plist
  • /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.calendarserver.archive.plist
  • /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.calendarserver.relocate.plist
  • /Library/Server/Calendar\ and\ Contacts/Config/caldavd-system.plist
  • sudo serveradmin set calendar
  • /Applications/Server.app/Contents/ServerRoot/Library/CalendarServer/caldavd/caldavd.plist

Additionally, Server.app v5.7's CalendarServer is run behind a reverse proxy confugured within /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf, /Library/Server/Web/Config/Proxy, /Library/Server/Web/Config/ProxyServices/CalendarServer/*.conf, and more. This is a good idea for several reasons:

  1. Modern crypto recommendations from e.g. Mozilla do not appear to be supported by ccs-calendarserver's <key>SSLMethod</key> or <key>SSLCiphers</key>. Several of these ciphers require DH parameter generation for PFS, and it's not clear where or how to configure PFS. See twisted/twisted/docs/core/howto/ssl.rst, https://github.com/twisted/twisted/blob/trunk/src/twisted/internet/_sslverify.py, and specifically twisted/twisted/src/twisted/internet/_sslverify.py#L1849-L1868.
  2. The apple/ccs-calendarserver, twisted/twisted, and dependent repos are still based upon Python 2.7 with no visible TODO's about migration to Python 3.7. Python 2.7 is EOL on January 1st, 2020, after which security upgrades will cease. And there are still regular security patches to Python 2.7.
  3. A reverse proxy capable of handling the modern crypto and some security checks, e.g. mod_security in apache or nginx, addresses some of these concerns.

The CalendarServer configuration necessarily involves both CalendarServer itself and its reverse proxy. Be sure not to expose CalendarServer to the open internet.

Baseline Server.app CalendarServer Configuration

Reference Server.app v5.7's CalendarServer configuration to determine how to wrap the service in a reverse proxy, configure APNS, and whatever else needs to be done. Compare these settings to those available in apple/ccs-calendarserver/twistedcaldav/stdconfig.py.

  1. The Server.app Web proxy listens on ports 8008 (calDAV http), 8443 (calDAV https), 8800 (cardDAV http), 8843 (cardDAV https):
  • /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf
  1. The Server.app Web proxy forwards requests to the sockets /var/run/caldavd_requests/unsecured.sock and /var/run/caldavd_requests/secured.sock.
  • /Applications/Server.app/Contents/ServerRoot/Library/Server/Web/Config/ProxyServices/CalendarServer/UnsecuredDedicated.conf
  • /Applications/Server.app/Contents/ServerRoot/Library/Server/Web/Config/ProxyServices/CalendarServer/SecuredDedicated.conf
  1. These unix sockets are created by caldavd, which is run by the plist org.calendarserver.calendarserver:
  • /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.calendarserver.calendarserver.plist
  • /Applications/Server.app/Contents/ServerRoot/usr/sbin/caldavd
  1. Inspect the logs for configuration clues:
  • /Library/Server/Logs/caldavd.log

Reading configuration from file: /Applications/Server.app/Contents/ServerRoot/private/etc/caldavd/caldavd-apple.plist
Adding configuration from file: /Library/Server/Preferences/Calendar.plist
Adding configuration from file: /Library/Server/Calendar and Contacts/Config/caldavd-system.plist
Missing configuration file: /Library/Server/Calendar and Contacts/Config/caldavd-user.plist
Created directory: /var/run/caldavd_requests
Created directory: /var/run/caldavd

  1. Configuration file caldavd-apple.plist sets up the socket, access to PostgreSQL, additional configuration and keys from the following configuration plists, a bunch of other stuff. GitHub code: caldavd-apple.plist.
  • /Applications/Server.app/Contents/ServerRoot/private/etc/caldavd/caldavd-apple.plist
  1. Configuration file caldavd-system.plist adds FQDN-specific information and configures APNS (for APNS configuration also see apple/ccs-calendarserver/twistedcaldav/test/test_config.py and apple/ccs-calendarserver/conf/caldavd-stdconfig.plist).
  • /Library/Server/Calendar\ and\ Contacts/Config/caldavd-system.plist
  1. Configuration file Calendar.plist just sets the ServerRoot key.
  • /Library/Server/Preferences/Calendar.plist
  1. IMAP and SMTPD authentication are handled with Basic/Digest/Kerberos methods and retrieval of the password from the Keychain. Make sure the appropriate settings are reflected in the final CalendarServer .plist local configuration files. There are several more than these, and it appears that a line-by-line assessment will be necessary while making the CalendarServer .plist local configuration.
  • sudo serveradmin set calendar

calendar:EnableAPNS = yes
calendar:Notifications:Services:APNS:Enabled = yes
calendar:EnableSSL = yes
calendar:Authentication:Basic:Enabled = yes
calendar:Authentication:Basic:AllowedOverWireUnencrypted = no
calendar:Authentication:Digest:Enabled = yes
calendar:Authentication:Digest:AllowedOverWireUnencrypted = yes
calendar:Authentication:Kerberos:Enabled = yes
calendar:Authentication:Kerberos:AllowedOverWireUnencrypted = yes
calendar:Scheduling:iMIP:Enabled = yes
calendar:Scheduling:iMIP:Sending:UseSSL = yes
calendar:Scheduling:iMIP:Sending:Server = "host.domain.tld"
calendar:Scheduling:iMIP:Sending:Address = "com.apple.calendarserver@host.domain.tld"
calendar:Scheduling:iMIP:Sending:Username = "com.apple.calendarserver"
calendar:Scheduling:iMIP:Sending:Password = "com.apple.calendarserver's password"
calendar:Scheduling:iMIP:Sending:Port = 587
calendar:Scheduling:iMIP:Receiving:UseSSL = yes
calendar:Scheduling:iMIP:Receiving:Server = "host.domain.tld"
calendar:Scheduling:iMIP:Receiving:Type = "imap"
calendar:Scheduling:iMIP:Receiving:Username = "com.apple.calendarserver"
calendar:Scheduling:iMIP:Receiving:Password = "com.apple.calendarserver's password"
calendar:Scheduling:iMIP:Receiving:Port = 993

  • sudo serveradmin set addressbook

addressbook:EnableAPNS = yes

  1. Also relevant (somehow) are the _calendar-owned sockets at:
  • sudo ls -l /var/run/caldavd

CalendarServer configuration

Copy these plist files to the necessary locations and auto/hand configure them. Rather than use the defaults available in apple/ccs-calendarserver/contrib/conf/org.calendarserver.plist and apple/ccs-calendarserver/contrib/conf/calendarserver.plist, use the classic Server.app configurations without TLS configured and on nonstandard ports running behind a reverse proxy.

mkdir -p ~/Library/CalendarServer/Config/LaunchDaemons
chmod 0750 ~/Library/CalendarServer/Config
cp -p ~calendarserver/Source/github/essandess/ccs-calendarserver/contrib/conf/org.calendarserver.plist ~/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.calendarserver.plist
cp -p ~calendarserver/Source/github/essandess/ccs-calendarserver/conf/caldavd-apple.plist ~/Library/CalendarServer/Config/calendarserver.plist
cp -p /Library/Server_v57/Calendar\ and\ Contacts/Config/caldavd-system.plist ~/Library/CalendarServer/Config
  • Note that DEFAULT_CONFIG_FILE is hard-coded in apple/ccs-calendarserver/twistedcaldav/stdconfig.py. Use ~/Library/CalendarServer/Config/calendarserver.plist as the configuration file, merged from caldavd-apple.plist and (writable in Server.app v5.7) caldavd-system.plist.
  • The password is retrived fom the Keychain via the function getPasswordFromKeychain. This means that caldavd must be called as root, consistent with its launchd.plist, and that the password must be saved in the Keychain as above.

Baseline auto-edits:

sed -i '' 's#/Users/calendarserver/CalendarServer#/var/calendarserver/Library/CalendarServer#g' ~/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.calendarserver.plist

Merge all the things to a ~/Library/CalendarServer/Config/calendarserver.plist configuration file.

mkdir -p ~/Library/CalendarServer/logs
mkdir -p ~/Library/CalendarServer/etc

CalendarServer PostgreSQL configuration

The part is unnecessary; caldavd forks its own postgres server if configured for it.

Create this fresh using the latest PostgreSQL version, then export/import data to populate.

Save pg_hba.conf and postmaster.opts from the original server as a reference.

mkdir -p ~/Library/CalendarServer/Data/Database.xpg/cluster.pg.orig
cp /Library/Server_v57/Calendar\ and\ Contacts/Data/Database.xpg/cluster.pg/pg_hba.conf ~/Library/CalendarServer/Data/Database.xpg/cluster.pg.orig
cp /Library/Server_v57/Calendar\ and\ Contacts/Data/Database.xpg/cluster.pg/postmaster.opts ~/Library/CalendarServer/Data/Database.xpg/cluster.pg.orig

Initialize the database. One can use port select --set postgresql postgresql96 to link commands like pg_ctl to their v96 binaries, but be explicit and point to exact binaries here for when databases must be migrated.

/opt/local/lib/postgresql96/bin/pg_ctl -U calendarserver -D ~calendarserver/Library/CalendarServer/Data/Database.xpg/cluster.pg initdb

Use the original postmaster.opts file and MacPorts's startup items as a base to create a launchd.plist and accompamying script to launch and maintain a running postgres instance for CalendarServer:

vi ~calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.postgresql96.plist
vi  ~calendarserver/Library/CalendarServer/Config/LaunchDaemons/postgresql96-server.wrapper
chmod go+x  ~calendarserver/Library/CalendarServer/Config/LaunchDaemons/postgresql96-server.wrapper
sudo cp ~calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.postgresql96.plist /Library/LaunchDaemons
sudo launchctl load -w /Library/LaunchDaemons/org.calendarserver.postgresql96.plist

The startup command in postgresql96-server.wrapper based on postmaster.opts is:

POSTGRES=/opt/local/lib/postgresql96/bin/postgres

#
# Start
#
Start()
{
        su calendarserver -c "${POSTGRES} -D ${POSTGRESQL96DATA:=/var/calendarserver/Library/CalendarServer/Data/Database.xpg/cluster.pg} -c listen_addresses= -c unix_socket_directories=/var/run/caldavd/PostgresSocket -c shared_buffers=165 -c max_connections=110 -c standard_conforming_strings=on -c unix_socket_permissions=0770 -c log_lock_waits=TRUE -c deadlock_timeout=10 -c log_line_prefix='%m [%p] ' -c log_directory=/var/calendarserver/Library/CalendarServer/logs -c log_truncate_on_rotation=on -c log_filename='postgresql_%w.log' -c log_rotation_age=1440 -c logging_collector=on -c 'log_line_prefix=%t'"
}

CalendarServer Reverse Proxy configuration

Require modern crypto.

vi mkdir -p ~/Library/CalendarServer/etc/nginx.conf
openssl dhparam -out ~/Library/CalendarServer/etc/nginx/dhparam.pem 4096

# test
sudo nginx -g "daemon off;" -c ~calendarserver/Library/Calendarrver/etc/nginx.conf

vi ~calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.nginx.plist
sudo cp ~calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.nginx.plist /Library/LaunchDaemons
sudo launchctl load -w /Library/LaunchDaemons/org.calendarserver.nginx.plist

Command line tests

Launch CalenderServer (trial-and-error on whether to launch as root or calendarserver, use _calendar group or not, use -u or -g flags or not; this is the one that works):

sudo bash -c 'sudo -u calendarserver /var/calendarserver/Library/CalendarServer/bin/caldavd -X -R kqueue -o FailIfUpgradeNeeded=False -f /var/calendarserver/Library/CalendarServer/Config/calendarserver.plist'

Clean up after CalenderServer, postgres, memcached

sudo kill -9 `sudo cat /var/run/caldavd/caldavd.pid`
sudo kill -9 `sudo readlink /var/run/caldavd/directory-proxy.sock.lock`
sudo kill -9 `ps -ef | grep memcache | grep /var/run/caldavd/memcache.sock | grep -v grep | awk '{print$2;}'`
sudo -u calendarserver /opt/local/lib/postgresql96/bin/pg_ctl -D /var/calendarserver/Library/CalendarServer/Data/Database/cluster.pg stop
ps -ef | grep CalendarServer | grep -v grep | awk '{ print $2; }' | xargs -n1 sudo kill -9
sudo bash -c 'cd /private/var/calendarserver/Library/CalendarServer/logs ; rm access.log error.log ; cd /var/run/caldavd ; rm *.sock* *.pid ; cd /var/run/caldavd/PostgresSocket ; rm *.sock* *.pid'

Launch CalendarServer

Copy the launchd.plist:

sudo cp ~/Library/CalendarServer/Config/org.calendarserver.calendarserver.plist /Library/LaunchDaemons
sudo launchctl load -w /Library/LaunchDaemons/org.calendarserver.nginx.plist
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment