diff --git a/v3.html b/v3.html index 5ccd7956..f0c9f5dc 100644 --- a/v3.html +++ b/v3.html @@ -182,23 +182,18 @@ with the WSGI server
Radicale is really easy to install and works out-of-the-box.
-python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz
-python3 -m radicale --logging-level info --storage-filesystem-folder=~/.var/lib/radicale/collections
python3 -m pip install --upgrade radicale
+python3 -m radicale --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.
First, make sure that python 3.8 or later and
-pip are installed. On most distributions it should be
-enough to install the package python3-pip
.
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 pip install --upgrade radicale
$ 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.
@@ -325,7 +323,7 @@ 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 pip install --upgrade radicale
python -m radicale --storage-filesystem-folder=~/radicale/collections python
Victory! Open http://localhost:5232 in your browser!
You can log in with any username and password.
@@ -357,19 +355,20 @@ file.
The secure way ¶
The users
file can be created and managed with htpasswd:
-# Create a new htpasswd file with the user "user1" using SHA-512 as hash method
-$ htpasswd -5 -c /path/to/users user1
+# 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 -5 /path/to/users user2
+$ 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
-htpasswd_encryption = autodetect
+# encryption method used in the htpasswd file
+htpasswd_encryption = md5
The simple but insecure way ¶
@@ -432,8 +431,6 @@ 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. (Run
useradd --system --user-group --home-dir / --shell /sbin/nologin radicale
@@ -562,11 +559,15 @@ below.
proxy_set_header Host $http_host;
proxy_pass_header Authorization;
}
-Example Caddy configuration:
-handle_path /radicale/* {
- uri strip_prefix /radicale
+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-Script-Name "/radicale"
+ header_up +X-remote-user "{http.auth.user.id}"
}
}
Example Apache configuration:
@@ -595,19 +596,6 @@ below.
<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 @@ -628,45 +616,34 @@ and disables HTTP authentication.
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 set X-Script-Name /radicale
- RequestHeader set X-Remote-User expr=%{REMOTE_USER}
- RequestHeader</Location>
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 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
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 @@ -681,22 +658,16 @@ 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
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 = /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/; @@ -715,15 +686,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
.Radicale.tmp-*type
in the @@ -746,18 +717,9 @@ content:The configuration option
-hook
in thestorage
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.
-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"
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 = 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
@@ -788,9 +750,9 @@ 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 md5
Add the argument --config ""
to stop Radicale from
loading the default configuration files. Run
python3 -m radicale --help
for more information.
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.
ldap
: Use a LDAP or AD server to authenticate
-users.
Default: none
bcrypt
: This uses a modified version of the Blowfish
stream cipher. It's very secure. The installation of
-bcrypt is required for this.
md5
: This uses an iterated MD5 digest of the password
-with a salt (nowadays insecure).
sha256
: This uses an iterated SHA-256 digest of the
-password with a salt.
sha512
: This uses an iterated SHA-512 digest of the
-password with a salt.
autodetect
: This selects autodetection of method per
-entry.
Default: autodetect
md5
: This uses an iterated md5 digest of the password
+with a salt.
Default: md5
Message displayed in the client when a password is needed.
Default: Radicale - Password Required
The URI to the ldap server
-Default: ldap://localhost
LDAP base DN of the ldap server. This parameter must be provided if -auth type is ldap.
-Default:
-The DN of a ldap user with read access to get the user accounts. This -parameter must be provided if auth type is ldap.
-Default:
-The password of the ldap_reader_dn. This parameter must be provided -if auth type is ldap.
-Default:
-The search filter to find the user DN to authenticate by the -username. User '{0}' as placeholder for the user name.
-Default: (cn={0})
Load the ldap groups of the authenticated user. These groups can be -used later on to define rights. This also gives you access to the group -calendars, if they exist.
-Default: False
-Use ssl on the ldap connection
-Default: False
-The certifikat verification mode. NONE, OPTIONAL or REQUIRED
-Default: REQUIRED
-The path to the CA file in pem format which is used to certificate -the server certificate
-Default:
-Сonvert username to lowercase, must be true for case-insensitive auth -providers like ldap, kerberos
-Default: False
Strip domain from username
-Default: False
File for the rights backend from_file
. See the Rights section.
(New since 3.1.9)
-Global control of permission to delete complete collection (default: -True)
-If False it can be permitted by permissions per section with: D If -True it can be forbidden by permissions per section with: d
-(New since 3.3.0)
-Global control of permission to overwrite complete collection -(default: True)
-If False it can be permitted by permissions per section with: O If -True it can be forbidden by permissions per section with: o
-Default: 2592000
Skip broken item instead of triggering an exception
-Default: True
Command that is run after changes to storage. Take a look at the Versioning with Git tutorial for an example.
Default:
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:
-Don't include passwords in logs.
Default: True
Log bad PUT request content (for further diagnostics)
-Default: False
Log backtrace on level=debug
-Default: False
Log request on level=debug
-Default: False
Log request on level=debug
-Default: False
Log response on level=debug
-Default: False
Log rights rule which doesn't match on level=debug
-Default: False
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 = *
Hook binding for event changes and deletion notifications.
-Available types:
-none
: Disabled. Nothing will be notified.
rabbitmq
: Push the message to the rabbitmq server.
Default: none
Access-Control-Allow-Origin = *
End-point address for rabbitmq server. Ex: -amqp://user:password@localhost:5672/
-Default:
-RabbitMQ topic to publish message.
-Default:
-RabbitMQ queue type for the topic.
-Default: classic
-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
-Radicale has been tested with:
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.
GNOME Calendar and Contacts do not +support adding WebDAV calendars and address books directly, but you can +add them in 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.
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'
Note: requires config/option
-permit_delete_collection = True
curl -u user -X DELETE 'http://localhost:5232/user/calendar'
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
@@ -1373,14 +1135,6 @@ expensive search requests)
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
.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 @@ -1594,49 +1348,49 @@ password.
modules is Distutils. For a minimal setup create the filesetup.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
#!/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 ""
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 .
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
Want to say something? Join our IRC room: ##kozea
on
+Freenode.
Found a bug? Want a new feature? Report a new issue on the Radicale @@ -1686,7 +1445,7 @@ you want to add new features, fix bugs or update the documentation.
To change or complement the documentation create a pull request to DOCUMENTATION.md.
+To change or complement the documentation create a pull request to DOCUMENTATION.md.
Radicale is available on PyPI. To install, just type as superuser:
-python3 -m pip install --upgrade radicale
python3 -m pip install --upgrade radicale
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.