diff --git a/master.html b/master.html index fc9b4e5c..12f9bffa 100644 --- a/master.html +++ b/master.html @@ -461,8 +461,15 @@ user2:password2 <Location "/radicale/"> ProxyPass http://localhost:5232/ retry=0 ProxyPassReverse http://localhost:5232/ - RequestHeader set X-Script-Name /radicale/ + RequestHeader set X-Script-Name /radicale </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
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.
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}
@@ -500,14 +520,14 @@ user2:password2Security: Untrusted clients should not be able to access the Radicale server directly. Otherwise, they can authenticate as any user.
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
$ 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
Example nginx configuration:
location /radicale/ {
proxy_pass https://localhost:5232/;
@@ -525,14 +545,14 @@ user2:password2
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
+[uwsgi]
+http-socket = 127.0.0.1:5232
+processes = 8
+plugin = python3
+module = radicale
+env = RADICALE_CONFIG=/etc/radicale/config
Example Gunicorn configuration:
-
+
Manage user accounts with the WSGI server ¶
Set the configuration option type
in the auth
section to remote_user
. Radicale uses the user name provided by the WSGI server and disables authentication over HTTP.
@@ -547,7 +567,7 @@ user2:password2
.Radicale.tmp-*
The configuration option hook
in the storage
section must be set to the following command:
The command gets executed after every change to the storage and commits the changes into the git repository.
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 = md5
-
-[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 = md5
+
+[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 --htpasswd-filename ~/.config/radicale/users --htpasswd-encryption md5
python3 -m radicale --server-hosts 0.0.0.0:5232,[::]:5232 --auth-type htpasswd --htpasswd-filename ~/.config/radicale/users --htpasswd-encryption md5
Add the argument --config ""
to stop Radicale from loading the default configuration files. Run python3 -m radicale --help
for more information.
In the following, all configuration categories and options are described.
In this section additional HTTP headers that are sent to clients can be specified.
An example to relax the same-origin policy:
- +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>'
$ 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:
- +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 to calendars and address books outside the home directory of users (that's /USERNAME/
) is granted, clients won't detect these 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 user name)
-[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 user name)
+[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 user name and the path of the collection. Permissions from the first matching section are used. If no section matches, access gets denied.
The user name 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.
Use the flock utility.
- +To create a new collection, you have to create the corresponding folder in the file system storage (e.g. collection-root/user/calendar
). To tell Radicale and clients that the collection is a calendar, you have to create the file .Radicale.props
with the following content in the folder:
The calendar is now available at the URL path /user/calendar
. For address books the file must contain:
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.
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
-
-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
:
To make use this great creation in Radicale, set the configuration option type
in the auth
section to radicale_static_password_auth
:
You can uninstall the module with:
- +