+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!
+When everything works, you can get a client and start creating calendars and
+address books. The server only binds to localhost (is
+not reachable over the network) and you can log in with
+any username and password. If Radicale fits your needs, it may be time
+for some basic configuration.
+Follow one of the chapters below depending on your operating
+system.
+
+Linux / *BSD
+First, make sure that python 3.5 or later
+(python ≥ 3.6 is recommended) and pip
+are installed. On most distributions it should be enough to install the
+package python3-pip
.
+Then open a console and type:
+# Run the following command as root or
+# add the --user argument to only install for the current user
+$ python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
+$ python3 -m radicale --storage-filesystem-folder=~/.var/lib/radicale/collections
+Victory! Open http://localhost:5232 in your browser!
+You can log in with any username and password.
+
+
+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:
+python -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
+python -m radicale --storage-filesystem-folder=~/radicale/collections
+Victory! Open http://localhost:5232 in your browser!
+You can log in with any username and password.
+
+
+
+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 Radicale doesn't check usernames or
+passwords. If the server is reachable over a network, you should change
+this.
+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:
+# Create a new htpasswd file with the user "user1"
+$ htpasswd -c /path/to/users user1
+New password:
+Re-type new password:
+# Add another user
+$ htpasswd /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
+# encryption method used in the htpasswd file
+htpasswd_encryption = md5
+
+
+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 can't 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 should 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
+Create the radicale user and group for the Radicale
+service. (Run
+useradd --system --user-group --home-dir / --shell /sbin/nologin radicale
+as root.) The storage folder must be writable by
+radicale. (Run
+mkdir -p /var/lib/radicale/collections && chown -R radicale:radicale /var/lib/radicale/collections
+as root.)
+
+Security: The storage should not be readable by
+others. (Run chmod -R o= /var/lib/radicale/collections
as
+root.)
+
+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/collections
+
+[Install]
+WantedBy=multi-user.target
+Radicale will load the configuration file from
+/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
+Radicale will load the configuration file from
+~/.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:
-m radicale --config C:\Path\To\Config
+
+- I/O redirection
+
+- Error:
C:\Path\To\Radicale.log
+
+
+
+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:
+location /radicale/ { # The trailing / is important!
+ proxy_pass http://localhost:5232/; # The / is important!
+ proxy_set_header X-Script-Name /radicale;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Host $http_host;
+ proxy_pass_header Authorization;
+}
+Example Caddy configuration with basicauth from
+Caddy:
+handle_path /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
+RewriteRule ^/radicale$ /radicale/ [R,L]
+
+<Location "/radicale/">
+ ProxyPass http://localhost:5232/ retry=0
+ ProxyPassReverse http://localhost:5232/
+ RequestHeader set X-Script-Name /radicale
+ RequestHeader set X-Forwarded-Port "%{SERVER_PORT}s"
+ RequestHeader unset X-Forwarded-Proto
+ <If "%{HTTPS} =~ /on/">
+ RequestHeader set X-Forwarded-Proto "https"
+ </If>
+</Location>
+Example Apache .htaccess configuration:
+DirectoryIndex disabled
+RewriteEngine On
+RewriteRule ^(.*)$ http://localhost:5232/$1 [P,L]
+
+# Set to directory of .htaccess file:
+RequestHeader set X-Script-Name /radicale
+RequestHeader set X-Forwarded-Port "%{SERVER_PORT}s"
+RequestHeader unset X-Forwarded-Proto
+<If "%{HTTPS} =~ /on/">
+RequestHeader set X-Forwarded-Proto "https"
+</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 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 Apache configuration:
+RewriteEngine On
+RewriteRule ^/radicale$ /radicale/ [R,L]
+
+<Location "/radicale/">
+ AuthType Basic
+ AuthName "Radicale - Password Required"
+ AuthUserFile "/etc/radicale/htpasswd"
+ Require valid-user
+
+ ProxyPass http://localhost:5232/ retry=0
+ ProxyPassReverse http://localhost:5232/
+ RequestHeader set X-Script-Name /radicale
+ RequestHeader set X-Remote-User expr=%{REMOTE_USER}
+</Location>
+Example Apache .htaccess configuration:
+DirectoryIndex disabled
+RewriteEngine On
+RewriteRule ^(.*)$ http://localhost:5232/$1 [P,L]
+
+AuthType Basic
+AuthName "Radicale - Password Required"
+AuthUserFile "/etc/radicale/htpasswd"
+Require valid-user
+
+# Set to directory of .htaccess file:
+RequestHeader set X-Script-Name /radicale
+RequestHeader set X-Remote-User expr=%{REMOTE_USER}
+
+Security: Untrusted clients should not be able to
+access the Radicale server directly. Otherwise, they can authenticate as
+any user.
+
+
+
+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 have 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, the
+values don't 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're using the Let's Encrypt's 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;
+ proxy_ssl_trusted_certificate /path/to/server_cert.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
. Radicale uses the
+username provided by the WSGI server and disables authentication over
+HTTP.
+
+
+
+Versioning 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 by running git init
+in the file system folder. Internal files of Radicale can be excluded by
+creating the file .gitignore
with the following
+content:
+.Radicale.cache
+.Radicale.lock
+.Radicale.tmp-*
+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.
+For the hook to not cause errors either git user
+details need to be set and match the owner of the collections directory
+or the repository needs to be marked as safe.
+When using the systemd unit file from the Running as a service section this
+cannot be done via a .gitconfig
file in
+the users home directory, as Radicale won't have read permissions!
+In /var/lib/radicale/collections/.git
run:
+git config user.name "radicale"
+git config user.email "radicale@example.com"
+
+