1
0
Fork 0
mirror of https://github.com/Kozea/Radicale.git synced 2025-06-29 16:55:32 +00:00

Merge pull request #607 from Unrud/doc

Documentation for Radicale 2.0.0 (WIP)
This commit is contained in:
Guillaume Ayoub 2017-05-27 11:18:39 +02:00 committed by GitHub
commit cc341fb090
16 changed files with 722 additions and 82 deletions

49
1to2.md
View file

@ -36,44 +36,35 @@ work, Radicale won't be able to read your previous data.**
There's now only one way to store data in Radicale: collections are stored as
folders and events / contacts are stored in files. This new storage is close to
the `multifilesystem`, but **it's now thread-safe, with atomic writes and file
locks**.
locks**. Other storage types can be used by creating
[plugins]({{ site.baseurl }}/plugins/).
Migrating your data can be done with tool called
[transplant](https://github.com/Kozea/transplant/blob/master/transplant.py)
that will copy your collections from one server to another using
CalDAV / CardDAV requests. Following these simple steps will help you migrate
your data:
- Stop Radicale 1.x.x,
- edit your configuration to only listen to `http://localhost:5232`,
- remove authentication,
- restart the 1.x.x server,
- download Radicale 2.0.x and go into the downloaded folder,
- launch Radicale 2.0.x with
`python3 radicale.py --config=/dev/null --hosts=localhost:5233 --storage-filesystem-folder=~/.local/share/radicale/`,
- download transplant and go into the downloaded folder,
- launch transplant with `python3 transplant http://localhost:5232 http://localhost:5233`,
- you're done!
This migration should work at least with simple configurations of Radicale 1.x.x
on Linux and macOS. Please adapt these steps carefully if you're on Windows or
if you're using a more complex configuration.
Other storage types can be used by creating [plugins](/plugins/). These storage
types can reuse the current storage class to extend it (for example to add
versioning) or can be totally different from it (yes, don't worry, you can
write your own storage plugin using a DataBase®™ if you want).
To migrate data to Radicale 2.0.x the command line argument
``--export-storage`` was added to Radicale 1.1.3.
Start Radicale 1.x.x as you would normally do, but add the argument
``--export-storage path/to/empty/folder``. Radicale will export the storage
into the specified folder. This folder can be directly used with the
default storage backend of Radicale 2.0.x.
### Authentication
**Radicale 2.0.x only provides htpasswd authentication out-of-the-box.** Other
authentication methods can be added by creating or using [plugins](/plugins/).
authentication methods can be added by creating or using
[plugins]({{ site.baseurl }}/plugins/).
### Rights
In Radicale 2.0.x, rights are managed using regex-based rules based on the
login of the authenticated user and the URL of the resource. Default
configurations are built in for common cases, you'll find more about this on
the [Authentication & Rights](/rights/) page.
the [Authentication & Rights]({{ site.baseurl }}/rights/) page.
Other rights managers can be added by creating [plugins](/plugins/).
Other rights managers can be added by creating
[plugins]({{ site.baseurl }}/plugins/).
### Versioning
Support for versioning with **git** was removed from Radicale 2.0.x.
Instead, the configuration option ``hook`` in the ``storage`` section was added,
the [Collection Versioning]({{ site.baseurl }}/versioning/) page explains its
usage for version control.

View file

@ -17,7 +17,7 @@ configure. As a consequence, it requires few software dependencies and is
pre-configured 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.
(Linux, \*BSD, macOS) and Windows. It is free and open-source software.
## What Radicale Will Never Be

View file

@ -3,3 +3,253 @@ layout: page
title: Configuration
permalink: /configuration/
---
Radicale can be configured with a configuration file or with
command line arguments.
An example configuration file looks like:
```ini
[server]
hosts = 0.0.0.0:5232 # Bind all addresses
[auth]
type = htpasswd
htpasswd_filename = /path/to/users
htpasswd_encryption = bcrypt
[storage]
filesystem_folder = ~/.var/lib/radicale/collections
```
Radicale tries to load configuration files from */etc/radicale/config*,
*~/.config/radicale/config* and the ``RADICALE_CONFIG`` environment variable.
This behaviour can be overwritten by specifying a path with the
``--config /path/to/config`` command line argument.
The same example configuration via command line arguments looks like:
```sh
python3 -m radicale --config "" --server-hosts 0.0.0.0:5232 --auth-type htpasswd --htpasswd-filename /path/to/htpasswd --htpasswd-encryption bcrypt
```
The ``--config ""`` argument is required to stop Radicale from trying
to load configuration files. Run ``python3 -m radicale --help`` for more information.
In the following, all configuration categories and options are described.
## server
Most configuration options in this category are only relevant in standalone
mode. All options beside ``max_content_length`` and ``realm`` are ignored,
when Radicale runs via WSGI.
### hosts
A comma separated list of addresses that the server will bind to.
Default: ``127.0.0.1:5555``
### daemon
Daemonize the Radicale process. It does not reset the umask or double fork.
Default: ``False``
### pid
If daemon mode is enabled, Radicale will write its PID to this file.
Default:
### max_connections
The maximum number of parallel connections. Set to ``0`` to disable the limit.
Default: ``20``
### max_content_length
The maximum size of the request body. (bytes)
Default: ``10000000``
### timeout
Socket timeout. (seconds)
Default: ``10``
### ssl
Enable transport layer encryption.
Default: ``False``
### certificate
Path of the SSL certifcate.
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``
### protocol
SSL protocol used. See python's ssl module for available values.
Default: ``PROTOCOL_TLSv1_2``
### ciphers
Available ciphers for SSL. See python's ssl module for available ciphers.
Default:
### dns_lookup
Reverse DNS to resolve client address in logs.
Default: ``True``
### realm
Message displayed in the client when a password is needed.
Default: ``Radicale - Password Required``
## 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 backends:
`None`
: Just allows all usernames and passwords.
`htpasswd`
: Use an [Apache htpasswd file](https://httpd.apache.org/docs/current/programs/htpasswd.html) to store
usernames and passwords.
Default: ``None``
### htpasswd_filename
Path to the htpasswd file.
Default:
### htpasswd_encryption
The encryption method that is used in the htpasswd file. Use the
[htpasswd](https://httpd.apache.org/docs/current/programs/htpasswd.html)
or similar to generate this files.
Available methods:
`plain`
: Passwords are stored in plaintext. This is obviously not secure!
The htpasswd file for this can be created by hand and looks like:
```htpasswd
user1:password1
user2:password2
```
`bcrypt`
: This uses a modified version of the Blowfish stream cipher. It's very secure.
The **passlib** python module is required for this. Additionally you may need
one of the following python modules: **bcrypt**, **py-bcrypt** or **bcryptor**.
`md5`
: This uses an iterated md5 digest of the password with a salt.
The **passlib** python module is required for this.
`sha1`
: Passwords are stored as SHA1 hashes. It's insecure!
`ssha`
: Passwords are stored as salted SHA1 hashes. It's insecure!
`crypt`
: This uses UNIX [crypt(3)](http://man7.org/linux/man-pages/man3/crypt.3.html).
It's insecure!
Default: ``bcrypt``
## rights
### type
The backend that is used to check the access rights of collections.
Available backends:
`None`
: Everyone can read and write everything.
`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
File for the rights backend ``from_file``. See the
[Rights]({{ site.baseurl }}/logging/) page.
## storage
### type
The backend that is used to store data.
Available backends:
`multifilesystem`
: Stores the data in the filesystem.
Default: ``multifilesystem``
### filesystem_fsync
Sync all changes to disk during requests. (This can impair performance.)
Disabling it increases the risk of data loss, when the system crashes or
power fails!
Default: ``True``
### hook
Command that is run after changes to storage. Take a look at the
[Versioning]({{ site.baseurl }}/versioning/) page for an example.
Default:
## logging
## debug
Set the default logging level to debug.
Default: ``False``
### full_environment
Log all environment variables (including those set in the shell).
Default: ``False``
### mask_passwords
Don't include passwords in logs.
Default: ``True``
### config
Logging configuration file. See the [Logging]({{ site.baseurl }}/logging/) page.
Default:
## headers
In this section additional HTTP headers that are sent to clients can be
specified.
An example to relax the same-origin policy:
```ini
Access-Control-Allow-Origin = *
```

View file

@ -7,14 +7,16 @@ permalink: /documentation/
This documentation page is written for version 2.0.x. If you want to update
Radicale from 1.x.x to 2.0.x, please follow our [migration guide]({{ site.baseurl }}/1to2/).
## Install
## Install and set up
You're new to Radicale and you want to know how to use it? Welcome aboard!
- [What is Radicale?]({{ site.baseurl }}/about/)
- [A really simple 5-minute tutorial.]({{ site.baseurl }}/tutorial/)
- [A simple but solid installation for a personal use.]({{ site.baseurl }}/installation/)
- [A production-ready installation.]({{ site.baseurl }}/production/)
- [A simple but solid setup.]({{ site.baseurl }}/setup/)
- [Run behind a reverse proxy.]({{ site.baseurl }}/proxy/)
- [Run with a WSGI server.]({{ site.baseurl }}/wsgi/)
- [Track all changes to calendars and address books with Git.]({{ site.baseurl }}/versioning/)
## Use
@ -23,7 +25,7 @@ You're new to Radicale and you want to know how to use it? Welcome aboard!
## Configure
Now that you have Radicale running, let's see what we can configure to make it
fit our needs.
fit your needs.
- [What can I configure?]({{ site.baseurl }}/configuration/)
- [Authentication & Rights.]({{ site.baseurl }}/rights/)
@ -38,5 +40,4 @@ and simple piece of code, it may be the perfect project to start hacking!
- [How does Radicale work?]({{ site.baseurl }}/architecture/)
- [Plugins.]({{ site.baseurl }}/plugins/)
- [Debugging.]({{ site.baseurl }}/debugging/)
- [Collection versioning.]({{ site.baseurl }}/versioning/)
- [Adding or fixing documentation.]({{ site.baseurl }}/edit/)

View file

@ -9,13 +9,12 @@ permalink: /download/
Radicale is [available on PyPI](http://pypi.python.org/pypi/Radicale/). To
install, just type as superuser:
pip install 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]({{ site.github.repository_url }}), or clone it
thanks to:
[git repository on GitHub]({{ site.github.repository_url }}), or clone it:
git clone git://github.com/Kozea/Radicale.git

View file

@ -3,3 +3,6 @@ layout: page
title: Editing the Documentation
permalink: /edit/
---
To change or complement the documentation create a pull requests to
https://github.com/Kozea/Radicale/tree/gh-pages.

View file

@ -1,5 +0,0 @@
---
layout: page
title: Simple Installation
permalink: /installation/
---

View file

@ -3,3 +3,46 @@ layout: page
title: Logging
permalink: /logging/
---
Radicale logs to ``stderr``. The verbosity of the log output can be controlled
with ``--debug`` command line argument or the ``debug`` configuration option in
the ``logging`` section.
This is the recommended configuration for use with modern init systems
(like **systemd**) or if you just test Radicale in a terminal.
You can configure Radicale to write its logging output to files (and even
rotate them).
This is useful if the process daemonizes or if your chosen method of running
Radicale doesn't handle logging output.
A logging configuration file can be specified in the ``config`` configuration
option in the ``logging`` section. The file format is explained in the
[Python Logging Module](https://docs.python.org/3/library/logging.config.html#configuration-file-format).
An example configuration to write the log output to the file */var/log/radicale/log*:
```ini
[loggers]
keys = root
[handlers]
keys = file
[formatters]
keys = full
[logger_root]
level = WARNING # Change this to DEBUG or INFO for higher verbosity.
handlers = file
[handler_file]
class = FileHandler
args = ('/var/log/radicale/log',) # Specify the output file here.
formatter = full
[formatter_full]
format = %(asctime)s - [%(thread)x] %(levelname)s: %(message)s
```
You can specify multiple **logger**, **handler** and **formatter** if you want
to have multiple simultaneous log outputs.

View file

@ -3,3 +3,67 @@ layout: page
title: Plugins
permalink: /plugins/
---
Radicale can be extended by plugins for authentication, rights management and
storage. Plugins are **python** modules.
## Getting started
To get started we walk through the creation of a simple authentication
plugin, that accepts login attempts if the username and password are equal.
The easiest way to develop and install **python** modules is
[Distutils](https://docs.python.org/3/distutils/setupscript.html).
For a minimal setup create the file **setup.py** with the following content
in an empty folder:
```python
#!/usr/bin/env python3
from distutils.core import setup
setup(packages=["silly_auth_plugin"])
```
In the same folder create the sub-folder **silly_auth_plugin**. The folder
must have the same name as specified in ``packages`` above.
Create the file **\_\_init\_\_.py** in the **silly_auth_plugin** folder with the
following content:
```python
from radicale.auth import BaseAuth
class Auth(BaseAuth):
def is_authenticated(self, user, password):
self.logger.info("Login attempt by '%s' with password '%s'",
user, password)
return user == password
```
Install the python module by running the following command in the same folder
as **setup.py**:
```sh
python3 -m pip install --upgrade .
```
To make use this great creation in Radicale, set the configuration option
``type`` in the ``auth`` section to ``silly_auth_plugin``.
## 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.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.auth.BaseAuth``. Take a look at the file *radicale/rights.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.auth.BaseStorage``. Take a look at the file *radicale/storage.py* in
Radicale's source code for more information.

View file

@ -1,5 +0,0 @@
---
layout: page
title: Installation for Production
permalink: /production/
---

21
proxy.md Normal file
View file

@ -0,0 +1,21 @@
---
layout: page
title: Reverse Proxy
permalink: /proxy/
---
When a everse proxy is used, the path at which Radicale is available must
be provided via the ``X-Script-Name`` header.
Example **nginx** configuration:
```
location /sub/folder/radicale {
proxy_pass localhost:5232/; # The / is important!
proxy_set_header X-Script-Name /radciale;
}
```
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.

View file

@ -3,3 +3,56 @@ layout: page
title: Authentication and Rights
permalink: /rights/
---
This page 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 mehtod is ``owner_only``. If access to calendars
and address books outside of 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:
```ini
# The user "admin" can read and write any collection.
[admin]
user: admin
collection: .*
permission: rw
# Block access for the user "user" to everything.
[block]
user: user
collection: .*
permission:
# Authenticated users can read and write their own collections.
[owner-write]
user: .+
collection: %(login)s/.*
permission: rw
# Everyone can read the root collection
[read]
user: .*
collection:
permission: r
```
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.
``%(login)s`` gets replaced by the user name and ``%(path)s`` by the path of
the collection. You can also get groups from the ``user`` regex in the
``collection`` regex with ``{0}``, ``{1}``, etc.

201
setup.md Normal file
View file

@ -0,0 +1,201 @@
---
layout: page
title: Basic Setup
permalink: /setup/
---
Installation instructions can be found on the
[Tutorial]({{ site.baseurl }}/tutorial/) page.
## Configuration
Radicale tries to load configuration files from */etc/radicale/config*,
*~/.config/radicale/config* and the ``RADICALE_CONFIG`` environment variable.
A custom path can be specified with the ``--config /path/to/config`` command
line argument.
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 on the
[Configuration]({{ site.baseurl }}/configuration/) page.
## Authentication
In it's default configuration Radicale doesn't check user names or passwords.
If the server is reachable over a network, you should change this.
First a **users** file with all user names and passwords must be created.
It can be stored in the same directory as the configuration file.
The file can be created and managed with
[htpasswd](https://httpd.apache.org/docs/current/programs/htpasswd.html):
```bash
# Create a new htpasswd file with the user "user1"
$ htpasswd -B -c /path/to/users user1
New password:
Re-type new password:
# Add another user
$ htpasswd -B /path/to/users user2
New password:
Re-type new password:
```
**bcrypt** is used to secure the passwords. Radicale required additional
dependencies for this encryption method:
```bash
$ python3 -m pip install --upgrade passlib
$ python3 -m pip install --upgrade bcrypt
```
Authentication can be enabled with the following configuration:
```ini
[auth]
type = htpasswd
htpasswd_filename = /path/to/users
htpasswd_encryption = bcrypt # encryption method used in the htpasswd file
```
## 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:
```ini
[server]
hosts = 0.0.0.0:5232
```
More addresses can be added (separated by commas).
## Storage
Data is stored in the folder */var/lib/radicale/collections*. The path can
be changed with the foloowing configuration:
```ini
[storage]
filesystem_folder = /path/to/storage
```
## 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.
```ini
[server]
max_connections = 20
max_content_length = 10000000 # 1 Megabyte
timeout = 10 # seconds
[auth]
delay = 1 # Average delay after failed login attempts in seconds
```
## 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 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
```
You may have to add addition command line arguments to Radicale for the
configuration file, etc.
To enable and manage the service run:
```bash
# 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
```
### Linux with systemd system-wide
Create the **radicale** user and group for the Radicale service.
The configuration files must be readable by this user and the storage folder
must be writable.
Create the file */etc/systemd/system/radicale.service*:
```
[Unit]
Description=A simple CalDAV (calendar) and CardDAV (contact) server
[Service]
ExecStart=/usr/bin/env python3 -m radicale
Restart=on-failure
User=radicale
[Install]
WantedBy=multi-user.target
```
You may have to add addition command line arguments to Radicale for the
configuration file, etc.
To enable and manage the service run:
```bash
# 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
```
## MacOS with launchd
*To be written.*
## Classic daemonization
Set the configuration option ``daemon`` in the section ``server`` to ``True``.
You may want to set the option ``pid`` to the path of a PID file.
After daemonization the server will not log anything. You have to configure
[Logging]({{ site.baseurl }}/tutorial/).
If you start Radicale now, it will initialize and fork into the background.
The main process exits, after the PID file is written.
## Windows with "NSSM - the Non-Sucking Service Manager"
First install [NSSM](https://nssm.cc/) 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``
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.
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.

View file

@ -8,50 +8,42 @@ You want to try Radicale but only have 5 minutes free in your calendar? Let's
go right now! You won't have the best installation ever, but it will be enough
to play a little bit with Radicale.
Follow one of the chapters below depending on your operating system.
When Radicale is launched, you can check that everything is OK by opening
[http://localhost:5232/](http://localhost:5232/) in your favourite browser:
you'll get a "Radicale works!" message.
When everything works, you can get a [client]({{ site.baseurl }}/clients/) and
start creating calendars and address books. And if Radicale fits your needs, it
may be time to [install it "The Right Way"]({{ site.baseurl }}/install/).
may be time to for [some basic configuration](/setup/).
## Linux / *BSD
Follow one of the chapters below depending on your operating system.
Installing Radicale on Linux or *BSD is often really easy.
## Linux / \*BSD
First of all, check that you have Python 3.4 or superior installed, or install
it thanks to your package manager. Then open a console and type:
First of all, make sure that **python** 3.4 or later and **pip** are
installed. On most distributions it should be enough to install the package
``python3-pip``.
$ pip3 install radicale
$ python3 -m radicale --debug --storage-filesystem-folder=~/.local/radicale
...
Radicale server ready
Then open a console and type:
## Windows
First of all: please install all the Windows updates available for your version
of Windows! (But it's already done, isn't it?)
The next step on Windows is to intall Python. Go to
[python.org](http://python.org) and download the latest version of Python. 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!
Then launch a command prompt, and type:
C:\Users\MyName> python -m pip install radicale
C:\Users\MyName> python -m radicale --debug --storage-filesystem-folder=~/radicale
...
Radicale server ready
$ python3 -m pip install --upgrade radicale
$ python3 -m radicale --config "" --storage-filesystem-folder=~/.var/lib/radicale/collections
Victory! Open [http://localhost:5232/](http://localhost:5232/) in your browser
and enjoy the "Radicale works!" message!
## macOS
## Windows
The first step is to install Python. Go to
[python.org](https://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:
C:\Users\MyName> python -m pip install --upgrade radicale
C:\Users\MyName> python -m radicale --config "" --storage-filesystem-folder=~/radicale
Victory! Open [http://localhost:5232/](http://localhost:5232/) in your browser
and enjoy the "Radicale works!" message!
## MacOS
*To be written.*

View file

@ -3,3 +3,24 @@ layout: page
title: Versioning
permalink: /versioning/
---
This page 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:
```sh
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.

11
wsgi.md Normal file
View file

@ -0,0 +1,11 @@
---
layout: page
title: WSGI
permalink: /wsgi/
---
Radicale is compatible with the WSGI specification. No special configuration
is required.
Be reminded that Radicale's default configuration enforces limits on the
maximum file size and that connections are terminated after a timeout.