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!
-