diff --git a/v3.html b/v3.html index cd45bf2c..a0ea46e7 100644 --- a/v3.html +++ b/v3.html @@ -286,22 +286,25 @@ structure.

Installation

-

Radicale is really easy to install (for testing purposes) and works -out-of-the-box.

-
# Run as normal user
-python3 -m pip install --user --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
-python3 -m radicale --logging-level info --storage-filesystem-folder=~/.var/lib/radicale/collections
-

When the server is launched, open http://localhost:5232 in your browser! -You can login with any username and password.

-

Want more? Check the tutorials and the documentation.

-

Instead of downloading from PyPI look for packages provided by used -distribution, they contain -also startup scripts to run daemonized.

+

Check

+ +

Hint: instead of downloading from PyPI look for packages provided by +used distribution, they +contain also startup scripts to run daemonized.

What's New?

-

Read the changelog -on GitHub.

+

Read the Changelog +on GitHub.

@@ -324,19 +327,40 @@ system.

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.

-

Then open a console and type:

-
# Run the following command to only install for the current user
-#  data is also stored for the current user only
-python3 -m pip install --user --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
-python3 -m radicale --storage-filesystem-folder=~/.var/lib/radicale/collections
-

Alternative one can install as root or system user

-
# Run the following command as root
-# or non-root system user (can require --user in case of dependencies are not available system-wide)
-#  requires existence of and write permissions to /var/lib/radicale/collections
-python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
-python3 -m radicale --storage-filesystem-folder=/var/lib/radicale/collections
+
+
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
+
+
+
as system user (or as root)
+

Alternative one can install and run as system user or as root (not +recommended)

+
# Run the following command as root (not required)
+# or non-root system user (can require --user in case of 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, data is stored in a system folder

+
# 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
+
+
+
common

Victory! Open http://localhost:5232 in your browser! -You can log in with any username and password.

+You can log in with any username and password (no authentication is +required as long as not proper configured - INSECURE).

+

Windows

@@ -345,10 +369,11 @@ 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
+
python -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
+python -m radicale --storage-filesystem-folder=~/radicale/collections --auth-type none

Victory! Open http://localhost:5232 in your browser! -You can log in with any username and password.

+You can log in with any username and password (no authentication is +required as long as not proper configured - INSECURE).

@@ -382,19 +407,19 @@ without supporting SHA-256 or SHA-512 (e.g. Ubuntu LTS 22), in this case use '-B' for "bcrypt" hash method or stay with insecure MD5 (default) or SHA-1 ('-s').

Note that support of SHA-256 or 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:
+
# 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
+
[auth]
+type = htpasswd
+htpasswd_filename = /path/to/users
+htpasswd_encryption = autodetect
The simple but insecure way
@@ -403,11 +428,11 @@ 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
+
[auth]
+type = htpasswd
+htpasswd_filename = /path/to/users
+# encryption method used in the htpasswd file
+htpasswd_encryption = plain
@@ -415,16 +440,16 @@ user2:password2

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
+
[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
+
[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 @@ -438,16 +463,16 @@ 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
+
[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
@@ -473,69 +498,69 @@ 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/ /var/cache/radicale/
-
-[Install]
-WantedBy=multi-user.target
+
[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/ /var/cache/radicale/
+
+[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
+
# 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
+
[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
+
# 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"

@@ -600,28 +625,28 @@ below.

}

Example Apache configuration:

See for latest examples: https://github.com/Kozea/Radicale/tree/master/contrib/apache/

-
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    set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
-</Location>
+
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    set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
+</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>
+
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" )
 
@@ -667,33 +692,33 @@ and disables HTTP authentication.

} }

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>
+
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}
+
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 @@ -710,22 +735,22 @@ 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
+
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
+
[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
+
[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/;
@@ -743,15 +768,15 @@ look similar to this:

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
+
[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
+
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 @@ -767,36 +792,36 @@ 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
+
## 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\"")
+
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
+
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 @@ -816,17 +841,17 @@ logging.

Radicale can be configured with a configuration file or with command line arguments.

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
+
[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 @@ -837,27 +862,27 @@ configuration files can be separated by : (resp. 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
+
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.

One can also use command line options in startup scripts using 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[@]}
+
## 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[@]}

In the following, all configuration categories and options are described.

@@ -961,20 +986,31 @@ htpasswd file to store usernames and passwords.

remote_user : Takes the username from the REMOTE_USER environment variable and disables HTTP authentication. This can be used to provide the username from a WSGI -server.

+server which authenticated the client upfront. Required to validate, +otherwise client can supply the header itself which is unconditionally +trusted then.

http_x_remote_user : Takes the username from the X-Remote-User HTTP header and disables HTTP authentication. -This can be used to provide the username from a reverse proxy.

+This can be used to provide the username from a reverse proxy which +authenticated the client upfront. Required to validate, otherwise client +can supply the header itself which is unconditionally trusted then.

ldap (>= 3.3.0) : Use a LDAP or AD server to -authenticate users.

+authenticate users by relaying credentials from client and handle +result.

dovecot (>= 3.3.1) : Use a Dovecot server to -authenticate users.

+authenticate users by relaying credentials from client and handle +result.

imap (>= 3.4.1) : Use an IMAP server to -authenticate users.

+authenticate users by relaying credentials from client and handle +result.

oauth2 (>= 3.5.0) : Use an OAuth2 server to -authenticate users.

+authenticate users by relaying credentials from client and handle +result. Oauth2 authentication (SSO) directly on client is not supported. +Use herefore http_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.

+authenticate users by relaying credentials from client and handle +result..

Default: none (< 3.5.0) denyall (>= 3.5.0)

@@ -1132,6 +1168,15 @@ alikes, 'groupMembership' on Novell eDirectory, ...

the server certificate

Default:

+
+
ldap_ignore_attribute_create_modify_timestamp
+

(>= 3.5.1)

+

Add modifyTimestamp and createTimestamp to the exclusion list of +internal ldap3 client so that these schema attributes are not checked. +This is needed at least for Authentik LDAP server as not providing these +both attributes.

+

Default: false

+
dovecot_connection_type = AF_UNIX

(>= 3.4.1)

@@ -1355,7 +1400,10 @@ example.

Default:

Supported placeholders:

    -
  • %(user): logged-in user
  • +
  • %(user)s: logged-in user
  • +
  • %(cwd)s: current working directory (>= +3.5.1)
  • +
  • %(path)s: full path of item (>= 3.5.1)

Command will be executed with base directory defined in filesystem_folder (see above)

@@ -1453,7 +1501,7 @@ books and calendars.

In this section additional HTTP headers that are sent to clients can be specified.

An example to relax the same-origin policy:

-
Access-Control-Allow-Origin = *
+
Access-Control-Allow-Origin = *

hook

@@ -1592,47 +1640,47 @@ InfCloud.

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>'
+
$ 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>'
+
$ 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'
+
curl -u user -X DELETE 'http://localhost:5232/user/calendar'

Note: requires config/option permit_delete_collection = True

@@ -1648,24 +1696,24 @@ to calendars and address books outside the home directory of users collections and will not show them to the user. 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
+
# 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 @@ -1752,10 +1800,10 @@ system. The storage is locked with exclusive access while the

Linux shell scripts

Use the flock utility.

-
# Exclusive
-$ flock --exclusive /path/to/storage/.Radicale.lock COMMAND
-# Shared
-$ flock --shared /path/to/storage/.Radicale.lock COMMAND
+
# Exclusive
+$ flock --exclusive /path/to/storage/.Radicale.lock COMMAND
+# Shared
+$ flock --shared /path/to/storage/.Radicale.lock COMMAND
Linux and MacOS
@@ -1780,11 +1828,11 @@ folder in the file system storage (e.g. clients that the collection is a calendar, you have to create the file .Radicale.props with the following content in the folder:

-
{"tag": "VCALENDAR"}
+
{"tag": "VCALENDAR"}

The calendar is now available at the URL path /user/calendar. For address books the file must contain:

-
{"tag": "VADDRESSBOOK"}
+
{"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 @@ -1914,49 +1962,49 @@ password.

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
-
-setup(name="radicale_static_password_auth",
-      packages=["radicale_static_password_auth"])
+
#!/usr/bin/env python3
+
+from distutils.core import setup
+
+setup(name="radicale_static_password_auth",
+      packages=["radicale_static_password_auth"])

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
-
-PLUGIN_CONFIG_SCHEMA = {"auth": {
-    "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
-        static_password = self.configuration.get("auth", "password")
-        # Check authentication
-        logger.info("Login attempt by %r with password %r",
-                    login, password)
-        if password == static_password:
-            return login
-        return ""
+
from radicale.auth import BaseAuth
+from radicale.log import logger
+
+PLUGIN_CONFIG_SCHEMA = {"auth": {
+    "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
+        static_password = self.configuration.get("auth", "password")
+        # Check authentication
+        logger.info("Login attempt by %r with password %r",
+                    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 .
+
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
+
[auth]
+type = radicale_static_password_auth
+password = secret

You can uninstall the module with:

-
python3 -m pip uninstall radicale_static_password_auth
+
python3 -m pip uninstall radicale_static_password_auth

Authentication plugins

@@ -2015,14 +2063,14 @@ you want to add new features, fix bugs or update the documentation.

PyPI

Radicale is available on PyPI. To install, just type as superuser:

-
python3 -m pip install --upgrade radicale
+
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
+
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.