rss logo

Setting Up a Shared Calendar on Debian Linux with Baïkal

Baikal Logo Debian Logo Calendar icon representing a shared calendar system

I have been a long-time user of the Zimbra collaborative software, appreciating its web interface with email access and shared calendar features. Initially, there was a free and open-source version that served its purpose well, even if it became somewhat challenging to use and to update, it remained overall a good solution. However, with recent developments (since version 8.5) and various changes in ownership, the free edition has been completely abandoned. I therefore found myself looking for alternative solutions for the various modules (calendar, webmail, etc.).

This article will focus on setting up a shared calendar server. I'll show how to set up a shared calendar on GNU/Linux using the Baïkal server, which supports both CalDAV and CardDAV. Its web interface makes it easy to manage users, address books, and calendars.

The sqlite3 database is the perfect choice for a small number of users.

And a big thank you to ByteHamster for making this product free and Open Source.

Diagram showing the general architecture of the Baïkal shared calendar on Debian, with local and remote Thunderbird clients and DAVx⁵ smartphone synchronization through the internet.
General architecture of the Baïkal shared calendar environment, illustrating the Debian server, LAN clients, remote Thunderbird users, and smartphone synchronization via DAVx⁵.

Baïkal Installation

Prerequisites

  • Install prerequisites:
root@host:~# apt update && apt install apache2 php-sqlite3 git sqlite3 unzip php php-xml libapache2-mod-php
root@host:~# wget https://github.com/sabre-io/Baikal/releases/download/0.11.1/baikal-0.11.1.zip
  • Unzip and move the folder to /var/www/baikal/:
root@host:~# unzip baikal-0.11.1.zip
root@host:~# mv baikal /var/www/baikal
  • Set www-data as the owner of the folder:
root@host:~# chown -R www-data:www-data /var/www/baikal/

Certificates

To enable HTTPS on your Baïkal server, you need TLS certificates. You can choose between generating self-signed certificates or using Let’s Encrypt certificates.

Self-signed certificates are easy to generate, but they are not trusted by default by external devices and applications. As a result, clients will display security warnings when connecting to your server.

Let’s Encrypt provides free, publicly trusted TLS certificates. Certificates issued by Let’s Encrypt are recognized automatically by operating systems, browsers, and CalDAV/CardDAV clients, which prevents security warnings.

In this guide, both methods are presented so you can choose the solution that best fits your environment.

Self signed certificates

  • First, create the /etc/apache2/ssl/ directory, which will be used to store the TLS certificates and private keys:
root@host:~# mkdir /etc/apache2/ssl/
  • Generate the self-signed TLS certificate using openssl:
root@host:~# openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -keyout /etc/apache2/ssl/selfsigned.key -out /etc/apache2/ssl/selfsigned.crt
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:The Elements Of A State
Locality Name (eg, city) []:City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:STD Corp
Organizational Unit Name (eg, section) []:STD Department
Common Name (e.g. server FQDN or YOUR name) []:baikal.std.rocks
Email Address []:baikal@std.rocks
  • Create the cert.pem file by concatenating the private key and the certificate:
root@host:~# cat /etc/apache2/ssl/selfsigned.key /etc/apache2/ssl/selfsigned.crt > /etc/apache2/ssl/cert.pem
  • Edit the Apache VirtualHost configuration file /etc/apache2/sites-available/000-default.conf:
<VirtualHost *:443>

    DocumentRoot /var/www/baikal/html
    ServerName baikal.std.rocks

    RewriteEngine On
    # Generally already set by global Apache configuration
    #RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    RewriteRule /.well-known/carddav /dav.php [R=308,L]
    RewriteRule /.well-known/caldav  /dav.php [R=308,L]

    <Directory "/var/www/baikal/html">
        Options None
        # If you install cloning git repository, you may need the following
        Options +FollowSymlinks
        AllowOverride None
        # Configuration for apache-2.4:
        Require all granted
        # Configuration for apache-2.2:
        # Order allow,deny
        # Allow from all
    </Directory>

    <IfModule mod_expires.c>
        ExpiresActive Off
    </IfModule>

    SSLEngine On

    #SECURE SSL
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
    SSLHonorCipherOrder On

    #AUTOGENERATE CERTIFICATES
    SSLCertificateFile    /etc/apache2/ssl/cert.pem
    SSLCertificateKeyFile /etc/apache2/ssl/selfsigned.key

    #LETS ENCRYPT CERTIFICATES
    #SSLCertificateFile /etc/letsencrypt/live/baikal.std.rocks/fullchain.pem
    #SSLCertificateKeyFile /etc/letsencrypt/live/baikal.std.rocks/privkey.pem
</VirtualHost>

Let's encrypt certificates

  • First, stop the Apache service to allow Certbot to listen on the HTTP port during the certificate validation process:
root@host:~# systemctl stop apache2.service
  • Install the certbot package:
root@debian:~# apt update && sudo apt install certbot
  • Use certbot to request a Let’s Encrypt SSL/TLS certificate. Replace baikal.std.rocks with your own domain name and letsencrypt@std.rocks with your administrative email address:
root@debian:~# certbot certonly --standalone -d baikal.std.rocks --email letsencrypt@std.rocks --agree-tos --noninteractive
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for mail.std.rocks

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/baikal.std.rocks/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/baikal.std.rocks/privkey.pem
This certificate expires on 2026-04-23.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

💡 Note: Keep track of your certificate’s expiration date. Certbot automatically sets up renewal, but you can also configure a cron job or systemd timer to ensure the process runs smoothly.

  • Edit the Apache VirtualHost configuration file /etc/apache2/sites-available/000-default.conf:
<VirtualHost *:443>

    DocumentRoot /var/www/baikal/html
    ServerName baikal.std.rocks

    RewriteEngine On
    # Generally already set by global Apache configuration
    #RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    RewriteRule /.well-known/carddav /dav.php [R=308,L]
    RewriteRule /.well-known/caldav  /dav.php [R=308,L]

    <Directory "/var/www/baikal/html">
        Options None
        # If you install cloning git repository, you may need the following
        Options +FollowSymlinks
        AllowOverride None
        # Configuration for apache-2.4:
        Require all granted
        # Configuration for apache-2.2:
        # Order allow,deny
        # Allow from all
    </Directory>

    <IfModule mod_expires.c>
        ExpiresActive Off
    </IfModule>

    SSLEngine On

    #SECURE SSL
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
    SSLHonorCipherOrder On

    #AUTOGENERATE CERTIFICATES
    #SSLCertificateFile    /etc/apache2/ssl/cert.pem
    #SSLCertificateKeyFile /etc/apache2/ssl/selfsigned.key

    #LETS ENCRYPT CERTIFICATES
    SSLCertificateFile /etc/letsencrypt/live/baikal.std.rocks/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/baikal.std.rocks/privkey.pem
</VirtualHost>

Finalize configuration

Once your self-signed or Let’s Encrypt certificate has been generated, you can continue with the installation of Baïkal.

  • Enable the required Apache modules for URL rewriting and SSL support:
root@host:~# a2enmod rewrite
root@host:~# a2enmod ssl
  • Restart the Apache service to apply the configuration changes:
root@host:~# systemctl restart apache2

You can now proceed with the Baïkal configuration.

Baïkal Configuration

  • Open a web browser and connect to the Baïkal web interface (https://IP_SERVER) to set the admin password:
Baïkal installation wizard showing the initial configuration screen with admin password fields and the Save changes button
Baïkal installation wizard displaying the initial configuration settings, including the administrator password setup.
  • Keep the default database configuration (SQLite) and click Save changes to continue:
Baïkal database setup screen showing SQLite selected as the database backend
Baïkal database configuration screen with SQLite selected as the backend.
  • Finally, click on Start using Baïkal:
Baïkal installation wizard completion screen confirming that the database is configured and ready for use
Final screen of the Baïkal installation wizard confirming that the database has been configured successfully.
  • Use the previously configured password and click Authenticate:
Baïkal web administration authentication screen showing the login and password fields with the Authenticate button
Authentication screen of the Baïkal web administration interface, used to access the dashboard.
  • To add users, click Users and Resources from the dashboard:
Baïkal web administration dashboard showing system information, services status, and access to users and resources
Baïkal web administration dashboard providing an overview of the system status and access to users and resources management.
  • Then, click the Add User button:
Baïkal user management page showing the Users section with access to add new user accounts
User management section of the Baïkal web administration interface, used to manage accounts and related resources.
  • Enter information for the new account and click Save changes:
Baïkal user creation form showing username, display name, email, password fields, and the Save changes button
User creation form in the Baïkal web administration interface, used to add a new user account.
  • The user is now created. Click on the Calendars button:
Baïkal user management screen showing a created user with access to calendars and address books settings
User management screen in the Baïkal web administration interface, allowing access to calendars and address books for a specific user.
  • From here, you can add a calendar and obtain the URI information (which can be useful depending on the calendar client):
Baïkal calendar management screen showing the default calendar and the CalDAV URI information for a user
Calendar management screen in the Baïkal web administration interface, displaying the CalDAV URI required to configure calendar clients.

Calendar Clients Configuration

At this point, we have a working shared calendar server. Now, let's connect our clients. I'll demonstrate how to do it with Thunderbird, which has an integrated calendar, and the DAVx5 Android application, allowing synchronization with calendars on Android devices.

Thunderbird

  • Open Thunderbird and click the calendar button, then select New Calendar…:
Mozilla Thunderbird calendar main interface showing the calendar view and the option to add a new calendar
Thunderbird calendar main interface, used to manage calendars and start the process of adding a new network calendar.
  • Select On the Network and click the Next button:
Thunderbird create new calendar dialog showing the option to add a calendar on the network
Creating a new network calendar in Mozilla Thunderbird as the first step to connect to a CalDAV server.
  • Add the Username login and the URL https://IP_SERVER, then click Find Calendars:
Thunderbird network calendar setup showing the username field and the CalDAV server URL location before clicking Find Calendars
Entering the username and CalDAV server URL in Thunderbird to discover available calendars on the Baïkal server.
  • If you used a self-signed certificate, confirm the security exception:
Thunderbird security warning dialog prompting to add a certificate exception for an untrusted CalDAV server
Security warning in Thunderbird when connecting to a CalDAV server using a self-signed certificate, requiring a certificate exception.
  • Enter the password of the user previously created:
Thunderbird authentication dialog requesting the user password when connecting to a CalDAV calendar server
Entering the user password in Thunderbird to authenticate against the Baïkal CalDAV server.
  • Finally, click on Subscribe to add the calendar:
Thunderbird calendar subscription dialog showing the selected calendar and the Subscribe button
Final step in Thunderbird to subscribe to a CalDAV calendar by selecting the calendar and confirming the subscription.
  • The shared calendar will appear:
Mozilla Thunderbird calendar view showing the subscribed CalDAV calendar listed in the left pane
Thunderbird calendar view after subscribing to the Baïkal CalDAV calendar, with the shared calendar now visible in the calendar list.

DAVx5

  • Open the DAVx5 app and click on the plus symbol to add an account:
DAVx5 main interface on Android showing the add account button to configure a CalDAV connection
Main screen of the DAVx5 Android application, used to start adding a CalDAV account for calendar synchronization.
  • Select Connect with URL and enter the requested information:
DAVx5 add account screen showing the option to connect using a URL and username for a CalDAV server
Adding a CalDAV account in DAVx5 by entering the server URL, username, and password on an Android device.
  • As with Thunderbird, we will receive a warning about the certificate if it is self-signed. Just click Accept:
DAVx5 security warning screen displaying the details of a self-signed SSL certificate and prompting the user to accept it
Certificate validation screen in DAVx5 when connecting to a CalDAV server using a self-signed SSL certificate.
  • Finally, click on Create:
DAVx5 account creation screen on Android showing the create account button to finish adding a CalDAV account
Final step in DAVx5 to create the CalDAV account on Android and enable calendar synchronization with the Baïkal server.

Upgrading Baïkal

Baïkal is a maintained software, so new versions become available as time goes by. Here, I'll explain how to update Baïkal while preserving user data. The first step, as usual for this kind of operation, will be to make a full backup of your system.

  • Stop the apache2 service:
root@host:~# systemctl stop apache2
  • Backup the sqlite3 database:
root@host:~# sqlite3 /var/www/baikal/Specific/db/db.sqlite ".backup 'backup.db.sqlite'"
  • Backup the baikal folder:
root@host:~# cp -a /var/www/baikal /var/www/$(date +%Y%m%d).baikal
root@host:~# cd /tmp/
root@host:~# wget https://github.com/sabre-io/Baikal/releases/download/0.11.1/baikal-0.11.1.zip
root@host:~# unzip baikal-0.11.1.zip
  • Copy the current config and Specific folders to /tmp/baikal:
root@host:~# cp -ra /var/www/baikal/config /tmp/baikal/
root@host:~# cp -ra /var/www/baikal/Specific /tmp/baikal/
  • Disable old baikal folder:
root@host:~# cd /var/www/
root@host:~# mv baikal baikal.OLD
  • Move the new version of baikal to /var/www/:
root@host:~# mv /tmp/baikal /var/www/
  • Restore www-data rights:
root@host:~# chown -R www-data:www-data /var/www/baikal/
  • Start apache service:
root@host:~# systemctl start apache2
  • Open the baikal web administration page (e.g. https://baikal.std.rocks/admin/install/) and click on Start the upgrade:
Baïkal upgrade wizard showing the upgrade process from an older version to a newer one, with start upgrade and access admin actions
Baïkal upgrade wizard illustrating the start and completion of the upgrade process between two software versions.