User Tools

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
services:radicale [2024/02/22 08:54] – created willyservices:radicale [2025/09/16 13:10] (current) – [WEB GUI to Radicale] willy
Line 1: Line 1:
 ====== Radicale ====== ====== Radicale ======
  
-[[https://radicale.org/v3.html|Radicale]] is a CalDAV/CardDAV server.+[[https://radicale.org/v3.html|Radicale]] is a CalDAV/CardDAV server. It can be used to store your contacts and calendars, and i will show you how to install also [[https://github.com/ckulka/infcloud-docker|InfCloud]] as a WEB GUI to it.
  
 [[https://en.wikipedia.org/wiki/Web-based_Distributed_Authoring_and_Versioning|CalDAV]] is the WebDAV extension to manage Calendars [[https://en.wikipedia.org/wiki/Web-based_Distributed_Authoring_and_Versioning|CalDAV]] is the WebDAV extension to manage Calendars
Line 9: Line 9:
 To add support for both, which will allow your phone to sync contacts and calendars with your home server, i choose to use the great, simple and effective [[https://radicale.org/v3.html|Radicale]] server.  To add support for both, which will allow your phone to sync contacts and calendars with your home server, i choose to use the great, simple and effective [[https://radicale.org/v3.html|Radicale]] server. 
  
-Please note that Radicale do not provide a user-interface to **edit** or **use** calendars or contacts, you need third party apps for that.+Please note that Radicale do not provide a user-interface to **edit** or **use** calendars or contacts, you need third party apps for that, and the one i am currently using is [[https://github.com/ckulka/infcloud-docker|InfCloud]], see installation instructions at the bottom of this page.
  
 To install radicale, of course, you need it's dedicated user, so add user: To install radicale, of course, you need it's dedicated user, so add user:
Line 22: Line 22:
 </code> </code>
  
-Radicale uses //pip//, so as usual enable it on Gentoo for user Radicale by creating the file **/data/daemons/deemon/.config/pip/pip.conf** with this content: +Radicale uses //pip//, so as usual enable it on Gentoo for user Radicale by creating the file **/data/daemons/radicale/.config/pip/pip.conf** with this content: 
-<file pip.conf>+<file pip.conf>
 [global] [global]
 break-system-packages = true break-system-packages = true
Line 37: Line 37:
 Create the config file **~/.config/radicale/config**: Create the config file **~/.config/radicale/config**:
 <file - config> <file - config>
 +[server]
 # Bind all addresses # Bind all addresses
 hosts = 127.0.0.1:5232 hosts = 127.0.0.1:5232
Line 47: Line 48:
 [storage] [storage]
 filesystem_folder = /data/cardcal filesystem_folder = /data/cardcal
-</code>+</file>
  
 then start it: then start it:
Line 56: Line 57:
  
 ==== Reverse Proxy ==== ==== Reverse Proxy ====
 +
 +Radicale can be hosted both on subdomain or subpath, but i choose subdomain to make it easier to also host InfCloud on the same subdomain.
  
 As usual you want it protected by the Reverse Proxy, so create the **radicale.conf** file: As usual you want it protected by the Reverse Proxy, so create the **radicale.conf** file:
 <file - radicale.conf> <file - radicale.conf>
-location /radicale/  +server { 
-# The trailing / is important! +        server_name radicale.mydomain.com; 
-    proxy_pass        http://localhost:5232/; # The / is important! +        listen 443 ssl; 
-    proxy_set_header  X-Script-Name /radicale+        listen 8443 ssl; 
-    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for; +        http2 on; 
-    proxy_set_header  Host $http_host; + 
-    proxy_pass_header Authorization; +        include "com.mydomain/authelia_location-basic.conf"; 
-    proxy_set_header     X-Remote-User $remote_user; # allow automatic authentication using proxy credentials + 
-    # to prevent timeouts importing huge calendars or contacts lists +        access_log /var/log/nginx/radicale.mydomain.com_access_log main; 
-    proxy_send_timeout 600+        error_log /var/log/nginx/radicale.mydomain.com_error_log info; 
-    proxy_read_timeout 600;+ 
 +        location / { # The trailing / is important! 
 +                proxy_pass        http://127.0.0.1:5232/; # The / is important! 
 +                proxy_set_header  X-Script-Name /; 
 +                proxy_set_header  X-Remote-User $remote_user; 
 +                proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for; 
 +                proxy_set_header  Host $http_host; 
 +                proxy_pass_header Authorization; 
 +                include "com.mydomain/authelia_proxy.conf"; 
 +                include "com.mydomain/authelia_authrequest-basic.conf"; 
 +        } 
 + 
 +        location /gui/ { # The trailing / is important! 
 +                proxy_pass        http://127.0.0.1:5233/; # The / is important! 
 +                proxy_set_header  X-Script-Name /; 
 +                proxy_set_header  X-Remote-User $remote_user; 
 +                proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for; 
 +                proxy_set_header  Host $http_host
 +                proxy_pass_header Authorization; 
 +        } 
 +        include com.mydomain/certbot.conf;
 } }
 </file> </file>
 add this config file to NGINX (see [[selfhost:nginx|The Reverse Proxy concept]] for more details) and restart nginx. add this config file to NGINX (see [[selfhost:nginx|The Reverse Proxy concept]] for more details) and restart nginx.
  
-Now go with browser to **http://10.0.0.1/radicale** to finish setup.+This set-up links also Radicale to your SSO (see [[selfhost:sso|this page]], which is a good approach, but please note that this will make access to the radicale web ui (not the WEB GUI InfCloud) a bit more awkward as the Radicale login window cannot be disabled, and the user will need double authentication.
  
-==== Autostart ====+Now go with browser to **https://radicale.mydomain.com** to finish setup.
  
-Autostart, put this into **/etc/local.d/50-radicale.start** and make it executable: +=== URLs summary ===
-<file - 50-radicale.start> +
-#!/bin/bash+
  
-start-stop-daemon -b -m -p /var/run/radicale.pid -n radicale -u radicale /data/daemons/radicale/.local/bin/radicale+The following URL's are exposed between Radicale and InfCloud: 
 +  * https://radicale.mydomain.com: server web access, will redirect to ".web" and let you create calendars 
 +  * https://radicale.mydomain.com/gui/: InfCloud, client GUI to actually edit and access your calendars and contacts 
 + 
 +And, last, when setting up your *DAV clients (like on Android or similar), use **https://radicale.mydomain.com** as server URL. 
 + 
 + 
 +===== Startup ===== 
 + 
 +Since i use OpenRC, to start radicale simply create the following script under /etc/init.d: 
 +<file /etc/init.d/radicale> 
 +#!/sbin/openrc-run 
 +# Copyright 1999-2021 Gentoo Authors 
 +# Distributed under the terms of the GNU General Public License v2 
 + 
 +description="Radicale WebDAV WebCAL server" 
 +pidfile="/run/radicale.pid
 +command_background=true 
 +command="/data/daemons/radicale/.local/bin/radicale
 +command_args="" 
 +command_user="radicale:users" 
 + 
 +depend() { 
 +        need net 
 +
 +</file> 
 + 
 +Make it executable and add the service to the default runlevel: 
 +<code bash> 
 +chmod +x /etc/init.d/radicale 
 +rc-update add radicale default
 </code> </code>
 +
 +==== Sharing calendars ====
 +
 +Radicale doesn't directly support sharing calendars (see [[https://github.com/Kozea/Radicale/issues/696|here]]) but it's pretty easy to share calendars between users anyway by creating simple symlinks.
 +
 +So, first of all login on Radicale web GUI with all the users you want to share the calendar with, then create in one of them the actual calendar.
 +
 +At this point, you only need to link the calendar folder inside all he users:
 +<code bash>
 +ln -s /data/cardcal/collection-root/user1/72757af3-557c-e8e4-bdd7-c9bc5689b862   /data/cardcal/collection-root/user2/
 +</code>
 +
 +and that's it.
 +
 +====== WEB GUI for Radicale ======
 +
 +[[https://inf-it.com/open-source/clients/infcloud/|InfCloud]] is a nice javascript WEB GUI for Radicale. It's a bit old-style, but solid and pretty usable. I strongly suggest to go the container way and use this [[https://github.com/ckulka/infcloud-docker|InfCloud docker]] solution here, which is pretty nice and easy to setup.
 +
 +First of all, to avoid cross-domain issues (CORS) which are hard to solve due to using SSO on Radicale itself, i will host InfCloud on the same radicale domain, using the **/gui/** subpath. 
 +
 +First of all, setup the docker-compose file **/data/daemons/radicale/docker-compose.yml**:
 +<file - docker-compose.yml>
 +version: "3"
 +
 +services:
 +  infcloud:
 +    image: ckulka/infcloud
 +    restart: always
 +    depends_on:
 +      - php
 +    ports:
 +      - "5233:80"
 +    volumes:
 +      - infcloud:/usr/share/nginx/infcloud
 +      - ./config.js:/usr/share/nginx/infcloud/config.js:ro
 +
 +  php:
 +    image: php:7.3-fpm-alpine
 +    restart: always
 +    volumes:
 +      - infcloud:/usr/share/nginx/infcloud:ro
 +
 +volumes:
 +  infcloud:
 +
 +</file>
 +
 +Now, create the **/data/daemons/radicale/config.js**:
 +<file - config.js>
 +var globalNetworkCheckSettings={
 +        href: "https://radicale.mydomain.com/",
 +        timeOut: 90000,
 +        lockTimeOut: 10000,
 +        checkContentType: true,
 +        settingsAccount: true,
 +        delegation: true,
 +        additionalResources: [],
 +        hrefLabel: null,
 +        forceReadOnly: null,
 +        ignoreAlarms: false,
 +        backgroundCalendars: []
 +};
 +var globalInterfaceLanguage='it_IT';
 +var globalSearchTransformAlphabet={
 +        '[ÀàÁáÂâÄ䯿ÃãÅåĀā]': 'a', '[ÇçĆćČč]': 'c', '[Ďď]': 'd',
 +        '[ÈèÉéÊêËëĒēĖėĘęĚě]': 'e', '[Ğğ]': 'g', '[ÌìÍíÎîİıÏïĪīĮį]': 'i',
 +        '[ŁłĹ弾]': 'l', '[ŃńÑñŇň]': 'n', '[ÒòÓóÔôÖöŐőŒœØøÕõŌō]': 'o',
 +        '[ŔŕŘř]': 'r', '[ŚśŠšȘșŞşẞß]': 's', '[ŤťȚțŢţ]': 't',
 +        '[ÙùÚúÛûÜüŰűŮůŪū]': 'u', '[ÝýŸÿ]': 'y', '[ŹźŻżŽž]': 'z'
 +};
 +var globalSortAlphabet=' 0123456789'+
 +        'AÀÁÂÄÆÃÅĀBCÇĆČDĎEÈÉÊËĒĖĘĚFGĞHIÌÍÎİÏĪĮJKLŁĹĽMNŃÑŇOÒÓÔÖŐŒØÕŌ'+
 +        'PQRŔŘSŚŠȘșŞşẞTŤȚțŢţUÙÚÛÜŰŮŪVWXYÝŸZŹŻŽ'+
 +        'aàáâäæãåābcçćčdďeèéêëēėęěfgğhiìíîïīįıjklłĺľmnńñňoòóôöőœøõō'+
 +        'pqrŕřsśšßtťuùúûüűůūvwxyýÿzźżžАБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЮЯ'+
 +        'Ьабвгґдеєжзиіїйклмнопрстуфхцчшщюяь';
 +var globalBackgroundSync=true;
 +var globalSyncResourcesInterval=120000;
 +var globalEnableRefresh=false;
 +var globalEnableKbNavigation=true;
 +var globalInterfaceCustomLanguages=[];
 +var globalResourceAlphabetSorting=true;
 +var globalNewVersionNotifyUsers=[];
 +var globalDatepickerFirstDayOfWeek=1;
 +var globalHideInfoMessageAfter=1800;
 +var globalEditorFadeAnimation=666;
 +var globalEventStartPastLimit=3;
 +var globalEventStartFutureLimit=3;
 +var globalTodoPastLimit=1;
 +var globalLoadedCalendarCollections=[];
 +var globalLoadedTodoCollections=[];
 +var globalActiveCalendarCollections=[];
 +var globalActiveTodoCollections=[];
 +var globalActiveView='multiWeek';
 +var globalOpenFormMode='double';
 +var globalTodoListFilterSelected=['filterAction', 'filterProgress'];
 +var globalCalendarStartOfBusiness=8;
 +var globalCalendarEndOfBusiness=17;
 +var globalDefaultEventDuration=120;
 +var globalDisplayHiddenEvents=false;
 +var globalTimeZoneSupport=true;
 +var globalTimeZone='Europe/Berlin';
 +var globalTimeZonesEnabled=[];
 +var globalRewriteTimezoneComponent=true;
 +var globalRemoveUnknownTimezone=false;
 +var globalShowHiddenAlarms=false;
 +var globalIgnoreCompletedOrCancelledAlarms=true;
 +var globalMozillaSupport=false;
 +var globalWeekendDays=[0, 6];
 +var globalAppleRemindersMode=true;
 +var globalLoadedAddressbookCollections=[];
 +var globalActiveAddressbookCollections=[];
 +var globalCompatibility={anniversaryOutputFormat: ['apple']};
 +var globalUriHandlerTel='tel:';
 +var globalUriHandlerEmail='mailto:';
 +var globalUriHandlerUrl='http://';
 +var globalUriHandlerProfile={
 +        'twitter': 'http://twitter.com/%u',
 +        'facebook': 'http://www.facebook.com/%u',
 +        'flickr': 'http://www.flickr.com/photos/%u',
 +        'linkedin': 'http://www.linkedin.com/in/%u',
 +        'myspace': 'http://www.myspace.com/%u',
 +        'sinaweibo': 'http://weibo.com/n/%u'
 +};
 +var globalDefaultAddressCountry='us';
 +var globalAddressCountryEquivalence=[
 +        {country: 'de', regex: '^\\W*Deutschland\\W*$'},
 +        {country: 'sk', regex: '^\\W*Slovensko\\W*$'}
 +];
 +var globalAddressCountryFavorites=[];
 +var globalContactStoreFN=['prefix',' last',' middle',' first',' suffix'];
 +var globalGroupContactsByCompanies=false;
 +var globalContactDataMinVisiblePercentage=0.95;
 +</file>
 +
 +Edit to your likings, more detail can be found [[https://github.com/ckulka/infcloud-docker/blob/master/examples/config.js|here]].
 +
 +Now create the startup config script **/etc/conf.d/user-containers.infCloud**:
 +<file - user-containers.infCloud>
 +USER=radicale
 +DESCRIPTION="WEB GUI for Radicale"
 +</file>
 +
 +Create the link and start it:
 +<code bash>
 +cd /etc/init.d/
 +ln -s user-containers user-containers.infCloud
 +rc-update add user-containers.infCloud default
 +./user-containers.infCloud start
 +</code>
 +
 +Now point your browser to **https://radicale.mydomain.com/gui/** to access infCloud.