Getting started ¶
+About Radicale ¶
+Radicale is a small but powerful CalDAV (calendars, to-do lists) and +CardDAV (contacts) server, that:
+-
+
- Shares calendars and contact lists through CalDAV, CardDAV and +HTTP. +
- Supports events, todos, journal entries and business cards. +
- Works out-of-the-box, no complicated setup or configuration +required. +
- Offers flexible authentication options. +
- Can limit access by authorization. +
- Can secure connections with TLS. +
- Works with many CalDAV and CardDAV +clients. +
- Stores all data on the file system in a simple folder +structure. +
- Can be extended with plugins. +
- Is GPLv3-licensed free software. +
Installation ¶
+Check
+ +What's New? ¶
+Read the Changelog +on GitHub.
+Tutorials ¶
+Simple 5-minute setup ¶
+You want to try Radicale but only have 5 minutes free in your +calendar? Let's go right now and play a bit with Radicale!
+The server, configured with settings from this section, only binds to +localhost (i.e. it is not reachable over the network), and you can log +in with any username and password. When everything works, you may get a +local client and start creating +calendars and address books. If Radicale fits your needs, it may be time +for some basic configuration to +support remote clients and desired authentication type.
+Follow one of the chapters below depending on your operating +system.
+Linux / *BSD ¶
+Hint: instead of downloading from PyPI, look for packages provided by +your distribution. They +contain also startup scripts integrated into your distributions, that +allow Radicale to run daemonized.
+First, make sure that python 3.9 or later and
+pip are installed. On most distributions it should be
+enough to install the package python3-pip
.
as normal user ¶
+Recommended only for testing - open a console and type:
+# Run the following command to only install for the current user
+python3 -m pip install --user --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
If install is not working and instead
+error: externally-managed-environment
is displayed, create
+and activate a virtual environment in advance.
python3 -m venv ~/venv
+source ~/venv/bin/activate
and try to install with
+python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
Start the service manually, data is stored only for the current +user
+# Start, data is stored for the current user only
+python3 -m radicale --storage-filesystem-folder=~/.var/lib/radicale/collections --auth-type none
as system user (or as root) ¶
+Alternatively, you can install and run as system user or as root (not +recommended):
+# Run the following command as root (not recommended) or non-root system user
+# (the later may require --user in case dependencies are not available system-wide and/or virtual environment)
+python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
Start the service manually, with data stored in a system folder under
+/var/lib/radicale/collections
:
# Start, data is stored in a system folder (requires write permissions to /var/lib/radicale/collections)
+python3 -m radicale --storage-filesystem-folder=/var/lib/radicale/collections --auth-type none
Windows ¶
+The first step is to install Python. Go to python.org and download the latest version +of Python 3. Then run the installer. On the first window of the +installer, check the "Add Python to PATH" box and click on "Install +now". Wait a couple of minutes, it's done!
+Launch a command prompt and type:
+-m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
+ python -m radicale --storage-filesystem-folder=~/radicale/collections --auth-type none python
Common ¶
+Success!!! Open http://localhost:5232 in your browser!
+You can log in with any username and password as no authentication is
+required by example option --auth-type none
. This is
+INSECURE, see Configuration/Authentication for more details.
Just note that default configuration for security reason binds the
+server to localhost
(IPv4: 127.0.0.1
, IPv6:
+::1
). See Addresses and Configuration/Server for more details.
Basic Configuration ¶
+Installation instructions can be found in the simple 5-minute setup tutorial.
+Radicale tries to load configuration files from
+/etc/radicale/config
and
+~/.config/radicale/config
. Custom paths can be specified
+with the --config /path/to/config
command line argument or
+the RADICALE_CONFIG
environment variable. Multiple
+configuration files can be separated by :
(resp.
+;
on Windows). Paths that start with ?
are
+optional.
You should create a new configuration file at the desired location. +(If the use of a configuration file is inconvenient, all options can be +passed via command line arguments.)
+All configuration options are described in detail in the Configuration section.
+Authentication ¶
+In its default configuration since version 3.5.0, Radicale rejects
+all authentication attempts by using config option
+type = denyall
(introduced with 3.2.2) as default until
+explicitly configured.
Versions before 3.5.0 did not check usernames or passwords at all, +unless explicitly configured. If such a server is reachable over a +network, you should change this as soon as possible.
+First a users
file with all usernames and passwords must
+be created. It can be stored in the same directory as the configuration
+file.
The secure way ¶
+The users
file can be created and managed with htpasswd:
Note: some OSes or distributions contain outdated versions of
+htpasswd
(< 2.4.59) without support for SHA-256 or
+SHA-512 (e.g. Ubuntu LTS 22). In these cases, use
+htpasswd
's command line option -B
for the
+bcrypt
hash method (recommended), or stay with the insecure
+(not recommended) MD5 (default) or SHA-1 (command line option
+-s
).
Note: support of SHA-256 and SHA-512 was introduced with 3.1.9
+# Create a new htpasswd file with the user "user1" using SHA-512 as hash method
+$ htpasswd -5 -c /path/to/users user1
+New password:
+Re-type new password:
+# Add another user
+$ htpasswd -5 /path/to/users user2
+New password:
+Re-type new password:
Authentication can be enabled with the following configuration:
+[auth]
+type = htpasswd
+htpasswd_filename = /path/to/users
+htpasswd_encryption = autodetect
The simple but insecure way ¶
+Create the users
file by hand with lines containing the
+username and password separated by :
. Example:
user1:password1
+user2:password2
+Authentication can be enabled with the following configuration:
+[auth]
+type = htpasswd
+htpasswd_filename = /path/to/users
+# encryption method used in the htpasswd file
+htpasswd_encryption = plain
Addresses ¶
+The default configuration binds the server to localhost. It cannot be +reached from other computers. This can be changed with the following +configuration options (IPv4 and IPv6):
+[server]
+hosts = 0.0.0.0:5232, [::]:5232
Storage ¶
+Data is stored in the folder
+/var/lib/radicale/collections
. The path can be changed with
+the following configuration:
[storage]
+filesystem_folder = /path/to/storage
++Security: The storage folder shall not be readable +by unauthorized users. Otherwise, they can read the calendar data and +lock the storage. You can find OS dependent instructions in the Running as a service section.
+
Limits ¶
+Radicale enforces limits on the maximum number of parallel +connections, the maximum file size (important for contacts with big +photos) and the rate of incorrect authentication attempts. Connections +are terminated after a timeout. The default values should be fine for +most scenarios.
+[server]
+max_connections = 20
+# 100 Megabyte
+max_content_length = 100000000
+# 30 seconds
+timeout = 30
+
+[auth]
+# Average delay after failed login attempts in seconds
+delay = 1
Running as a service ¶
+The method to run Radicale as a service depends on your host +operating system. Follow one of the chapters below depending on your +operating system and requirements.
+Linux with systemd system-wide ¶
+Recommendation: check support by Linux Distribution Packages +instead of manual setup / initial configuration.
+Create the radicale user and group for the Radicale
+service by running (as root
:
useradd --system --user-group --home-dir / --shell /sbin/nologin radicale
The storage folder must be made writable by the
+radicale user by running (as root
):
mkdir -p /var/lib/radicale/collections && chown -R radicale:radicale /var/lib/radicale/collections
If a dedicated cache folder is configured (see option filesystem_cache_folder), it also
+must be made writable by radicale. To achieve that, run
+(as root
):
mkdir -p /var/cache/radicale && chown -R radicale:radicale /var/cache/radicale
++Security: The storage shall not be readable by +others. To make sure this is the case, run (as
+root
):+chmod -R o= /var/lib/radicale/collections
Create the file
+/etc/systemd/system/radicale.service
:
[Unit]
+Description=A simple CalDAV (calendar) and CardDAV (contact) server
+After=network.target
+Requires=network.target
+
+[Service]
+ExecStart=/usr/bin/env python3 -m radicale
+Restart=on-failure
+User=radicale
+# Deny other users access to the calendar data
+UMask=0027
+# Optional security settings
+PrivateTmp=true
+ProtectSystem=strict
+ProtectHome=true
+PrivateDevices=true
+ProtectKernelTunables=true
+ProtectKernelModules=true
+ProtectControlGroups=true
+NoNewPrivileges=true
+ReadWritePaths=/var/lib/radicale/
+# Replace with following in case dedicated cache folder should be used
+#ReadWritePaths=/var/lib/radicale/ /var/cache/radicale/
+
+[Install]
+WantedBy=multi-user.target
In this system-wide implementation, Radicale will load the
+configuration from the file /etc/radicale/config
.
To enable and manage the service run:
+# Enable the service
+$ systemctl enable radicale
+# Start the service
+$ systemctl start radicale
+# Check the status of the service
+$ systemctl status radicale
+# View all log messages
+$ journalctl --unit radicale.service
Linux with systemd as a user ¶
+Create the file
+~/.config/systemd/user/radicale.service
:
[Unit]
+Description=A simple CalDAV (calendar) and CardDAV (contact) server
+
+[Service]
+ExecStart=/usr/bin/env python3 -m radicale
+Restart=on-failure
+
+[Install]
+WantedBy=default.target
In this user-specific configuration, Radicale will load the
+configuration from the file ~/.config/radicale/config
. You
+should set the configuration option filesystem_folder
in
+the storage
section to something like
+~/.var/lib/radicale/collections
.
To enable and manage the service run:
+# Enable the service
+$ systemctl --user enable radicale
+# Start the service
+$ systemctl --user start radicale
+# Check the status of the service
+$ systemctl --user status radicale
+# View all log messages
+$ journalctl --user --unit radicale.service
Windows with "NSSM - the Non-Sucking Service Manager" ¶
+First install NSSM and start
+nssm install
in a command prompt. Apply the following
+configuration:
-
+
- Service name:
Radicale
+ - Application
+
-
+
- Path:
C:\Path\To\Python\python.exe
+ - Arguments:
--config C:\Path\To\Config
+
+ - Path:
- I/O redirection
+
-
+
- Error:
C:\Path\To\Radicale.log
+
+ - Error:
++Security: Be aware that the service runs in the +local system account, you might want to change this. Managing user +accounts is beyond the scope of this manual. Also, make sure that the +storage folder and log file is not readable by unauthorized users.
+
The log file might grow very big over time, you can configure file +rotation in NSSM to prevent this.
+The service is configured to start automatically when the computer +starts. To start the service manually open Services in +Computer Management and start the +Radicale service.
+Reverse Proxy ¶
+When a reverse proxy is used, and Radicale should be made available
+at a path below the root (such as /radicale/
), then this
+path must be provided via the X-Script-Name
header (without
+a trailing /
). The proxy must remove the location from the
+URL path that is forwarded to Radicale. If Radicale should be made
+available at the root of the web server (in the nginx case using
+location /
), then the setting of the
+X-Script-Name
header should be removed from the example
+below.
Example nginx configuration extension:
+See also for latest examples: https://github.com/Kozea/Radicale/tree/master/contrib/nginx/
+location /radicale/ { # The trailing / is important!
+ proxy_pass http://localhost:5232;
+ proxy_set_header X-Script-Name /radicale;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Host $host;
+ proxy_set_header X-Forwarded-Port $server_port;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header Host $http_host;
+ proxy_pass_header Authorization;
+}
+Example Caddy configuration extension:
+See also for latest examples: https://github.com/Kozea/Radicale/tree/master/contrib/caddy/
+handle_path /radicale/* {
+ uri strip_prefix /radicale
+ reverse_proxy localhost:5232 {
+ }
+}
+Example Apache configuration extension:
+See also for latest examples: https://github.com/Kozea/Radicale/tree/master/contrib/apache/
+RewriteEngine On
+ ^/radicale$ /radicale/ [R,L]
+ RewriteRule
+<Location "/radicale/">
+ http://localhost:5232/ retry=0
+ ProxyPass http://localhost:5232/
+ ProxyPassReverse set X-Script-Name /radicale
+ RequestHeader set X-Forwarded-Port "%{SERVER_PORT}s"
+ RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
+ RequestHeader<IfVersion >= 2.4.40>
+
+ Proxy100Continue Off</IfVersion>
+ </Location>
Example Apache .htaccess configuration:
+ disabled
+ DirectoryIndexRewriteEngine On
+ ^(.*)$ http://localhost:5232/$1 [P,L]
+ RewriteRule
+# Set to directory of .htaccess file:
+ set X-Script-Name /radicale
+ RequestHeader set X-Forwarded-Port "%{SERVER_PORT}s"
+ RequestHeader unset X-Forwarded-Proto
+ RequestHeader<If "%{HTTPS} =~ /on/">
+ set X-Forwarded-Proto "https"
+ RequestHeader</If>
Example lighttpd configuration:
+server.modules += ( "mod_proxy" , "mod_setenv", "mod_rewrite" )
+
+$HTTP["url"] =~ "^/radicale/" {
+ proxy.server = ( "" => (( "host" => "127.0.0.1", "port" => "5232" )) )
+ proxy.header = ( "map-urlpath" => ( "/radicale/" => "/" ))
+
+ setenv.add-request-header = (
+ "X-Script-Name" => "/radicale",
+ "Script-Name" => "/radicale",
+ )
+ url.rewrite-once = ( "^/radicale/radicale/(.*)" => "/radicale/$1" )
+}
+Be reminded that Radicale's default configuration enforces limits on +the maximum number of parallel connections, the maximum file size and +the rate of incorrect authentication attempts. Connections are +terminated after a timeout.
+Manage user accounts with the reverse proxy ¶
+Set the configuration option type
in the
+auth
section to http_x_remote_user
. Radicale
+uses the username provided in the X-Remote-User
HTTP header
+and disables its internal HTTP authentication.
Example nginx configuration:
+location /radicale/ {
+ proxy_pass http://localhost:5232/;
+ proxy_set_header X-Script-Name /radicale;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Remote-User $remote_user;
+ proxy_set_header Host $http_host;
+ auth_basic "Radicale - Password Required";
+ auth_basic_user_file /etc/nginx/htpasswd;
+}
+Example Caddy configuration:
+handle_path /radicale/* {
+ uri strip_prefix /radicale
+ basicauth {
+ USER HASH
+ }
+ reverse_proxy localhost:5232 {
+ header_up X-Script-Name /radicale
+ header_up X-remote-user {http.auth.user.id}
+ }
+}
+Example Apache configuration:
+RewriteEngine On
+ ^/radicale$ /radicale/ [R,L]
+ RewriteRule
+<Location "/radicale/">
+AuthType Basic
+ "Radicale - Password Required"
+ AuthName "/etc/radicale/htpasswd"
+ AuthUserFile valid-user
+ Require
+ http://localhost:5232/ retry=0
+ ProxyPass http://localhost:5232/
+ ProxyPassReverse<IfVersion >= 2.4.40>
+
+ Proxy100Continue Off</IfVersion>
+ set X-Script-Name /radicale
+ RequestHeader set X-Remote-User expr=%{REMOTE_USER}
+ RequestHeader</Location>
Example Apache .htaccess configuration:
+ disabled
+ DirectoryIndexRewriteEngine On
+ ^(.*)$ http://localhost:5232/$1 [P,L]
+ RewriteRule
+AuthType Basic
+ "Radicale - Password Required"
+ AuthName "/etc/radicale/htpasswd"
+ AuthUserFile valid-user
+ Require
+# Set to directory of .htaccess file:
+ set X-Script-Name /radicale
+ RequestHeader set X-Remote-User expr=%{REMOTE_USER} RequestHeader
++Security: Untrusted clients should not be able to +access the Radicale server directly. Otherwise, they can authenticate as +any user by simply setting related HTTP header. This can be prevented by +listening to the loopback interface only or local firewall rules.
+
Secure connection between Radicale and the reverse proxy ¶
+SSL certificates can be used to encrypt and authenticate the +connection between Radicale and the reverse proxy. First you need to +generate a certificate for Radicale and a certificate for the reverse +proxy. The following commands generate self-signed certificates. You +will be asked to enter additional information about the certificate, +these values do not really matter, and you can keep the defaults.
+openssl req -x509 -newkey rsa:4096 -keyout server_key.pem -out server_cert.pem \
+-nodes -days 9999
+ openssl req -x509 -newkey rsa:4096 -keyout client_key.pem -out client_cert.pem \
+-nodes -days 9999
Use the following configuration for Radicale:
+[server]
+ssl = True
+certificate = /path/to/server_cert.pem
+key = /path/to/server_key.pem
+certificate_authority = /path/to/client_cert.pem
If you are using the Let's Encrypt Certbot, the configuration should +look similar to this:
+[server]
+ssl = True
+certificate = /etc/letsencrypt/live/{Your Domain}/fullchain.pem
+key = /etc/letsencrypt/live/{Your Domain}/privkey.pem
Example nginx configuration:
+location /radicale/ {
+ proxy_pass https://localhost:5232/;
+ ...
+ # Place the files somewhere nginx is allowed to access (e.g. /etc/nginx/...).
+ proxy_ssl_certificate /path/to/client_cert.pem;
+ proxy_ssl_certificate_key /path/to/client_key.pem;
+}
+WSGI Server ¶
+Radicale is compatible with the WSGI specification.
+A configuration file can be set with the RADICALE_CONFIG
+environment variable, otherwise no configuration file is loaded and the
+default configuration is used.
Example uWSGI configuration:
+[uwsgi]
+http-socket = 127.0.0.1:5232
+processes = 8
+plugin = python3
+module = radicale
+env = RADICALE_CONFIG=/etc/radicale/config
Example Gunicorn configuration:
+gunicorn --bind '127.0.0.1:5232' --env 'RADICALE_CONFIG=/etc/radicale/config' \
+--workers 8 radicale
Manage user accounts with the WSGI server ¶
+Set the configuration option type
in the
+auth
section to remote_user
. This way Radicale
+uses the username provided by the WSGI server and disables its internal
+authentication over HTTP.
Versioning collections with Git ¶
+This tutorial describes how to keep track of all changes to calendars +and address books with git (or any other version +control system).
+The repository must be initialized in the collection base directory
+of the user running radicale
daemon.
## assuming "radicale" user is starting "radicale" service
+# change to user "radicale"
+su -l -s /bin/bash radicale
+
+# change to collection base directory defined in [storage] -> filesystem_folder
+# assumed here /var/lib/radicale/collections
+cd /var/lib/radicale/collections
+
+# initialize git repository
+git init
+
+# set user and e-mail, here minimum example
+git config user.name "$USER"
+git config user.email "$USER@$HOSTNAME"
+
+# define ignore of cache/lock/tmp files
+cat <<'END' >.gitignore
+.Radicale.cache
+.Radicale.lock
+.Radicale.tmp-*
+END
The configuration option hook
in the
+storage
section must be set to the following command:
git add -A && (git diff --cached --quiet || git commit -m "Changes by \"%(user)s\"")
The command gets executed after every change to the storage and +commits the changes into the git repository.
+Log of git
can be investigated using
su -l -s /bin/bash radicale
+cd /var/lib/radicale/collections
+git log
In case of problems, make sure you run radicale with
+--debug
switch and inspect the log output. For more
+information, please visit section on
+logging.
Reason for problems can be
+-
+
- SELinux status -> check related audit log +
- problematic file/directory permissions +
- command is not fond or cannot be executed or argument problem +
Documentation ¶
+Configuration ¶
+Radicale can be configured with a configuration file or with command +line arguments.
+Configuration files have INI-style syntax comprising key-value pairs +grouped into sections with section headers enclosed in brackets.
+An example configuration file looks like:
+[server]
+# Bind all addresses
+hosts = 0.0.0.0:5232, [::]:5232
+
+[auth]
+type = htpasswd
+htpasswd_filename = ~/.config/radicale/users
+htpasswd_encryption = autodetect
+
+[storage]
+filesystem_folder = ~/.var/lib/radicale/collections
Radicale tries to load configuration files from
+/etc/radicale/config
and
+~/.config/radicale/config
. Custom paths can be specified
+with the --config /path/to/config
command line argument or
+the RADICALE_CONFIG
environment variable. Multiple
+configuration files can be separated by :
(resp.
+;
on Windows). Paths that start with ?
are
+optional.
The same example configuration via command line arguments looks +like:
+python3 -m radicale --server-hosts 0.0.0.0:5232,[::]:5232 \
+--auth-type htpasswd --auth-htpasswd-filename ~/.config/radicale/users \
+ --auth-htpasswd-encryption autodetect
Add the argument --config ""
to stop Radicale from
+loading the default configuration files. Run
+python3 -m radicale --help
for more information.
You can also use command-line options in startup scripts as shown in +the following examples:
+## simple variable containing multiple options
+RADICALE_OPTIONS="--logging-level=debug --config=/etc/radicale/config --logging-request-header-on-debug --logging-rights-rule-doesnt-match-on-debug"
+/usr/bin/radicale $RADICALE_OPTIONS
+
+## variable as array method #1
+RADICALE_OPTIONS=("--logging-level=debug" "--config=/etc/radicale/config" "--logging-request-header-on-debug" "--logging-rights-rule-doesnt-match-on-debug")
+/usr/bin/radicale ${RADICALE_OPTIONS[@]}
+
+## variable as array method #2
+RADICALE_OPTIONS=()
+RADICALE_OPTIONS+=("--logging-level=debug")
+RADICALE_OPTIONS+=("--config=/etc/radicale/config")
+/usr/bin/radicale ${RADICALE_OPTIONS[@]}
The following describes all configuration sections and options.
+[server] ¶
+The configuration options in this section are only relevant in +standalone mode; they are ignored, when Radicale runs on WSGI.
+hosts ¶
+A comma separated list of addresses that the server will bind to.
+Default: localhost:5232
max_connections ¶
+The maximum number of parallel connections. Set to 0
to
+disable the limit.
Default: 8
max_content_length ¶
+The maximum size of the request body. (bytes)
+Default: 100000000
In case of using a reverse proxy in front of check also there related +option
+timeout ¶
+Socket timeout. (seconds)
+Default: 30
ssl ¶
+Enable transport layer encryption.
+Default: False
certificate ¶
+Path of the SSL certificate.
+Default: /etc/ssl/radicale.cert.pem
key ¶
+Path to the private key for SSL. Only effective if ssl
+is enabled.
Default: /etc/ssl/radicale.key.pem
certificate_authority ¶
+Path to the CA certificate for validating client certificates. This +can be used to secure TCP traffic between Radicale and a reverse proxy. +If you want to authenticate users with client-side certificates, you +also have to write an authentication plugin that extracts the username +from the certificate.
+Default: (unset)
+protocol ¶
+(>= 3.3.1)
+Accepted SSL protocol (maybe not all supported by underlying OpenSSL +version) Example for secure configuration: ALL -SSLv3 -TLSv1 -TLSv1.1 +Format: Apache SSLProtocol list (from "mod_ssl")
+Default: (system default)
+ciphersuite ¶
+(>= 3.3.1)
+Accepted SSL ciphersuite (maybe not all supported by underlying +OpenSSL version) Example for secure configuration: DHE:ECDHE:-NULL:-SHA +Format: OpenSSL cipher list (see also "man openssl-ciphers")
+Default: (system-default)
+script_name ¶
+(>= 3.5.0)
+Strip script name from URI if called by reverse proxy
+Default: (taken from HTTP_X_SCRIPT_NAME or SCRIPT_NAME)
+[encoding] ¶
+request ¶
+Encoding for responding requests.
+Default: utf-8
stock ¶
+Encoding for storing local collections
+Default: utf-8
[auth] ¶
+type ¶
+The method to verify usernames and passwords.
+Available types are:
+-
+
none
+Just allows all usernames and passwords.
+denyall
(>= 3.2.2)
+Just denies all usernames and passwords.
+htpasswd
+Use an Apache +htpasswd file to store usernames and passwords.
+remote_user
+Takes the username from theREMOTE_USER
environment +variable and disables Radicale's internal HTTP authentication. This can +be used to provide the username from a WSGI server which authenticated +the client upfront. Requires validation, otherwise clients can supply +the header themselves, which then is unconditionally trusted.
+http_x_remote_user
+Takes the username from theX-Remote-User
HTTP header and +disables Radicale's internal HTTP authentication. This can be used to +provide the username from a reverse proxy which authenticated the client +upfront. Requires validation, otherwise clients can supply the header +themselves, which then is unconditionally trusted.
+ldap
(>= 3.3.0)
+Use a LDAP or AD server to authenticate users by relaying credentials +from clients and handle results.
+dovecot
(>= 3.3.1)
+Use a Dovecot server to authenticate users by relaying credentials from +clients and handle results.
+imap
(>= 3.4.1)
+Use an IMAP server to authenticate users by relaying credentials from +clients and handle results.
+oauth2
(>= 3.5.0)
+Use an OAuth2 server to authenticate users by relaying credentials from +clients and handle results. OAuth2 authentication (SSO) directly on +client is not supported. Use hereforehttp_x_remote_user
in +combination with SSO support in reverse proxy (e.g. +Apache+mod_auth_openidc).
+pam
(>= 3.5.0)
+Use local PAM to authenticate users by relaying credentials from client +and handle result..
+
Default: none
(< 3.5.0) /
+denyall
(>= 3.5.0)
cache_logins ¶
+(>= 3.4.0)
+Cache successful/failed logins until expiration time. Enable this to +avoid overload of authentication backends.
+Default: False
cache_successful_logins_expiry ¶
+(>= 3.4.0)
+Expiration time of caching successful logins in seconds
+Default: 15
cache_failed_logins_expiry ¶
+(>= 3.4.0)
+Expiration time of caching failed logins in seconds
+Default: 90
htpasswd_filename ¶
+Path to the htpasswd file.
+Default: /etc/radicale/users
htpasswd_encryption ¶
+The encryption method that is used in the htpasswd file. Use htpasswd +or similar to generate this file.
+Available methods:
+-
+
+plain
+Passwords are stored in plaintext. This is not recommended. as it is +obviously insecure! The htpasswd file for this can be +created by hand and looks like:user1:password1 +user2:password2
+bcrypt
+This uses a modified version of the Blowfish stream cipher, which is +considered very secure. The installation of Python's +bcrypt module is required for this to work.
+md5
+Use an iterated MD5 digest of the password with salt (nowadays +insecure).
+sha256
(>= 3.1.9)
+Use an iterated SHA-256 digest of the password with salt.
+sha512
(>= 3.1.9)
+Use an iterated SHA-512 digest of the password with salt.
+argon2
(>= 3.5.3)
+Use an iterated ARGON2 digest of the password with salt. The +installation of Python's argon2-cffi module is required +for this to work.
+autodetect
(>= 3.1.9)
+Automatically detect the encryption method used per user entry.
+
Default: md5
(< 3.3.0) /
+autodetect
(>= 3.3.0)
htpasswd_cache ¶
+(>= 3.4.0)
+Enable caching of htpasswd file based on size and mtime_ns
+Default: False
delay ¶
+Average delay (in seconds) after failed login attempts.
+Default: 1
realm ¶
+Message displayed in the client when a password is needed.
+Default: Radicale - Password Required
ldap_uri ¶
+(>= 3.3.0)
+URI to the LDAP server. Mandatory for auth type
+ldap
.
Default: ldap://localhost
ldap_base ¶
+(>= 3.3.0)
+Base DN of the LDAP server. Mandatory for auth type
+ldap
.
Default: (unset)
+ldap_reader_dn ¶
+(>= 3.3.0)
+DN of a LDAP user with read access users and - if defined - groups.
+Mandatory for auth type ldap
.
Default: (unset)
+ldap_secret ¶
+(>= 3.3.0)
+Password of ldap_reader_dn
. Mandatory for auth type
+ldap
unless ldap_secret_file
is given.
Default: (unset)
+ldap_secret_file ¶
+(>= 3.3.0)
+Path to the file containing the password of
+ldap_reader_dn
. Mandatory for auth type ldap
+unless ldap_secret
is given.
Default: (unset)
+ldap_filter ¶
+(>= 3.3.0)
+Filter to search for the LDAP entry of the user to authenticate. It +must contain '{0}' as placeholder for the login name.
+Default: (cn={0})
ldap_user_attribute ¶
+(>= 3.4.0)
+LDAP attribute whose value shall be used as the username after +successful authentication.
+If set, you can use flexible logins in ldap_filter
and
+still have consolidated usernames, e.g. to allow users to login using
+mail addresses as an alternative to cn, simply set
ldap_filter = (&(objectclass=inetOrgPerson)(|(cn={0})(mail={0})))
+ldap_user_attribute = cn
Even for simple filter setups, it is recommended to set it in order +to get usernames exactly as they are stored in LDAP and to avoid +inconsistencies in the upper-/lower-case spelling of the login +names.
+Default: (unset, in which case the login name is directly used as the +username)
+ldap_use_ssl ¶
+(>= 3.3.0)
+Use ssl on the LDAP connection. Deprecated! Use
+ldap_security
instead.
ldap_security ¶
+(>= 3.5.2)
+Use encryption on the LDAP connection.
+One of
+-
+
none
+tls
+starttls
+
Default: none
ldap_ssl_verify_mode ¶
+(>= 3.3.0)
+Certificate verification mode for tls and starttls.
+One of
+-
+
NONE
+OPTIONAL
+REQUIRED
.
+
Default: REQUIRED
ldap_ssl_ca_file ¶
+(>= 3.3.0)
+Path to the CA file in PEM format which is used to certify the server +certificate
+Default: (unset)
+ldap_groups_attribute ¶
+(>= 3.4.0)
+LDAP attribute in the authenticated user's LDAP entry to read the +group memberships from.
+E.g. memberOf
to get groups on Active Directory and
+alikes, groupMembership
on Novell eDirectory, ...
If set, get the user's LDAP groups from the attribute given.
+For DN-valued attributes, the value of the RDN is used to determine +the group names. The implementation also supports non-DN-valued +attributes: their values are taken directly.
+The user's group names can be used later to define rights. They also +give you access to the group calendars, if those exist.
+-
+
- Group calendars are placed directly under
+collection_root_folder
/GROUPS/
with the +base64-encoded group name as the calendar folder name.
+ - Group calendar folders are not created automatically. This must be +done manually. In the LDAP-authentication +section of Radicale's wiki you can find a script to create a group +calendar. +
Default: (unset)
+ldap_group_members_attribute ¶
+(>= 3.5.6)
+Attribute in the group entries to read the group's members from.
+E.g. member
for groups with objectclass
+groupOfNames
.
Using ldap_group_members_attribute
,
+ldap_group_base
and ldap_group_filter
is an
+alternative approach to getting the user's groups. Instead of reading
+them from ldap_groups_attribute
in the user's entry, an
+additional query is performed to seach for those groups beneath
+ldap_group_base
, that have the user's DN in their
+ldap_group_members_attribute
and additionally fulfil
+ldap_group_filter
.
As with DN-valued ldap_groups_attribute
, the value of
+the RDN is used to determine the group names.
Default: (unset)
+ldap_group_base ¶
+(>= 3.5.6)
+Base DN to search for groups. Only necessary if
+ldap_group_members_attribute
is set, and if the base DN for
+groups differs from ldap_base
.
Default: (unset, in which case ldap_base
is used as
+fallback)
ldap_group_filter ¶
+(>= 3.5.6)
+Search filter to search for groups having the user DN found as
+member. Only necessary ldap_group_members_attribute
is set,
+and you want the groups returned to be restricted instead of all groups
+the user's DN is in.
Default: (unset)
+ldap_ignore_attribute_create_modify_timestamp ¶
+(>= 3.5.1)
+Quirks for Authentik LDAP server, which violates the LDAP RFCs: add +modifyTimestamp and createTimestamp to the exclusion list of internal +ldap3 client so that these schema attributes are not checked.
+Default: False
dovecot_connection_type ¶
+(>= 3.4.1)
+Connection type for dovecot authentication.
+One of:
+-
+
AF_UNIX
+AF_INET
+AF_INET6
+
Note: credentials are transmitted in cleartext
+Default: AF_UNIX
dovecot_socket ¶
+(>= 3.3.1)
+Path to the Dovecot client authentication socket (eg. +/run/dovecot/auth-client on Fedora). Radicale must have read & write +access to the socket.
+Default: /var/run/dovecot/auth-client
dovecot_host ¶
+(>= 3.4.1)
+Host of dovecot socket exposed via network
+Default: localhost
dovecot_port ¶
+(>= 3.4.1)
+Port of dovecot socket exposed via network
+Default: 12345
remote_ip_source ¶
+(>= 3.5.6)
+For authentication mechanisms that are made aware of the remote IP
+(such as dovecot via the rip=
auth protocol parameter),
+determine the source to use. Currently, valid values are
REMOTE_ADDR
(default) : Use the REMOTE_ADDR environment
+variable that captures the remote address of the socket connection.
X-Remote-Addr
: Use the X-Remote-Addr
HTTP
+header value.
In the case of X-Remote-Addr
, Radicale must be running
+be running behind a proxy that you control and that sets/overwrites the
+X-Remote-Addr
header (doesn't pass it) so that the value
+passed to dovecot is reliable. For example, for nginx, add
proxy_set_header X-Remote-Addr $remote_addr;
+to the configuration sample.
+Default: REMOTE_ADDR
imap_host ¶
+(>= 3.4.1)
+IMAP server hostname.
+One of:
+-
+
- address +
- address:port + +
- imap.server.tld +
Default: localhost
imap_security ¶
+(>= 3.4.1)
+Secure the IMAP connection:
+One of:
+-
+
tls
+starttls
+none
+
Default: tls
oauth2_token_endpoint ¶
+(>= 3.5.0)
+Endpoint URL for the OAuth2 token
+Default: (unset)
+pam_service ¶
+(>= 3.5.0)
+PAM service name
+Default: radicale
pam_group_membership ¶
+(>= 3.5.0)
+PAM group user should be member of
+Default: (unset)
+lc_username ¶
+Сonvert username to lowercase. Recommended to be True
+for case-insensitive auth providers like ldap, kerberos, ...
Default: False
Notes:
+-
+
lc_username
anduc_username
are mutually +exclusive
+- for auth type
ldap
the use of +ldap_user_attribute
is preferred over +lc_username
+
uc_username ¶
+(>= 3.3.2)
+Сonvert username to uppercase. Recommended to be True
+for case-insensitive auth providers like ldap, kerberos, ...
Default: False
Notes:
+-
+
uc_username
andlc_username
are mutually +exclusive
+- for auth type
ldap
the use of +ldap_user_attribute
is preferred over +uc_username
+
strip_domain ¶
+(>= 3.2.3)
+Strip domain from username
+Default: False
urldecode_username ¶
+(>= 3.5.3)
+URL-decode the username. If the username is an email address, some +clients send the username URL-encoded (notably iOS devices) breaking the +authentication process (user@example.com becomes +user%40example.com). This setting forces decoding the username.
+Default: False
[rights] ¶
+type ¶
+Authorization backend that is used to check the access rights to +collections.
+The default and recommended backend is owner_only
. If
+access to calendars and address books outside the user's collection
+directory (that's /username/
) is granted, clients will not
+detect these collections automatically and will not show them to the
+users. Choosing any other authorization backend is only useful if you
+access calendars and address books directly via URL.
Available backends are:
+-
+
authenticated
+Authenticated users can read and write everything.
+owner_only
+Authenticated users can read and write their own collections under the +path /USERNAME/.
+owner_write
+Authenticated users can read everything and write their own collections +under the path /USERNAME/.
+from_file
+Load the rules from a file.
+
Default: owner_only
file ¶
+Name of the file containing the authorization rules for the
+from_file
backend. See the Rights section for details.
Default: /etc/radicale/rights
permit_delete_collection ¶
+(>= 3.1.9)
+Global permission to delete complete collections.
+-
+
- If
False
it can be explicitly granted per collection by +permissions: D
+ - If
True
it can be explicitly forbidden per collection +bypermissions: d
+
Default: True
permit_overwrite_collection ¶
+(>= 3.3.0)
+Global permission to overwrite complete collections.
+-
+
- If
False
it can be explicitly granted per collection by +permissions: O
+ - If
True
it can be explicitly forbidden per collection +bypermissions: o
+
Default: True
[storage] ¶
+type ¶
+Backend used to store data.
+Available backends are:
+-
+
multifilesystem
+Stores the data in the filesystem.
+multifilesystem_nolock
+Themultifilesystem
backend without file-based locking. +Must only be used with a single process.
+
Default: multifilesystem
filesystem_folder ¶
+Folder for storing local collections; will be auto-created if not +present.
+Default: /var/lib/radicale/collections
filesystem_cache_folder ¶
+(>= 3.3.2)
+Folder for storing cache of local collections; will be auto-created +if not present
+Default: (filesystem_folder)
+Note: only used if use_cache_subfolder_* options are active
+Note: can be used on multi-instance setup to cache files on local +node (see below)
+use_cache_subfolder_for_item ¶
+(>= 3.3.2)
+Use subfolder collection-cache
for cache file structure
+of 'item' instead of inside collection folders, created if not
+present
Default: False
Note: can be used on multi-instance setup to cache 'item' on local +node
+use_cache_subfolder_for_history ¶
+(>= 3.3.2)
+Use subfolder collection-cache
for cache file structure
+of 'history' instead of inside collection folders, created if not
+present
Default: False
Note: only use on single-instance setup: it will break consistency +with clients in multi-instance setup
+use_cache_subfolder_for_synctoken ¶
+(>= 3.3.2)
+Use subfolder collection-cache
for cache file structure
+of 'sync-token' instead of inside collection folders, created if not
+present
Default: False
Note: only use on single-instance setup: it will break consistency +with clients in multi-instance setup
+use_mtime_and_size_for_item_cache ¶
+(>= 3.3.2)
+Use last modification time (in nanoseconds) and size (in bytes) for +'item' cache instead of SHA256 (improves speed)
+Default: False
Notes:
+-
+
- check used filesystem mtime precision before enabling +
- conversion is done on access +
- bulk conversion can be done offline using the storage verification
+option
radicale --verify-storage
+
folder_umask ¶
+(>= 3.3.2)
+umask to use for folder creation (not applicable for OS Windows)
+Default: (system-default, usually 0022
)
Useful values:
+-
+
0077
(user:rw group:- other:-)
+0027
(user:rw group:r other:-)
+0007
(user:rw group:rw other:-)
+0022
(user:rw group:r other:r)
+
max_sync_token_age ¶
+Delete sync-tokens that are older than the specified time (in +seconds).
+Default: 2592000
skip_broken_item ¶
+(>= 3.2.2)
+Skip broken item instead of triggering an exception
+Default: True
hook ¶
+Command that is run after changes to storage. See the Versioning collections with +Git tutorial for an example.
+Default: (unset)
+Supported placeholders:
+-
+
%(user)s
: logged-in user
+%(cwd)s
: current working directory (>= +3.5.1)
+%(path)s
: full path of item (>= 3.5.1)
+%(to_path)s
: full path of destination item (only set on +MOVE request) (>= 3.5.5)
+%(request)s
: request method (>= 3.5.5)
+
The command will be executed with base directory defined in
+filesystem_folder
(see above)
predefined_collections ¶
+Create predefined user collections.
+Example:
+{
+"def-addressbook": {
+ "D:displayname": "Personal Address Book",
+ "tag": "VADDRESSBOOK"
+ },
+ "def-calendar": {
+ "C:supported-calendar-component-set": "VEVENT,VJOURNAL,VTODO",
+ "D:displayname": "Personal Calendar",
+ "tag": "VCALENDAR"
+ }
+ }
Default: (unset)
+[web] ¶
+type ¶
+The backend that provides the web interface of Radicale.
+Available backends are:
+-
+
none
+Simply shows the message "Radicale works!".
+internal
+Allows creation and management of address books and calendars.
+
Default: internal
[logging] ¶
+level ¶
+Set the logging level.
+Available levels are:
+-
+
debug
+info
+warning
+error
+critical
+
Default: warning
(< 3.2.0) /
+info
(>= 3.2.0)
trace_on_debug ¶
+(> 3.5.4)
+Do not filter debug messages starting with 'TRACE'
+Default: False
trace_filter ¶
+(> 3.5.4)
+Filter debug messages starting with 'TRACE/
Prerequisite: trace_on_debug = True
Default: (empty)
+mask_passwords ¶
+Do not include passwords in logs.
+Default: True
bad_put_request_content ¶
+(>= 3.2.1)
+Log bad PUT request content (for further diagnostics)
+Default: False
backtrace_on_debug ¶
+(>= 3.2.2)
+Log backtrace on level = debug
Default: False
request_header_on_debug ¶
+(>= 3.2.2)
+Log request on level = debug
Default: False
request_content_on_debug ¶
+(>= 3.2.2)
+Log request on level = debug
Default: False
response_content_on_debug ¶
+(>= 3.2.2)
+Log response on level = debug
Default: False
rights_rule_doesnt_match_on_debug ¶
+(>= 3.2.3)
+Log rights rule which doesn't match on level = debug
Default: False
storage_cache_actions_on_debug ¶
+(>= 3.3.2)
+Log storage cache actions on level = debug
Default: False
[headers] ¶
+This section can be used to specify additional HTTP headers that will +be sent to clients.
+An example to relax the same-origin policy:
+Access-Control-Allow-Origin = *
[hook] ¶
+type ¶
+Hook binding for event changes and deletion notifications.
+Available types are:
+-
+
none
+Disabled. Nothing will be notified.
+rabbitmq
(>= 3.2.0)
+Push the message to the rabbitmq server.
+email
(>= 3.5.5)
+Send an email notification to event attendees.
+
Default: none
dryrun ¶
+(> 3.5.4)
+Dry-Run / simulate (i.e. do not really trigger) the hook action.
+Default: False
rabbitmq_endpoint ¶
+(>= 3.2.0)
+End-point address for rabbitmq server. E.g.:
+amqp://user:password@localhost:5672/
Default: (unset)
+rabbitmq_topic ¶
+(>= 3.2.0)
+RabbitMQ topic to publish message in.
+Default: (unset)
+rabbitmq_queue_type ¶
+(>= 3.2.0)
+RabbitMQ queue type for the topic.
+Default: classic
smtp_server ¶
+(>= 3.5.5)
+Address of SMTP server to connect to.
+Default: (unset)
+smtp_port ¶
+(>= 3.5.5)
+Port on SMTP server to connect to.
+Default:
+smtp_security ¶
+(>= 3.5.5)
+Use encryption on the SMTP connection.
+One of:
+-
+
none
+tls
+starttls
+
Default: none
smtp_ssl_verify_mode ¶
+(>= 3.5.5)
+The certificate verification mode for tls and starttls.
+One of:
+-
+
NONE
+OPTIONAL
+REQUIRED
+
Default: REQUIRED
smtp_username ¶
+(>= 3.5.5)
+Username to authenticate with SMTP server. Leave empty to disable +authentication (e.g. using local mail server).
+Default: (unset)
+smtp_password ¶
+(>= 3.5.5)
+Password to authenticate with SMTP server. Leave empty to disable +authentication (e.g. using local mail server).
+Default: (unset)
+from_email ¶
+(>= 3.5.5)
+Email address to use as sender in email notifications.
+Default: (unset)
+mass_email ¶
+(>= 3.5.5)
+When enabled, send one email to all attendee email addresses. When +disabled, send one email per attendee email address.
+Default: False
new_or_added_to_event_template ¶
+(>= 3.5.5)
+Template to use for added/updated event email body sent to an +attendee when the event is created or they are added to a pre-existing +event.
+The following placeholders will be replaced:
+-
+
$organizer_name
: Name of the organizer, or "Unknown +Organizer" if not set in event
+$from_email
: Email address the email is sent from
+$attendee_name
: Name of the attendee (email recipient), +or "everyone" if mass email enabled.
+$event_name
: Name/summary of the event, or "No Title" +if not set in event
+$event_start_time
: Start time of the event in ISO 8601 +format
+$event_end_time
: End time of the event in ISO 8601 +format, or "No End Time" if the event has no end time
+$event_location
: Location of the event, or "No Location +Specified" if not set in event
+
Providing any words prefixed with $ not included in the list above +will result in an error.
+Default:
+Hello $attendee_name,
+
+You have been added as an attendee to the following calendar event.
+
+ $event_title
+ $event_start_time - $event_end_time
+ $event_location
+
+This is an automated message. Please do not reply.
+deleted_or_removed_from_event_template ¶
+(>= 3.5.5)
+Template to use for deleted/removed event email body sent to an +attendee when the event is deleted or they are removed from the +event.
+The following placeholders will be replaced:
+-
+
$organizer_name
: Name of the organizer, or "Unknown +Organizer" if not set in event
+$from_email
: Email address the email is sent from
+$attendee_name
: Name of the attendee (email recipient), +or "everyone" if mass email enabled.
+$event_name
: Name/summary of the event, or "No Title" +if not set in event
+$event_start_time
: Start time of the event in ISO 8601 +format
+$event_end_time
: End time of the event in ISO 8601 +format, or "No End Time" if the event has no end time
+$event_location
: Location of the event, or "No Location +Specified" if not set in event
+
Providing any words prefixed with $ not included in the list above +will result in an error.
+Default:
+Hello $attendee_name,
+
+The following event has been deleted.
+
+ $event_title
+ $event_start_time - $event_end_time
+ $event_location
+
+This is an automated message. Please do not reply.
+updated_event_template ¶
+(>= 3.5.5)
+Template to use for updated event email body sent to an attendee when +non-attendee-related details of the event are updated.
+Existing attendees will NOT be notified of a modified event if the +only changes are adding/removing other attendees.
+The following placeholders will be replaced:
+-
+
$organizer_name
: Name of the organizer, or "Unknown +Organizer" if not set in event
+$from_email
: Email address the email is sent from
+$attendee_name
: Name of the attendee (email recipient), +or "everyone" if mass email enabled.
+$event_name
: Name/summary of the event, or "No Title" +if not set in event
+$event_start_time
: Start time of the event in ISO 8601 +format
+$event_end_time
: End time of the event in ISO 8601 +format, or "No End Time" if the event has no end time
+$event_location
: Location of the event, or "No Location +Specified" if not set in event
+
Providing any words prefixed with $ not included in the list above +will result in an error.
+Default:
+Hello $attendee_name,
+
+The following event has been updated.
+
+ $event_title
+ $event_start_time - $event_end_time
+ $event_location
+
+This is an automated message. Please do not reply.
+[reporting] ¶
+max_freebusy_occurrence ¶
+(>= 3.2.3)
+When returning a free-busy report, a list of busy time occurrences +are generated based on a given time frame. Large time frames could +generate a lot of occurrences based on the time frame supplied. This +setting limits the lookup to prevent potential denial of service attacks +on large time frames. If the limit is reached, an HTTP error is thrown +instead of returning the results.
+Default: 10000
+Supported Clients ¶
+Radicale has been tested with:
+-
+
- Android with DAVx⁵ (formerly DAVdroid), +
- OneCalendar +
- GNOME Calendar, +Contacts and Evolution +
- KDE PIM Applications, KDE Merkuro +
- Mozilla +Thunderbird (Thunderbird/Radicale) +with CardBook +and Lightning +
- InfCloud +(InfCloud/Radicale), +CalDavZAP, +CardDavMATE +and Open +Calendar +
- pimsync (pimsync/Radicale) +
Many clients do not support the creation of new calendars and address +books. You can use Radicale's web interface (e.g. http://localhost:5232) to create and +manage address books and calendars.
+In some clients, it is sufficient to simply enter the URL of the
+Radicale server (e.g. http://localhost:5232
) and your
+username. In others, you have to enter the URL of the collection
+directly (e.g. http://localhost:5232/user/calendar
).
Some clients (notably macOS's Calendar.app) may silently refuse to +include account credentials over unsecured HTTP, leading to unexpected +authentication failures. In these cases, you want to make sure the +Radicale server is accessible over HTTPS.
+DAVx⁵ ¶
+Enter the URL of the Radicale server (e.g.
+http://localhost:5232
) and your username. DAVx⁵ will show
+all existing calendars and address books and you can create new
+ones.
OneCalendar ¶
+When adding account, select CalDAV account type, then enter username,
+password and the Radicale server (e.g.
+https://yourdomain:5232
). OneCalendar will show all
+existing calendars and (FIXME: address books), you need to select which
+ones you want to see. OneCalendar supports many other server types
+too.
GNOME Calendar, Contacts ¶
+GNOME 46 added CalDAV and CardDAV support to GNOME Online +Accounts.
+Open GNOME Settings, navigate to Online Accounts >
+Connect an Account > Calendar, Contacts and Files.
+Enter the URL (e.g. https://example.com/radicale
) and your
+credentials then click Sign In. In the pop-up dialog, turn off
+Files. After adding Radicale in GNOME Online Accounts,
+it should be available in GNOME Contacts and GNOME Calendar.
Evolution ¶
+In Evolution add a new calendar and address book
+respectively with WebDAV. Enter the URL of the Radicale server (e.g.
+http://localhost:5232
) and your username. Clicking on the
+search button will list the existing calendars and address books.
Adding CalDAV and CardDAV accounts in Evolution will automatically +make them available in GNOME Contacts and GNOME Calendar.
+KDE PIM Applications ¶
+In Kontact add a DAV Groupware resource to +Akonadi under Settings > Configure Kontact > Calendar > +General > Calendars, select the protocol (CalDAV or CardDAV), +add the URL to the Radicale collections and enter the credentials. After +synchronization of the calendar resp. addressbook items, you can manage +them in Kontact.
+Thunderbird ¶
+Add a new calendar on the network. Enter your username and the URL of
+the Radicale server (e.g. http://localhost:5232
). After
+asking for your password, it will list the existing calendars.
Adress books with CardBook add-on ¶
+Add a new address book on the network with CardDAV. Enter the URL of
+the Radicale server (e.g. http://localhost:5232
) and your
+username and password. It will list your existing address books.
InfCloud, CalDavZAP and CardDavMATE ¶
+You can integrate InfCloud into Radicale's web interface with by
+simply downloading the latest package from InfCloud
+and extract the content into a folder named infcloud
in
+radicale/web/internal_data/
.
No further adjustments are required as content is adjusted on the fly +(tested with 0.13.1).
+See also Wiki/Client +InfCloud.
+Command line ¶
+This is not the recommended way of creating and managing your +calendars and address books. Use Radicale's web interface or a client +with support for it (e.g. DAVx⁵).
+To create a new calendar run something like:
+$ curl -u user -X MKCOL 'http://localhost:5232/user/calendar' --data \
+'<?xml version="1.0" encoding="UTF-8" ?>
+<create xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:I="http://apple.com/ns/ical/">
+ <set>
+ <prop>
+ <resourcetype>
+ <collection />
+ <C:calendar />
+ </resourcetype>
+ <C:supported-calendar-component-set>
+ <C:comp name="VEVENT" />
+ <C:comp name="VJOURNAL" />
+ <C:comp name="VTODO" />
+ </C:supported-calendar-component-set>
+ <displayname>Calendar</displayname>
+ <C:calendar-description>Example calendar</C:calendar-description>
+ <I:calendar-color>#ff0000ff</I:calendar-color>
+ </prop>
+ </set>
+</create>'
To create a new address book run something like:
+$ curl -u user -X MKCOL 'http://localhost:5232/user/addressbook' --data \
+'<?xml version="1.0" encoding="UTF-8" ?>
+<create xmlns="DAV:" xmlns:CR="urn:ietf:params:xml:ns:carddav">
+ <set>
+ <prop>
+ <resourcetype>
+ <collection />
+ <CR:addressbook />
+ </resourcetype>
+ <displayname>Address book</displayname>
+ <CR:addressbook-description>Example address book</CR:addressbook-description>
+ </prop>
+ </set>
+</create>'
The collection /USERNAME
will be created automatically,
+when the user authenticates to Radicale for the first time. Clients with
+automatic discovery of collections will only show calendars and address
+books that are direct children of the path /USERNAME/
.
Delete the collections by running something like:
+curl -u user -X DELETE 'http://localhost:5232/user/calendar'
Note: requires config/option
+permit_delete_collection = True
Authorization and Rights ¶
+This section describes the format of the rights file for the
+from_file
authentication backend. The configuration option
+file
in the rights
section must point to the
+rights file.
The recommended rights method is owner_only
. If access
+is granted to calendars and address books outside the home directory of
+users (that's /USERNAME/
), clients will not detect these
+collections automatically, and will not show them to the users. This is
+only useful if you access calendars and address books directly via
+URL.
An example rights file:
+# Allow reading root collection for authenticated users
+[root]
+user: .+
+collection:
+permissions: R
+
+# Allow reading and writing principal collection (same as username)
+[principal]
+user: .+
+collection: {user}
+permissions: RW
+
+# Allow reading and writing calendars and address books that are direct
+# children of the principal collection
+[calendars]
+user: .+
+collection: {user}/[^/]+
+permissions: rw
The titles of the sections are ignored (but must be unique). The keys
+user
and collection
contain regular
+expressions, that are matched against the username and the path of the
+collection. Permissions from the first matching section are used. If no
+section matches, access gets denied.
The username is empty for anonymous users. Therefore, the regex
+.+
only matches authenticated users and .*
+matches everyone (including anonymous users).
The path of the collection is separated by /
and has no
+leading or trailing /
. Therefore, the path of the root
+collection is empty.
In the collection
regex you can use {user}
+and get groups from the user
regex with {0}
,
+{1}
, etc.
In consequence of the parameter substitution you have to write
+{{
and }}
if you want to use regular curly
+braces in the user
and collection
regexes.
The following permissions
are recognized:
-
+
- R: read collections (excluding address books and +calendars) +
- r: read address book and calendar collections +
- i: subset of r that only allows +direct access via HTTP method GET (CalDAV/CardDAV is susceptible to +expensive search requests) +
- W: write collections (excluding address books and +calendars) +
- w: write address book and calendar collections +
- D: allow deleting a collection in case
+
permit_delete_collection=False
(>= 3.3.0)
+ - d: deny deleting a collection in case
+
permit_delete_collection=True
(>= 3.3.0)
+ - O: allow overwriting a collection in case
+
permit_overwrite_collection=False
+ - o: deny overwriting a collection in case
+
permit_overwrite_collection=True
+
Storage ¶
+This document describes the layout and format of the file system
+storage, the multifilesystem
backend.
It is safe to access and manipulate the data by hand or with scripts.
+Scripts can be invoked manually, periodically (e.g. using cron)
+or after each change to the storage with the configuration option
+hook
in the storage
section (e.g. Versioning collections with
+Git).
Layout ¶
+The file system comprises the following files and folders:
+-
+
.Radicale.lock
: The lock file for locking the +storage.
+collection-root
: This folder contains all collections +and items.
+
Each collection is represented by a folder. This folder may contain
+the file .Radicale.props
with all WebDAV properties of the
+collection encoded as JSON.
Each item in a calendar or address book collection is represented by +a file containing the item's iCalendar resp. vCard data.
+All files and folders, whose names start with a dot but not with
+.Radicale.
(internal files) are ignored.
Syntax errors in any of the files will cause all requests accessing +the faulty data to fail. The logging output should contain the names of +the culprits.
+Caches and sync-tokens are stored in the .Radicale.cache
+folder inside of collections. This folder may be created or modified,
+while the storage is locked for shared access. In theory, it should be
+safe to delete the folder. Caches will be recreated automatically and
+clients will be told that their sync-token is not valid anymore.
You may encounter files or folders that start with
+.Radicale.tmp-
. Radicale uses them for atomic creation and
+deletion of files and folders. They should be deleted after requests are
+finished but it is possible that they are left behind when Radicale or
+the computer crashes. You can safely delete them.
Locking ¶
+When the data is accessed by hand or by an externally invoked script,
+the storage must be locked. The storage can be locked for exclusive or
+shared access. It prevents Radicale from reading or writing the file
+system. The storage is locked with exclusive access while the
+hook
runs.
Linux shell scripts ¶
+Use the flock +utility to acquire exclusive or shared locks for the commands you want +to run on Radicale's data.
+# Exclusive lock for COMMAND
+$ flock --exclusive /path/to/storage/.Radicale.lock COMMAND
+# Shared lock for COMMAND
+$ flock --shared /path/to/storage/.Radicale.lock COMMAND
Linux and MacOS ¶
+Use the flock +syscall. Python provides it in the fcntl +module.
+Windows ¶
+Use LockFile
+for exclusive access or LockFileEx
+which also supports shared access. Setting
+nNumberOfBytesToLockLow
to 1
and
+nNumberOfBytesToLockHigh
to 0
works.
Manually creating collections ¶
+To create a new collection, you need to create the corresponding
+folder in the file system storage (e.g.
+collection-root/user/calendar
). To indicate to Radicale and
+clients that the collection is a calendar, you have to create the file
+.Radicale.props
with the following content in the
+folder:
{"tag": "VCALENDAR"}
The calendar is now available at the URL path (e.g.
+/user/calendar
). For address books
+.Radicale.props
must contain:
{"tag": "VADDRESSBOOK"}
Calendar and address book collections must not have any child
+collections. Clients with automatic discovery of collections will only
+show calendars and address books that are direct children of the path
+/USERNAME/
.
Delete collections by deleting the corresponding folders.
+Logging overview ¶
+Radicale logs to stderr
. The verbosity of the log output
+can be controlled with --debug
command line argument or the
+level
configuration option in the logging section.
Architecture ¶
+Radicale is a small piece of software, but understanding it is not as +easy as it seems. But don't worry, reading this short section is enough +to understand what a CalDAV/CardDAV server is, and how Radicale's code +is organized.
+Protocol overview ¶
+Here is a simple overview of the global architecture for reaching a +calendar or an address book through network:
+Part | +Layer | +Protocol or Format | +
---|---|---|
Server | +Calendar/Contact Storage | +iCal/vCard | +
'' | +Calendar/Contact Server | +CalDAV/CardDAV Server | +
Transfer | +Network | +CalDAV/CardDAV (HTTP + TLS) | +
Client | +Calendar/Contact Client | +CalDAV/CardDAV Client | +
'' | +GUI | +Terminal, GTK, Web interface, etc. | +
Radicale is only the server part of this +architecture.
+Please note:
+-
+
- CalDAV and CardDAV are extension protocols of WebDAV, +
- WebDAV is an extension of the HTTP protocol. +
Radicale being a CalDAV/CardDAV server, can also be seen as a special +WebDAV and HTTP server.
+Radicale is not the client part of this +architecture. It means that Radicale never draws calendars, address +books, events and contacts on the screen. It only stores them and give +the possibility to share them online with other people.
+If you want to see or edit your events and your contacts, you have to +use another software called a client, that can be a "normal" +applications with icons and buttons, a terminal or another web +application.
+Code Architecture ¶
+The radicale
package offers the following modules.
-
+
__init__
: Contains the entry point for +WSGI.
+__main__
: Provides the entry point for the +radicale
executable and includes the command line parser. +It loads configuration files from the default (or specified) paths and +starts the internal server.
+app
: This is the core part of Radicale, with the +code for the CalDAV/CardDAV server. The code managing the different HTTP +requests according to the CalDAV/CardDAV specification can be found +here.
+auth
: Used for authenticating users based on +username and password, mapping usernames to internal users and +optionally retrieving credentials from the environment.
+config
: Contains the code for managing +configuration and loading settings from files.
+ìtem
: Internal representation of address book and +calendar entries. Based on VObject.
+log
: The logger for Radicale based on the default +Python logging module.
+rights
: This module is used by Radicale to manage +access rights to collections, address books and calendars.
+server
: The integrated HTTP server for standalone +use.
+storage
: This module contains the classes +representing collections in Radicale and the code for storing and +loading them in the filesystem.
+web
: This module contains the web +interface.
+utils
: Contains general helper functions.
+httputils
: Contains helper functions for working +with HTTP.
+pathutils
: Helper functions for working with paths +and the filesystem.
+xmlutils
: Helper functions for working with the XML +part of CalDAV/CardDAV requests and responses. It's based on the +ElementTree XML API.
+
Plugins ¶
+Radicale can be extended by plugins for authentication, rights +management and storage. Plugins are python modules.
+Getting started with plugin development ¶
+To get started we walk through the creation of a simple +authentication plugin, that accepts login attempts with a static +password.
+The easiest way to develop and install python
+modules is Distutils.
+For a minimal setup create the file setup.py
with the
+following content in an empty folder:
#!/usr/bin/env python3
+
+from distutils.core import setup
+
+="radicale_static_password_auth",
+ setup(name=["radicale_static_password_auth"]) packages
In the same folder create the sub-folder
+radicale_static_password_auth
. The folder must have the
+same name as specified in packages
above.
Create the file __init__.py
in the
+radicale_static_password_auth
folder with the following
+content:
from radicale.auth import BaseAuth
+from radicale.log import logger
+
+= {"auth": {
+ PLUGIN_CONFIG_SCHEMA "password": {"value": "", "type": str}}}
+
+
+class Auth(BaseAuth):
+def __init__(self, configuration):
+ super().__init__(configuration.copy(PLUGIN_CONFIG_SCHEMA))
+
+def _login(self, login, password):
+ # Get password from configuration option
+ = self.configuration.get("auth", "password")
+ static_password # Check authentication
+ "Login attempt by %r with password %r",
+ logger.info(
+ login, password)if password == static_password:
+ return login
+ return ""
Install the python module by running the following command in the
+same folder as setup.py
:
python3 -m pip install .
To make use this great creation in Radicale, set the configuration
+option type
in the auth
section to
+radicale_static_password_auth
:
[auth]
+type = radicale_static_password_auth
+password = secret
You can uninstall the module with:
+python3 -m pip uninstall radicale_static_password_auth
Authentication plugins ¶
+This plugin type is used to check login credentials. The module must
+contain a class Auth
that extends
+radicale.auth.BaseAuth
. Take a look at the file
+radicale/auth/__init__.py
in Radicale's source code for
+more information.
Rights management plugins ¶
+This plugin type is used to check if a user has access to a path. The
+module must contain a class Rights
that extends
+radicale.rights.BaseRights
. Take a look at the file
+radicale/rights/__init__.py
in Radicale's source code for
+more information.
Web plugins ¶
+This plugin type is used to provide the web interface for Radicale.
+The module must contain a class Web
that extends
+radicale.web.BaseWeb
. Take a look at the file
+radicale/web/__init__.py
in Radicale's source code for more
+information.
Storage plugins ¶
+This plugin is used to store collections and items. The module must
+contain a class Storage
that extends
+radicale.storage.BaseStorage
. Take a look at the file
+radicale/storage/__init__.py
in Radicale's source code for
+more information.
Contribute ¶
+Report Bugs ¶
+Found a bug? Want a new feature? Report a new issue on the Radicale +bug-tracker.
+Hack ¶
+Interested in hacking? Feel free to clone the git repository on GitHub if +you want to add new features, fix bugs or update the documentation.
+Documentation ¶
+To change or complement the documentation create a pull request to DOCUMENTATION.md.
+Download ¶
+PyPI ¶
+Radicale is available on PyPI. To +install, just type as superuser:
+python3 -m pip install --upgrade radicale
Git Repository ¶
+If you want the development version of Radicale, take a look at the +git repository on +GitHub, or install it directly with:
+python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
You can also download the content of the repository as an archive.
+Source Packages ¶
+You can find the source packages of all releases on GitHub.
+Docker ¶
+Radicale is available as a Docker
+image for platforms linux/amd64
and
+linux/arm64
. To install the latest version, run:
docker pull ghcr.io/kozea/radicale:latest
An example docker-compose.yml
and detailed instructions
+will soon be updated.
Linux Distribution Packages ¶
+Radicale has been packaged for:
+-
+
- ArchLinux +by David Runge +
- Debian by Jonas +Smedegaard +
- Gentoo +by René Neumann, Maxim Koltsov and Manuel Rüger +
- Fedora/EnterpriseLinux +by Jorti and Peter Bieringer +
- Mageia +by Jani Välimaa +
- OpenBSD by +Sergey Bronnikov, Stuart Henderson and Ian Darwin +
- openSUSE +by Ákos Szőts and Rueckert +
- PyPM +
- Slackware +by Johannes Schöpfer +
- Trisquel +
- Ubuntu by the MOTU +and Jonas Smedegaard +
Radicale is also available +on Cloudron.
+If you are interested in creating packages for other Linux +distributions, read the "Contribute" +section.
+About ¶
+Main Goals ¶
+Radicale is a complete calendar and contact storing and manipulating +solution. It can store multiple calendars and multiple address +books.
+Calendar and contact manipulation is available from both local and +distant accesses, possibly limited through authentication policies.
+It aims to be a lightweight solution, easy to use, easy to install, +easy to configure. As a consequence, it requires few software +dependencies and is preconfigured to work out-of-the-box.
+Radicale is written in Python. It runs on most of the UNIX-like +platforms (Linux, *BSD, macOS) and Windows. It is free and open-source +software.
+What Radicale Will Never Be ¶
+Radicale is a server, not a client. No interfaces will be created to +work with the server.
+CalDAV and CardDAV are not perfect protocols. We think that their +main problem is their complexity, that is why we decided not to +implement the whole standard but just enough to understand some of its +client-side implementations.
+CalDAV and CardDAV are the best open standards available, and they +are quite widely used by both clients and servers. We decided to use it, +and we will not use another one.
+Technical Choices ¶
+Important global development choices have been decided before writing +code. They are very useful to understand why the Radicale Project is +different from other CalDAV and CardDAV servers, and why features are +included or not in the code.
+Oriented to Calendar and Contact User Agents ¶
+Calendar and contact servers work with calendar and contact clients, +using a defined protocol. CalDAV and CardDAV are good protocols, +covering lots of features and use cases, but it is quite hard to +implement fully.
+Some calendar servers have been created to follow the CalDAV and +CardDAV RFCs as much as possible: Davical, Baïkal and Darwin Calendar Server, for +example, are much more respectful of CalDAV and CardDAV and can be used +with many clients. They are very good choices if you want to develop and +test new CalDAV clients, or if you have a possibly heterogeneous list of +user agents.
+Even if it tries it best to follow the RFCs, Radicale does not and +will not blindly implement the CalDAV and CardDAV +standards. It is mainly designed to support the CalDAV and CardDAV +implementations of different clients.
+Simple ¶
+Radicale is designed to be simple to install, simple to configure, +simple to use.
+The installation is very easy, particularly with Linux: one +dependency, no superuser rights needed, no configuration required, no +database. Installing and launching the main script out-of-the-box, as a +normal user, are often the only steps to have a simple remote calendar +and contact access.
+Contrary to other servers that are often complicated, require high +privileges or need a strong configuration, the Radicale Server can +(sometimes, if not often) be launched in a couple of minutes, if you +follow the tutorial.
+Lazy ¶
+The CalDAV RFC defines what must be done, what can be done and what +cannot be done. Many violations of the protocol are totally defined and +behaviors are given in such cases.
+Radicale often assumes that the clients are perfect and that protocol +violations do not exist. That is why most of the errors in client +requests have undetermined consequences for the lazy server that can +reply good answers, bad answers, or even no answer.
+History ¶
+Radicale has been started as a (free topic) stupid school project +replacing another (assigned topic) even more stupid school project.
+At the beginning, it was just a proof-of-concept. The main goal was +to write a small, dirty and simple CalDAV server working with Lightning, +using no external libraries. That's how we created a piece of code +that's (quite) easy to understand, to use and to hack.
+The first +lines have been added to the SVN (!) repository as I was drinking +(many) beers at the very end of 2008 (Python 2.6 and 3.0 were just +released). It's now packaged for a growing number of Linux +distributions.
+And that was fun going from here to there thanks to you!
+