package caldav
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=47e8daa3246d42bab21696d7a81a8b2e5cf68551f64be440778d4ea70c4ec04a
sha512=881692617a96640dbaeff056bccd3ef57aa06baaae2cd2faaaf7adf76b0c0bcd0a573ab348185064e1a40cf8bc44660c4f0891d9e259b48ccb55847774890854
Description
A CalDAV server (RFC 4791). Supports everything from the robur-coop/icalendar library. Also includes a partial WebDAV implementation.
README
Live test server
A test caldav server is setup at https://calendar.robur.coop, which is a unikernel pushing to our calendar git repository. Please try using "mirage" as user and password either on our test server which serves as well a CalDavZAP user interface or configure our test server in your calendar client (calendar.robur.coop
). You can choose any not-yet-used username and password, an account will be created by caldav (using the "trust on first use" argument described below).
Installing as binary
Reproducible binaries are available at https://builds.robur.coop/job/caldav/
Compilation of CalDAV server unikernel
To begin the installation, you need to ssh
into your server. Then, you need to install opam
via your package manager (e.g. apt install opam
). Make sure you have OCaml version >=4.10.0
, and opam version >=2.1.0
and mirage version >=4.5.0
installed via your package manager. You can use ocaml --version
, opam --version
, and mirage --version
to find out.
It is recommended to use a custom opam switch:
opam switch create caldav 4.14.0
eval `opam env`
opam install lwt mirage
Now we're ready to compile the CalDAV server. Let's get the code:
git clone https://github.com/robur-coop/caldav.git
cd caldav/mirage
mirage configure // -t xen / -t hvt works as well
make depend
make
The make
command creates a caldav
executable in caldav/mirage
. This is the unikernel. If you compiled for unix (the default unless you specify -t xen/hvt/..
, this is an executable you can run directly: We can see all its options:
./dist/caldav --help
For other targets you have to create a virtual machine, e.g. solo5-hvt:
sudo solo5-hvt --net:service=tap100 -- caldav.hvt
CalDavZAP integration
CalDavZap is an externally developed web-UI for caldav servers. Embedding into this unikernel provides the web interface at https://calendar.example.com/index.html
.
A minified and configured version can be obtained from here, which is based on the zip file and patch below.
Download https://www.inf-it.com/CalDavZAP_0.13.1.zip (3936373 bytes, SHA256 1fb67a4f85c699bfd73f282407d60852f6649a34a923770ae2a378b4f2794dde) and unpack into mirage/caldavzap
directory.
Edit mirage/caldavzap/config.js
diff -ur caldavzap/config.js mirage/caldavzap/config.js
--- a/config.js 2015-09-22 15:29:59.000000000 +0200
+++ b/config.js 2019-11-10 00:46:12.653501000 +0100
@@ -335,12 +335,11 @@
href: location.protocol+'//'+location.hostname+
(location.port ? ':'+location.port: '')+
- location.pathname.replace(RegExp('/+[^/]+/*(index\.html)?$'),'')+
- '/caldav.php/',
+ '/principals/',
timeOut: 90000,
lockTimeOut: 10000,
checkContentType: true,
settingsAccount: true,
- delegation: true,
+ delegation: false,
additionalResources: [],
hrefLabel: null,
forceReadOnly: null,
Running the unikernel
The following steps vary based on your desired server features.
HTTPS preparations
If you're planning to use https you need to create a certificate:
opam install certify
certify selfsign -c server.pem -k server.key "calendar.example.com"
mv server.pem server.key caldav/mirage/tls/
cd caldav/mirage ; make
You can also copy an existing certificate and private key to that location.
First start
To start the server, we need a git remote (possibly with credentials) and an admin password, which will be used for the user root
that always exists. The password needs to be set on first run only. It will then be hashed, salted and stored in the git repository. The git repository persists on disk when the unikernel is not running. It's the part with your precious user data that you might want to back up.
You have to set up a git repository and provide access to that, either using git_daemon and --enable=receive-pack
(then everybody can push :/), or via https, or ssh with an RSA key. You can run awa_gen_key
to get a seed (to be passed to the unikernel) and a public key (which you need to enable access to the git repository).
The arguments for the command line vary depending on the setup:
With HTTP server and git via TCP
--admin-password="somecoolpassword" --host="calendar.example.com" --http=80 --remote=git://git.example.com/calendar-data.git
With HTTPS server and git via https
--admin-password="somecoolpassword" --host="calendar.example.com" --http=80 --https=443 --remote=https://user:pass@git.example.com/calendar-data.git
With HTTPS + trust on first use (tofu) and git via ssh:
--admin-password="somecoolpassword" --host="calendar.example.com" --http=80 --https=443 --tofu --remote=git@git.example.com:calendar-data.git --ssh-key=ed25519:<b64-data> --authenticator=SHA256:b64-encoded-hash-of-server-key
Use awa_gen_key --keytype=ed25519
to create a ssh private key at random.
Server administration
Create user
If you don't use trust on first use, you might want to create a new user:
curl -v -u root:somecoolpassword -X PUT "https://calendar.example.com/users/somenewuser?password=theirpassword"
Update password
If someone forgot their password, root can set a new one:
curl -v -u root:somecoolpassword -X PUT "https://calendar.example.com/users/somenewuser?password=theirpassword"
Delete user
If someone wants to leave, root can delete their account:
curl -v -u root:somecoolpassword -X DELETE "https://calendar.example.com/users/somenewuser"
Create group
You might want to create a new group. Members is an optional query parameter.
curl -v -u root:somecoolpassword -X PUT "https://calendar.example.com/groups/somenewgroup?members=ruth,viktor,carsten,else"
Update group members
You might want to update the members of a group. The members parameter will overwrite the existing group members. Be careful not to lose your groups.
curl -v -u root:somecoolpassword -X PUT "https://calendar.example.com/groups/somenewgroup?members=ruth,viktor,carsten,else"
You might want to add a member to a group.
curl -v -u root:somecoolpassword -X PUT "https://calendar.example.com/groups/somenewgroup/users/ruth"
You might want to remove a member from a group.
curl -v -u root:somecoolpassword -X DELETE "https://calendar.example.com/groups/somenewgroup/users/ruth"
Delete group
You might want to delete a group. Root can do this.
curl -v -u root:somecoolpassword -X DELETE "https://calendar.example.com/groups/somenewgroup"
Make calendar public
Make the private calendar TESTCALENDAR
publicly readable for everybody, while keeping all privileges for the OWNER
.
curl -v -u root:somecoolpassword -X PROPPATCH -d '<?xml version="1.0" encoding="utf-8" ?>
<D:propertyupdate xmlns:D="DAV:">
<D:set>
<D:prop>
<D:acl>
<D:ace>
<D:principal><D:href>/principals/OWNER/</D:href></D:principal>
<D:grant><D:privilege><D:all/></D:privilege></D:grant>
</D:ace>
<D:ace>
<D:principal><D:all/></D:principal>
<D:grant><D:privilege><D:read/></D:privilege></D:grant>
</D:ace>
</D:acl>
</D:prop>
</D:set>
</D:propertyupdate>' "https://calendar.example.com/calendars/TESTCALENDAR"
Make calendar private
Make the calendar TESTCALENDAR
private, only accessible for the OWNER
.
curl -v -u root:somecoolpassword -X PROPPATCH -d '<?xml version="1.0" encoding="utf-8" ?>
<D:propertyupdate xmlns:D="DAV:">
<D:set>
<D:prop>
<D:acl>
<D:ace>
<D:principal><D:href>/principals/OWNER/</D:href></D:principal>
<D:grant><D:privilege><D:all/></D:privilege></D:grant>
</D:ace>
</D:acl>
</D:prop>
</D:set>
</D:propertyupdate>' "https://calendar.example.com/calendars/TESTCALENDAR"
Vendored ocaml-webmachine
This project contains a vendored ocaml-webmachine (developed by Spiros Eliopoulos), using the webdav branch of https://github.com/robur-coop/ocaml-webmachine in the ocaml-webmachine
subdirectory (at commit fecaf3dfb9ce10821e86ca07e8bfe09afb1f73d0). The reason is because this version of webmachine has support for PROPFIND, PROPPATCH, REPORT HTTP verbs, as required by wedav. This is installed as caldav.webmachine
sublibrary.
Dependencies (25)
-
uri
>= "4.0.0"
-
dispatch
>= "0.5.0"
-
re
>= "1.7.2"
- metrics
-
ohex
>= "0.2.0"
-
logs
>= "0.6.3"
-
ppx_sexp_conv
>= "v0.12.0"
-
sexplib
>= "v0.12.0"
-
icalendar
>= "0.1.8"
-
tyxml
>= "4.3.0"
-
xmlm
>= "1.3.0"
-
base64
>= "3.0.0"
-
mirage-crypto-rng-mirage
>= "1.0.0"
-
mirage-crypto-rng
>= "1.0.0"
-
digestif
>= "1.2.0"
-
cohttp-lwt
>= "2.0.0"
-
cohttp
>= "2.0.0"
-
ptime
>= "0.8.5"
-
lwt
>= "4.0"
-
ppx_deriving
>= "4.3"
-
mirage-clock
>= "2.0.0"
-
mirage-kv
>= "6.0.0"
-
fmt
>= "0.8.7"
-
dune
>= "3.12"
-
ocaml
>= "4.08.0"
Dev Dependencies (7)
-
mirage-crypto-rng-lwt
with-test & >= "1.0.0"
-
cohttp-lwt-unix
with-test & >= "2.0.0" & < "6.0.0~~"
-
mirage-kv-mem
with-test & >= "2.0.0"
-
mirage-clock-unix
with-test & >= "2.0.0"
-
tcpip
with-test & >= "3.7.0"
-
ounit2
with-test & >= "2.0.0"
-
alcotest
with-test & >= "0.8.5"
Used by
None
Conflicts (1)
-
result
< "1.5"