Applications AWS

DAViCal 1.1.13 on AWS User Guide

| Product: DAViCal 1.1.13 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using the DAViCal 1.1.13 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg Nextcloud, office suites and workspaces listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.

DAViCal is an open source CalDAV and CardDAV server. It stores calendars, events, tasks and address books in PostgreSQL and shares them with any standards based client: Thunderbird, Apple Calendar and Contacts on macOS and iOS, DAVx5 on Android, Evolution and many more. Each user (a principal) gets a home calendar and an address book, and you can share collections between users and groups with fine grained rights. DAViCal's web interface is for administration: users, groups, collections and the rights between them.

What the cloudimg image adds:

  • No shared or stock password. First boot creates DAViCal's database with an admin password unique to your instance. No password is baked into the image, and every instance creates its own database and its own TLS certificate.
  • Passwords stored only as salted hashes. Upstream DAViCal's installer stores the admin password in plain text (marked with a leading **). On this image the admin password, and every password you set in the web interface, is stored as a salted SHA-1 hash, and re-saving a user's form without typing a new password keeps the password it had (Step 10).
  • Setup and maintenance pages unreachable. DAViCal's setup.php, upgrade.php, tools.php and metrics.php, and its scheduling and public pages, are refused by nginx. The check runs on the request exactly as the client sent it, so encoded, mixed case, doubled slash and dot segment variants are refused too.
  • No database password at all. DAViCal runs under its own PHP-FPM pool as the system user davical, and PostgreSQL 16 accepts DAViCal's database roles only over the local socket from that user (or root), by peer authentication. PostgreSQL has no network listener.
  • HTTPS from the first boot. nginx serves DAViCal on port 443 with a certificate generated on your instance, port 80 redirects to HTTPS, a request for a host name the instance does not serve gets no answer, and the session cookie is Secure and HttpOnly. nginx removes every forwarding header a client could use to pretend to be someone else, and hides DAViCal's version.
  • Abuse limits and cross site protection. Every web form post (sign in, the lost password button and the admin pages) is limited to 20 a minute per client address, so password guessing through the web interface is slow. CalDAV and CardDAV requests, which carry the password on every request, have a separate higher limit that suits real clients. Form posts must come from the instance's own pages, so a form on another site cannot act on your users' behalf.
  • Read only code and configuration. DAViCal and its AWL library are installed under /usr/share/davical and /usr/share/awl, owned by root. The davical user that runs it cannot change its code or /etc/davical/config.php.
  • Metadata access blocked, and an outbound firewall for DAViCal. nginx, PHP-FPM, PostgreSQL and first boot are blocked from the instance metadata service, and the AMI requires IMDSv2. DAViCal's own processes may connect only to public IPv4 addresses: never to the metadata service, to private or reserved ranges, to your VPC's own addresses, or to IPv6. You can let DAViCal reach specific internal addresses (Step 8).
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: DAViCal 1.1.13 and AWL 0.65 (the upstream release tarballs, sha512 verified), PHP 8.3 with PHP-FPM, nginx, PostgreSQL 16, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. No Ubuntu davical package and no Apache are used.

Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large

Prerequisites

  • An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
  • A security group that allows TCP 22 (SSH) from your admin network, and TCP 443 (DAViCal) and TCP 80 (redirects to HTTPS) from the networks your users and their calendar apps work from. Your calendars and contacts are on this server, so keep 80 and 443 as narrow as you can.

Step 1: Launch the instance

In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick DAViCal 1.1.13 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (a smaller instance is enough for a small team), your key pair and a security group as above.

With the AWS CLI (replace the values in angle brackets):

aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
  --instance-type m5.large --key-name <your-key-pair> \
  --security-group-ids <your-security-group> --subnet-id <your-subnet> \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=davical}]'

First boot creates the database and the certificate and finishes about a minute after the instance is running.

Step 2: Connect to your instance

Version SSH user
DAViCal 1.1.13 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>

Step 3: Check the services

First boot creates the PostgreSQL cluster, DAViCal's database, the admin password and the certificate; nginx and PHP-FPM start only after it has finished:

systemctl is-active nginx php8.3-fpm postgresql@16-main davical-egress-guard davical-firstboot
sudo test -f /var/lib/cloudimg/davical-firstboot.done && echo FIRSTBOOT_DONE

All five units are active and the first boot marker is present (after a later reboot davical-firstboot shows inactive, because it runs only once):

active
active
active
active
active
FIRSTBOOT_DONE

Only SSH and nginx listen on network ports. PostgreSQL has no network listener at all and PHP-FPM uses a local socket:

sudo ss -lntp | awk 'NR>1 && $4 !~ /^127\.0\.0\.5[34]/ {split($6, p, "\""); print $4, p[2]}' | sort
0.0.0.0:22 sshd
0.0.0.0:443 nginx
0.0.0.0:80 nginx
[::]:22 sshd
[::]:443 nginx
[::]:80 nginx

Step 4: Get your URL and password

sudo cat /root/davical-credentials.txt

The file is readable by root only:

# DAViCal 1.1.13 - generated on first boot by davical-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret.

DAVICAL_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/
DAVICAL_CALDAV_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/caldav.php/
DAVICAL_ADMIN_USER=admin
DAVICAL_ADMIN_PASSWORD=<DAVICAL_ADMIN_PASSWORD>
#
# Open DAVICAL_URL in a browser (self-signed certificate minted on this instance's first boot; port 80 redirects to
# https) and sign in as admin with the password above. Create your users (Principals) there; each gets a calendar
# (/caldav.php/<user>/calendar/) and an address book (/caldav.php/<user>/addresses/).
# Point CalDAV/CardDAV clients at DAVICAL_CALDAV_URL (or just the host name: /.well-known/caldav is answered).
# PostgreSQL 16: unix socket only (no TCP listener, no database password; PHP runs as the OS user davical).
# Settings: /etc/davical/config.php (then: sudo systemctl restart php8.3-fpm)
# Change the admin password:      sudo davical-set-admin-password
# Change the name it serves as:   sudo davical-set-hostname <your-dns-name>
# User guide: https://www.cloudimg.co.uk/guides/davical-1-1-13-on-ubuntu-24-04-aws/

The URL uses the instance's public DNS name from the EC2 instance metadata, and the certificate also names the public and private IP addresses. nginx answers only to the names in the certificate. The name is fixed at first boot, so if you stop and start the instance without an Elastic IP and its public address changes, run sudo davical-set-hostname with the new name (Step 7), or better, give the instance an Elastic IP or your own DNS name.

To check the sign in end to end from the instance itself (HTTPS redirect, an unknown host name refused, anonymous CalDAV refused, the admin password through both HTTP Basic authentication and the real sign in form, a wrong password refused, the session cookie flags, and an untouched re-save of the admin user's form keeping its password):

sudo davical-cred-roundtrip
OK https 301 + unknown Host refused + anonymous CalDAV refused + admin Basic and form sign-in + wrong/stock password refused + Secure HttpOnly cookie + principal form re-save kept the password

Step 5: Sign in and create your users

Open the DAVICAL_URL in your browser. The certificate is self signed, so your browser asks you to confirm it the first time (or install your own, Step 7). Sign in with the user name admin and the password from Step 4:

The DAViCal sign in page, Log On Please, with the User Name and Password fields, the GO! button and the forgotten password button

DAViCal opens on its Administration page. The web interface manages users, groups, collections and rights; calendars and contacts themselves are read and edited in your calendar and contacts apps (Step 6):

The DAViCal Administration page for the signed in admin, with the Home, User Functions, Administration and Help menu and an overview of principals, groups and grants

Create a user for each person. Choose User Functions, Create Principal. Enter a user name, the password twice, the full name and e-mail address, leave Principal Type as Person and leave Administrator unticked for everyone who does not manage the server, then choose Create:

The DAViCal Create New Principal form for the user alice, with the password fields, full name, e-mail address, locale, date format, principal type Person, Administrator unticked, Active ticked and the privileges granted to all users

DAViCal creates the new user's home collections at once: a calendar, an address book, and the scheduling inbox and outbox:

The Principal Collections table for alice, with /alice/.in/, /alice/.out/, /alice/addresses/ and /alice/calendar/

User Functions, List Users shows every user. A new instance has only admin; this one also has the user just created:

The DAViCal User Calendar Principals list with admin, DAViCal Administrator, and alice, Alice Example

Groups (Create Principal with Principal Type set to Group) let you grant a set of people rights to a collection in one step, and resources are principals for rooms and equipment that people book. The Administration menu's Setup, Upgrade Database and Tools entries open DAViCal's setup and maintenance scripts, which this image refuses from the web (they return Not Found, Step 10); new DAViCal releases arrive as new versions of this listing instead.

Keep admin for administration. Give each person their own user, and do not use admin for your own calendar. The Help! I've forgotten my password button only works once you have configured outgoing mail for PHP; until then, an administrator sets a new password on the user's page. If you lose the admin password, set a new one from the instance. Without an option it generates a random password and writes it to the credentials file; with --stdin it reads the password you type (24 to 72 letters and digits). Either way it signs every admin session out:

sudo davical-set-admin-password
sudo davical-set-admin-password --stdin

To change the address shown on the sign in page for access requests, set $c->admin_email in /etc/davical/config.php and restart PHP-FPM; to change the admin user's own e-mail address, edit it on its page.

Step 6: Connect your calendar and contacts apps

Every app needs the server address, the user name and the user's password:

App What to enter
Thunderbird New Calendar, On the Network, location https://<your-host>/caldav.php/<user>/calendar/; for contacts, New CardDAV Address Book with https://<your-host>/caldav.php/<user>/addresses/
Apple Calendar and Contacts (macOS, iOS) Add a CalDAV (and a CardDAV) account, Manual, server <your-host>; the app finds the collections through /.well-known/caldav and /.well-known/carddav
DAVx5 (Android) Login with URL and user name, base URL https://<your-host>/caldav.php/
Evolution, GNOME Calendar CalDAV calendar, URL https://<your-host>/caldav.php/<user>/calendar/

Phones and laptops reject a self signed certificate unless you trust it on the device, so set up your own DNS name and a trusted certificate (Step 7) before you roll DAViCal out.

To check CalDAV and CardDAV from the instance itself, this creates a calendar with a repeating event, finds the event's third day with a time range query, creates an address book with a contact, shows that a request without a password is refused, and removes the test collections again. The admin password is read from the credentials file into a file only you can read, so it never appears on a command line:

H=$(sudo awk -F/ '/^DAVICAL_URL=/{print $3}' /root/davical-credentials.txt)
( umask 077; sudo awk -F= -v h="$H" '/^DAVICAL_ADMIN_PASSWORD=/{print "machine " h " login admin password " $2}' /root/davical-credentials.txt > ~/.davical-netrc )
DAV=(curl -sk --resolve "$H:443:127.0.0.1" --netrc-file ~/.davical-netrc)
B="https://$H/caldav.php/admin"
"${DAV[@]}" -o /dev/null -w 'new calendar: %{http_code}\n' -X MKCALENDAR -H 'Content-Type: application/xml' \
  --data-binary '<C:mkcalendar xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav"><D:set><D:prop><D:displayname>Team</D:displayname></D:prop></D:set></C:mkcalendar>' "$B/team/"
printf 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//example//guide//EN\r\nBEGIN:VEVENT\r\nUID:standup-1@example.com\r\nDTSTAMP:20261108T090000Z\r\nDTSTART:20261109T090000Z\r\nDTEND:20261109T091500Z\r\nRRULE:FREQ=DAILY;COUNT=5\r\nSUMMARY:Daily stand-up\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n' \
  | "${DAV[@]}" -o /dev/null -w 'new event: %{http_code}\n' -X PUT -H 'Content-Type: text/calendar' --data-binary @- "$B/team/standup.ics"
"${DAV[@]}" -X REPORT -H 'Depth: 1' -H 'Content-Type: application/xml' \
  --data-binary '<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav"><D:prop><C:calendar-data/></D:prop><C:filter><C:comp-filter name="VCALENDAR"><C:comp-filter name="VEVENT"><C:time-range start="20261111T000000Z" end="20261112T000000Z"/></C:comp-filter></C:comp-filter></C:filter></C:calendar-query>' \
  "$B/team/" | grep -oE 'SUMMARY:[^&<]*'
"${DAV[@]}" -o /dev/null -w 'new address book: %{http_code}\n' -X MKCOL -H 'Content-Type: application/xml' \
  --data-binary '<D:mkcol xmlns:D="DAV:" xmlns:A="urn:ietf:params:xml:ns:carddav"><D:set><D:prop><D:resourcetype><D:collection/><A:addressbook/></D:resourcetype><D:displayname>Contacts</D:displayname></D:prop></D:set></D:mkcol>' "$B/contacts/"
printf 'BEGIN:VCARD\r\nVERSION:3.0\r\nUID:ada@example.com\r\nFN:Ada Lovelace\r\nN:Lovelace;Ada;;;\r\nEMAIL:ada@example.com\r\nEND:VCARD\r\n' \
  | "${DAV[@]}" -o /dev/null -w 'new contact: %{http_code}\n' -X PUT -H 'Content-Type: text/vcard' --data-binary @- "$B/contacts/ada.vcf"
"${DAV[@]}" "$B/contacts/ada.vcf" | grep -E '^FN' | tr -d '\r'
curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w 'anonymous read: %{http_code}\n' "$B/team/standup.ics"
"${DAV[@]}" -o /dev/null -w 'remove calendar: %{http_code}\n' -X DELETE "$B/team/"
"${DAV[@]}" -o /dev/null -w 'remove address book: %{http_code}\n' -X DELETE "$B/contacts/"
rm -f ~/.davical-netrc
new calendar: 201
new event: 201
SUMMARY:Daily stand-up
new address book: 201
new contact: 201
FN:Ada Lovelace
anonymous read: 401
remove calendar: 204
remove address book: 204

Step 7: Your own DNS name and certificate

Point a DNS record at the instance (an Elastic IP keeps the address stable), then set the name DAViCal is served as. This mints a new self signed certificate for the name, points nginx and DAViCal at it, updates the URLs in /root/davical-credentials.txt, and keeps the name across reboots:

sudo davical-set-hostname <your-domain>

To use a certificate from a public or internal certificate authority instead (for example one issued by Let's Encrypt for <your-domain>), copy it over the generated pair and reload nginx (running davical-set-hostname again replaces it with a self signed one):

sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/davical.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/davical.key
sudo nginx -t && sudo systemctl reload nginx

Step 8: What DAViCal can connect to

DAViCal itself rarely connects out, but a server that fetches what users name is a way into a network, so the image limits it. DAViCal's PHP processes run as the davical user, and davical-egress-guard.service loads an nftables table for that user at every boot. It lets DAViCal reach public IPv4 addresses and DNS through the local resolver, and refuses the metadata service, loopback, private, shared and reserved IPv4 ranges, the IPv4 blocks of the instance's own VPC (read at every boot) and all IPv6:

sudo nft list table inet cloudimg_davical_egress | grep -oE 'comment "cloudimg-[a-z0-9]+"' | uniq
comment "cloudimg-loopback"
comment "cloudimg-metadata"
comment "cloudimg-metadata6"
comment "cloudimg-multicast"
comment "cloudimg-allow"
comment "cloudimg-allow6"
comment "cloudimg-private"
comment "cloudimg-vpc"
comment "cloudimg-ipv6"

To let DAViCal reach an internal address, list it in /etc/cloudimg/davical-egress-allow (one private IPv4 or IPv6 CIDR per line; metadata, link-local, loopback and multicast ranges cannot be listed) and reload the table:

echo '10.0.5.25/32' | sudo tee -a /etc/cloudimg/davical-egress-allow
sudo systemctl reload davical-egress-guard

The table limits only the davical user. If you want to limit what the whole instance connects to, use its security group or a network ACL as well.

Step 9: Outgoing mail

No mail server ships. DAViCal sends e-mail only for the forgotten password button (server side scheduling, $c->enable_scheduling, is off on this image). To use it, install a minimal sendmail replacement such as msmtp-mta, configure it for your relay in /etc/msmtprc (for Amazon SES: email-smtp.<region>.amazonaws.com, port 587, tls on, and your SES SMTP credentials), make that file root:davical mode 0640 so only DAViCal can read the credentials, and restart PHP-FPM. A relay at a private address (inside your VPC or on premises) must be added to DAViCal's outbound allow-list first (Step 8).

Step 10: Security checks

nginx serves only DAViCal. Plain HTTP redirects to HTTPS, a request for a name the instance does not serve gets no answer at all, and the setup and maintenance pages are refused however the request is written:

H=$(sudo awk -F/ '/^DAVICAL_URL=/{print $3}' /root/davical-credentials.txt)
for p in / /index.php /caldav.php/ /setup.php /tools.php /upgrade.php /metrics.php /.git/config; do
  curl -sk -o /dev/null -w "%{http_code}  $p\n" --resolve "$H:443:127.0.0.1" "https://$H$p"
done
for p in /./setup.php /caldav.php/../setup.php /%73etup.php /SETUP.PHP; do
  curl -sk --path-as-is -o /dev/null -w "%{http_code}  $p (sent as is)\n" --resolve "$H:443:127.0.0.1" "https://$H$p"
done
curl -s -o /dev/null -w 'http:// -> %{http_code}\n' --resolve "$H:80:127.0.0.1" "http://$H/"
curl -sk -o /dev/null -w 'unknown host name -> %{http_code}\n' --resolve "other.example:443:127.0.0.1" "https://other.example/" || true
200  /
200  /index.php
401  /caldav.php/
404  /setup.php
404  /tools.php
404  /upgrade.php
404  /metrics.php
404  /.git/config
400  /./setup.php (sent as is)
400  /caldav.php/../setup.php (sent as is)
404  /%73etup.php (sent as is)
404  /SETUP.PHP (sent as is)
http:// -> 301
unknown host name -> 000

Passwords are stored only as salted hashes. This shows the form of each stored password (never the password or the hash):

sudo -u postgres psql -d davical -At -c "SELECT username || ': ' || CASE WHEN password ~ '^\*[^*]*\*\{SSHA\}' THEN 'salted SSHA hash' WHEN password LIKE '**%' THEN 'PLAIN TEXT' ELSE 'other' END FROM usr ORDER BY user_no"
admin: salted SSHA hash

Each user you create in the web interface is listed too, also as salted SSHA hash.

DAViCal's database roles have no password; PostgreSQL accepts them only over the local socket by peer authentication, and PostgreSQL does not listen on the network:

sudo -u postgres psql -At -c "SELECT rolname || ' password set: ' || CASE WHEN rolpassword IS NULL THEN 'no' ELSE 'yes' END FROM pg_authid WHERE rolname LIKE 'davical%' ORDER BY 1" -c 'SHOW listen_addresses' -c 'SHOW ssl'
davical_app password set: no
davical_dba password set: no

off

The certificate was generated on this instance and names its own addresses:

H=$(sudo awk -F/ '/^DAVICAL_URL=/{print $3}' /root/davical-credentials.txt)
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
subject=CN = ec2-<public-ip-dashed>.compute-1.amazonaws.com, O = cloudimg
X509v3 Subject Alternative Name:
    DNS:ec2-<public-ip-dashed>.compute-1.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost

None of the services can reach the instance metadata service (systemd prints the addresses in any order, so they are sorted here):

for u in nginx php8.3-fpm postgresql@16-main davical-egress-guard davical-firstboot; do
  echo "$u: $(systemctl show -p IPAddressDeny --value $u | tr ' ' '\n' | sort | paste -sd ' ')"
done
nginx: 168.63.129.16/32 169.254.169.254/32 192.0.0.0/24 198.18.0.0/15 224.0.0.0/4 240.0.0.0/4 fd00:ec2::254/128
php8.3-fpm: 168.63.129.16/32 169.254.169.254/32 192.0.0.0/24 198.18.0.0/15 224.0.0.0/4 240.0.0.0/4 fd00:ec2::254/128
postgresql@16-main: 168.63.129.16/32 169.254.169.254/32 192.0.0.0/24 198.18.0.0/15 224.0.0.0/4 240.0.0.0/4 fd00:ec2::254/128
davical-egress-guard: 168.63.129.16/32 169.254.169.254/32 192.0.0.0/24 198.18.0.0/15 224.0.0.0/4 240.0.0.0/4 fd00:ec2::254/128
davical-firstboot: 168.63.129.16/32 169.254.169.254/32 192.0.0.0/24 198.18.0.0/15 224.0.0.0/4 240.0.0.0/4 fd00:ec2::254/128

And the davical user is refused the metadata service and internal addresses by the outbound table as well:

sudo -u davical curl -s -m 5 -o /dev/null -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 60' http://169.254.169.254/latest/api/token && echo "davical -> metadata: REACHABLE" || echo "davical -> metadata: refused"
sudo -u davical curl -s -m 5 -o /dev/null http://10.0.0.1/ && echo "davical -> 10.0.0.1: REACHABLE" || echo "davical -> 10.0.0.1: refused"
davical -> metadata: refused
davical -> 10.0.0.1: refused

Step 11: Backup, storage and maintenance

Every calendar, event, task, address book and contact is in the PostgreSQL database davical (/var/lib/postgresql/16/main), and the settings are in /etc/davical/config.php. Both are on the root volume, so the simplest backup is an EBS snapshot of it. For a consistent copy while DAViCal is running:

umask 077
sudo -u postgres pg_dump -Fc davical > <backup-dir>/davical-$(date +%F).dump
sudo tar -C / -czf <backup-dir>/davical-config-$(date +%F).tar.gz etc/davical

The dump holds every user's password hash, calendar and contact, so store it as carefully as the instance. Users can also export a single calendar from their calendar app, or download it as an iCalendar file with a GET of the calendar's URL.

To give the database more room, enlarge the root volume in the EC2 console (Volumes, Modify); Ubuntu grows the file system on the next boot. Contact support if you would like help moving the database to its own EBS volume.

New DAViCal releases arrive as new versions of this listing, and support can help you move your data to one. Operating system security updates install automatically; run sudo apt-get update && sudo apt-get upgrade to apply everything else. nginx, PHP-FPM and PostgreSQL restart cleanly and DAViCal keeps all of its data.

Component Path
DAViCal /usr/share/davical (owned by root; PHP runs as the davical user)
AWL library /usr/share/awl
Settings /etc/davical/config.php (root:davical, mode 0640)
Database PostgreSQL 16 database davical (/var/lib/postgresql/16/main)
nginx site /etc/nginx/sites-available/cloudimg-davical
Request limits /etc/nginx/conf.d/cloudimg-davical.conf
Certificate and key /etc/nginx/ssl/davical.crt, /etc/nginx/ssl/davical.key
Services nginx.service, php8.3-fpm.service, postgresql@16-main.service, davical-egress-guard.service
Outbound allow-list /etc/cloudimg/davical-egress-allow
Helpers /usr/local/sbin/davical-set-admin-password, davical-set-hostname, davical-cred-roundtrip
Logs /var/log/nginx/, /var/log/php8.3-fpm.log, /var/log/postgresql/
Credentials /root/davical-credentials.txt (mode 0600)
Source /usr/share/doc/cloudimg-davical/SOURCE.txt

Step 12: Security recommendations

  • Allow port 22 from your admin network only, and ports 80 and 443 only from the networks your users and their devices work from.
  • Use your own DNS name and a certificate your users' devices trust (Step 7).
  • Give each person their own user, share calendars through groups and grants rather than shared passwords, and keep admin for administration with a password only you hold (Step 5).
  • Keep DAViCal's outbound allow-list empty unless it has to reach an internal address (Step 8).
  • Keep the operating system patched, and snapshot the root volume regularly.

Support and licensing

DAViCal is open source under the GNU General Public License, version 2 or (at your option) any later version; some of its files carry GPL-2.0-only, GPL-3.0-or-later or LGPL-3.0-or-later headers. Its AWL library is under the GNU GPL and LGPL. There is no per user licence fee. The image ships DAViCal and AWL exactly as released; the installed PHP files are their complete source, and /usr/share/doc/cloudimg-davical/SOURCE.txt names the releases, their download addresses and sha512 checksums, next to the licence texts. The AMI price covers cloudimg's hardening, first boot setup and support.

  • Email: support@cloudimg.co.uk
  • Website: https://www.cloudimg.co.uk
  • Support: 24/7, with a 24 hour response SLA

All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them. DAViCal is a project of its own contributors; cloudimg is not affiliated with it.