.\" Man page generated from reStructuredText
.\" by the Docutils 0.23 manpage writer.
.
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "VDIRSYNCER" "1" "Sep 05, 2026" "0.21" "vdirsyncer"
.SH NAME
vdirsyncer \- vdirsyncer Documentation
.INDENT 0.0
.IP \(bu 2
Documentation \%
.IP \(bu 2
Source code \%
.UNINDENT
.sp
Vdirsyncer is a command\-line tool for synchronizing calendars and addressbooks
between a variety of servers and the local filesystem. The most popular usecase
is to synchronize a server with a local folder and use a set of other
programs \%<> to change the local events and contacts.
Vdirsyncer can then synchronize those changes back to the server.
.sp
However, vdirsyncer is not limited to synchronizing between clients and
servers. It can also be used to synchronize calendars and/or addressbooks
between two servers directly.
.sp
It aims to be for calendars and contacts what OfflineIMAP \% is for emails.
.SH WHEN DO I NEED VDIRSYNCER?
.SS Why not Dropbox + todo.txt?
.sp
Projects like todo.txt \% criticize the complexity of
modern productivity apps, and that rightfully. So they set out to create a new,
super\-simple, human\-readable format, such that vim suffices for viewing the raw
data. However, when they\(aqre faced with the question how to synchronize that
data across multiple devices, they seemed to have reached the dead end with
their novel idea: \(dqLet\(aqs just use Dropbox\(dq.
.sp
What does file sync software do if both files have changed since the last sync?
The answer is to ignore the question, just sync as often as possible, and hope
for the best. Because if it comes to a sync conflict, most sync services are
not daring to merge files, and create two copies on each computer instead.
Merging the two task lists is left to the user.
.sp
A better idea would\(aqve been to use \fBgit\fP to synchronize the \fBtodo.txt\fP
file, which is at least able to resolve some basic conflicts.
.SS Why not file sync (Dropbox, git, ...) + vdir?
.sp
Since vdirs \%<> are just a bunch of files, it is obvious to try \fIfile
synchronization\fP for synchronizing your data between multiple computers, such
as:
.INDENT 0.0
.IP \(bu 2
Syncthing \%
.IP \(bu 2
Dropbox \% or one of the gajillion services like it
.IP \(bu 2
unison \%
.IP \(bu 2
Just \fBgit\fP with a \fBsshd\fP\&.
.UNINDENT
.sp
The disadvantages of those solutions largely depend on the exact file sync
program chosen:
.INDENT 0.0
.IP \(bu 2
Like with \fBtodo.txt\fP, Dropbox and friends are obviously agnostic/unaware of
the files\(aq contents. If a file has changed on both sides, Dropbox just copies
both versions to both sides.
.sp
This is a good idea if the user is directly interfacing with the file system
and is able to resolve conflicts themselves. Here it might lead to
erroneous behavior with e.g. \fBkhal\fP, since there are now two events with
the same UID.
.sp
This point doesn\(aqt apply to git: It has very good merging capabilities,
better than what vdirsyncer currently has.
.IP \(bu 2
Such a setup doesn\(aqt work at all with smartphones. Vdirsyncer, on the other
hand, synchronizes with CardDAV/CalDAV servers, which can be accessed with
e.g. DAVx⁵ \% or other apps bundled with smartphones.
.UNINDENT
.SH INSTALLATION
.SS OS/distro packages
.sp
The following packages are community\-contributed and were up\-to\-date at the
time of writing:
.INDENT 0.0
.IP \(bu 2
Arch Linux \%
.IP \(bu 2
Ubuntu and Debian, x86_64\-only \% (packages also exist
in the official repositories but may be out of date)
.IP \(bu 2
GNU Guix \%
.IP \(bu 2
macOS (homebrew) \%
.IP \(bu 2
NetBSD \%
.IP \(bu 2
OpenBSD \%
.IP \(bu 2
Slackware (SlackBuild at Slackbuilds.org) \%
.UNINDENT
.sp
We only support the latest version of vdirsyncer, which is at the time of this
writing 0.21.0\&. Please \fBdo not file bugs if you use an older
version\fP\&.
.sp
Some distributions have multiple release channels. Debian and Fedora for
example have a \(dqstable\(dq release channel that ships an older version of
vdirsyncer. Those versions aren\(aqt supported either.
.sp
If there is no suitable package for your distribution, you\(aqll need to
install vdirsyncer manually\&. There is an easy
command to copy\-and\-paste for this as well, but you should be aware of its
consequences.
.SS Manual installation
.sp
If your distribution doesn\(aqt provide a package for vdirsyncer, you still can
use Python\(aqs package manager \(dqpip\(dq. First, you\(aqll have to check that the
following things are installed:
.INDENT 0.0
.IP \(bu 2
Python 3.9 to 3.14 and pip.
.IP \(bu 2
\fBlibxml\fP and \fBlibxslt\fP
.IP \(bu 2
\fBzlib\fP
.IP \(bu 2
Linux or macOS. \fBWindows is not supported\fP, see issue #535 \%\&.
.UNINDENT
.sp
On Linux systems, using the distro\(aqs package manager is the best
way to do this, for example, using Ubuntu:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
sudo apt\-get install libxml2 libxslt1.1 zlib1g python3
.EE
.UNINDENT
.UNINDENT
.sp
Then you have several options. The following text applies for most Python
software by the way.
.SS pipx: The clean, easy way
.sp
pipx \% is a new package manager for Python\-based software that automatically
sets up a virtual environment for each program it installs. Please note that
installing via pipx will not include manual pages nor systemd services.
.sp
pipx will install vdirsyncer into \fB~/.local/pipx/venvs/vdirsyncer\fP
.sp
Assuming that pipx is installed, vdirsyncer can be installed with:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pipx install vdirsyncer
.EE
.UNINDENT
.UNINDENT
.sp
It can later be updated to the latest version with:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pipx upgrade vdirsyncer
.EE
.UNINDENT
.UNINDENT
.sp
And can be uninstalled with:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pipx uninstall vdirsyncer
.EE
.UNINDENT
.UNINDENT
.sp
This last command will remove vdirsyncer and any dependencies installed into
the above location.
.SS The dirty, easy way
.sp
If pipx is not available on your distribution, the easiest way to install
vdirsyncer at this point would be to run:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pip install \-\-ignore\-installed vdirsyncer
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.IP \(bu 2
\fB\-\-ignore\-installed\fP is to work around Debian\(aqs potentially broken packages
(see Requests\-related ImportErrors \%<#\:debian-urllib3>).
.UNINDENT
.sp
This method has a major flaw though: Pip doesn\(aqt keep track of the files it
installs. Vdirsyncer\(aqs files would be located somewhere in
\fB~/.local/lib/python*\fP, but you can\(aqt possibly know which packages were
installed as dependencies of vdirsyncer and which ones were not, should you
decide to uninstall it. In other words, using pip that way would pollute your
home directory.
.SS The clean, hard way
.sp
There is a way to install Python software without scattering stuff across
your filesystem: virtualenv \%\&. There are a lot of resources on how to use it,
the simplest possible way would look something like:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
virtualenv ~/vdirsyncer_env
~/vdirsyncer_env/bin/pip install vdirsyncer
alias vdirsyncer=\(dq~/vdirsyncer_env/bin/vdirsyncer\(dq
.EE
.UNINDENT
.UNINDENT
.sp
You\(aqll have to put the last line into your \fB\&.bashrc\fP or \fB\&.bash_profile\fP\&.
.sp
This method has two advantages:
.INDENT 0.0
.IP \(bu 2
It separately installs all Python packages into \fB~/vdirsyncer_env/\fP,
without relying on the system packages. This works around OS\- or
distro\-specific issues.
.IP \(bu 2
You can delete \fB~/vdirsyncer_env/\fP to uninstall vdirsyncer entirely.
.UNINDENT
.SH TUTORIAL
.sp
Before starting, consider if you actually need vdirsyncer \%<>\&. There
are better alternatives available for particular usecases.
.SS Installation
.sp
See Installation \%<#\:installation>\&.
.SS Configuration
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.IP \(bu 2
The config.example from the repository \%
contains a very terse version of this.
.IP \(bu 2
In this example we set up contacts synchronization, but calendar sync
works almost the same. Just swap \fBtype = \(dqcarddav\(dq\fP
for \fBtype = \(dqcaldav\(dq\fP and \fBfileext = \(dq.vcf\(dq\fP
for \fBfileext = \(dq.ics\(dq\fP\&.
.IP \(bu 2
Take a look at the Known Problems \%<> page if anything doesn\(aqt work like
planned.
.UNINDENT
.UNINDENT
.UNINDENT
.sp
By default, vdirsyncer looks for its configuration file in the following
locations:
.INDENT 0.0
.IP \(bu 2
The file pointed to by the \fBVDIRSYNCER_CONFIG\fP environment variable.
.IP \(bu 2
\fB~/.vdirsyncer/config\fP\&.
.IP \(bu 2
\fB$XDG_CONFIG_HOME/vdirsyncer/config\fP, which is normally
\fB~/.config/vdirsyncer/config\fP\&. See the XDG\-Basedir \% specification.
.UNINDENT
.sp
The config file should start with a general section \%<#\:general-config>,
where the only required parameter is \fBstatus_path\fP\&. The following is a
minimal example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[general]
status_path = \(dq~/.vdirsyncer/status/\(dq
.EE
.UNINDENT
.UNINDENT
.sp
After the general section, an arbitrary amount of \fIpair and storage sections\fP
might come.
.sp
In vdirsyncer, synchronization is always done between two storages. Such
storages are defined in storage sections \%<#\:storage-config>, and which
pairs of storages should actually be synchronized is defined in pair
section \%<#\:pair-config>\&. This format is copied from OfflineIMAP, where storages
are called repositories and pairs are called accounts.
.sp
The following example synchronizes ownCloud\(aqs addressbooks to \fB~/.contacts/\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[pair my_contacts]
a = \(dqmy_contacts_local\(dq
b = \(dqmy_contacts_remote\(dq
collections = [\(dqfrom a\(dq, \(dqfrom b\(dq]
[storage my_contacts_local]
type = \(dqfilesystem\(dq
path = \(dq~/.contacts/\(dq
fileext = \(dq.vcf\(dq
[storage my_contacts_remote]
type = \(dqcarddav\(dq
# We can simplify this URL here as well. In theory it shouldn\(aqt matter.
url = \(dqhttps://owncloud.example.com/remote.php/carddav/\(dq
username = \(dqbob\(dq
password = \(dqasdf\(dq
.EE
.UNINDENT
.UNINDENT
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
Configuration for other servers can be found at Servers \%<#\:supported-servers>\&.
.UNINDENT
.UNINDENT
.sp
After running \fBvdirsyncer discover\fP and \fBvdirsyncer sync\fP, \fB~/.contacts/\fP
will contain subfolders for each addressbook, which in turn will contain a
bunch of \fB\&.vcf\fP files which all contain a contact in \fBVCARD\fP format each.
You can modify their contents, add new ones and delete some [1], and your
changes will be synchronized to the CalDAV server after you run \fBvdirsyncer
sync\fP again. For further reference, it uses the storages \fBfilesystem\fP \%<#\:storage-filesystem>
and \fBcarddav\fP \%<#\:storage-carddav>\&.
.sp
However, if new collections are created on the server, it will not
automatically start synchronizing those [2]\&. You need to run \fBvdirsyncer
discover\fP again to re\-fetch this list instead.
.IP [1] 5
You\(aqll want to use a helper program for this \%<>\&.
.IP [2] 5
Because collections are added rarely, and checking for this case before
every synchronization isn\(aqt worth the overhead.
.SS More Configuration
.SS Conflict resolution
.sp
What if the same item is changed on both sides? What should vdirsyncer
do? Three options are currently provided:
.INDENT 0.0
.IP 1. 3
vdirsyncer displays an error message (the default);
.IP 2. 3
vdirsyncer chooses one alternative version over the other;
.IP 3. 3
vdirsyncer starts a command of your choice that is supposed to merge the two alternative versions.
.UNINDENT
.sp
Options 2 and 3 require adding a \fB\(dqconflict_resolution\(dq\fP
parameter to the pair section. Option 2 requires giving either \fB\(dqa
wins\(dq\fP or \fB\(dqb wins\(dq\fP as value to the parameter:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[pair my_contacts]
\&...
conflict_resolution = \(dqb wins\(dq
.EE
.UNINDENT
.UNINDENT
.sp
Earlier we wrote that \fBb = \(dqmy_contacts_remote\(dq\fP, so when vdirsyncer encounters
the situation where an item changed on both sides, it will simply overwrite the
local item with the one from the server.
.sp
Option 3 requires specifying as value of \fB\(dqconflict_resolution\(dq\fP an
array starting with \fB\(dqcommand\(dq\fP and containing paths and arguments
to a command. For example:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[pair my_contacts]
\&...
conflict_resolution = [\(dqcommand\(dq, \(dqvimdiff\(dq]
.EE
.UNINDENT
.UNINDENT
.sp
In this example, \fBvimdiff \fP will be called with \fB\fP and
\fB\fP being two temporary files containing the conflicting
files. The files need to be exactly the same when the command
returns. More arguments can be passed to the command by adding more
elements to the array.
.sp
See Pair Section \%<#\:pair-config> for the reference documentation.
.SS Metadata synchronization
.sp
Besides items, vdirsyncer can also synchronize metadata like the addressbook\(aqs
or calendar\(aqs \(dqhuman\-friendly\(dq name (internally called \(dqdisplayname\(dq) or the
color associated with a calendar. For the purpose of explaining this feature,
let\(aqs switch to a different base example. This time we\(aqll synchronize calendars:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[pair my_calendars]
a = \(dqmy_calendars_local\(dq
b = \(dqmy_calendars_remote\(dq
collections = [\(dqfrom a\(dq, \(dqfrom b\(dq]
metadata = [\(dqcolor\(dq]
[storage my_calendars_local]
type = \(dqfilesystem\(dq
path = \(dq~/.calendars/\(dq
fileext = \(dq.ics\(dq
[storage my_calendars_remote]
type = \(dqcaldav\(dq
url = \(dqhttps://owncloud.example.com/remote.php/caldav/\(dq
username = \(dqbob\(dq
password = \(dqasdf\(dq
.EE
.UNINDENT
.UNINDENT
.sp
Run \fBvdirsyncer discover\fP for discovery. Then you can use \fBvdirsyncer
metasync\fP to synchronize the \fBcolor\fP property between your local calendars
in \fB~/.calendars/\fP and your ownCloud. Locally the color is just represented
as a file called \fBcolor\fP within the calendar folder.
.SS More information about collections
.sp
\(dqCollection\(dq is a collective term for addressbooks and calendars. A Cardav or
Caldav server can contains several \(dqcollections\(dq which correspond to several
addressbooks or calendar.
.sp
Each collection from a storage has a \(dqcollection name\(dq, a unique identifier for each
collection. In the case of \fBfilesystem\fP \%<#\:storage-filesystem>\-storage, this is the name of the
directory that represents the collection, in the case of the DAV\-storages this
is the last segment of the URL. We use this identifier in the \fBcollections\fP
parameter in the \fBpair\fP\-section.
.sp
This identifier doesn\(aqt change even if you rename your calendar in whatever UI
you have, because that only changes the so\-called \(dqdisplayname\(dq property [3]\&.
On some servers (iCloud, Google) this identifier is randomly generated and has
no correlation with the displayname you chose.
.IP [3] 5
Which you can also synchronize with \fBmetasync\fP using \fBmetadata =
[\(dqdisplayname\(dq]\fP\&.
.sp
There are three collection names that have a special meaning:
.INDENT 0.0
.IP \(bu 2
\fB\(dqfrom a\(dq\fP, \fB\(dqfrom b\(dq\fP: A placeholder for all collections that can be
found on side A/B when running \fBvdirsyncer discover\fP\&.
.IP \(bu 2
\fBnull\fP: The parameters given to the storage are exact and require no discovery.
.UNINDENT
.sp
The last one requires a bit more explanation. Assume this config which
synchronizes two directories of addressbooks:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[pair foobar]
a = \(dqfoo\(dq
b = \(dqbar\(dq
collections = [\(dqfrom a\(dq, \(dqfrom b\(dq]
[storage foo]
type = \(dqfilesystem\(dq
fileext = \(dq.vcf\(dq
path = \(dq./contacts_foo/\(dq
[storage bar]
type = \(dqfilesystem\(dq
fileext = \(dq.vcf\(dq
path = \(dq./contacts_bar/\(dq
.EE
.UNINDENT
.UNINDENT
.sp
As we saw previously this will synchronize all collections in
\fB\&./contacts_foo/\fP with each same\-named collection in \fB\&./contacts_bar/\fP\&. If
there\(aqs a collection that exists on one side but not the other, vdirsyncer will
ask whether to create that folder on the other side.
.sp
If we set \fBcollections = null\fP, \fB\&./contacts_foo/\fP and \fB\&./contacts_bar/\fP
are no longer treated as folders with collections, but as collections
themselves. This means that \fB\&./contacts_foo/\fP and \fB\&./contacts_bar/\fP will
contain \fB\&.vcf\fP\-files, not subfolders that contain \fB\&.vcf\fP\-files.
.sp
This is useful in situations where listing all collections fails because your
DAV\-server doesn\(aqt support it, for example. In this case, you can set \fBurl\fP
of your \fBcarddav\fP \%<#\:storage-carddav>\- or \fBcaldav\fP \%<#\:storage-caldav>\-storage to a URL that points
to your CalDAV/CardDAV collection directly.
.sp
Note that not all storages support the \fBnull\fP\-collection, for example
\fBgoogle_contacts\fP \%<#\:storage-google_contacts> and \fBgoogle_calendar\fP \%<#\:storage-google_calendar> don\(aqt.
.SS Advanced collection configuration (server\-to\-server sync)
.sp
The examples above are good enough if you want to synchronize a remote server
to a previously empty disk. However, even more trickery is required when you
have two servers with \fIalready existing\fP collections which you want to
synchronize.
.sp
The core problem in this situation is that vdirsyncer pairs collections by
collection name by default (see definition in previous section, basically a
foldername or a remote UUID). When you have two servers, those collection names
may not line up as nicely. Suppose you created two calendars \(dqTest\(dq, one on a
NextCloud server and one on iCloud, using their respective web interfaces. The
URLs look something like this:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
NextCloud: https://example.com/remote.php/dav/calendars/user/test/
iCloud: https://p\-XX.caldav.icloud.com/YYY/calendars/3b4c9995\-5c67\-4021\-9fa0\-be4633623e1c
.EE
.UNINDENT
.UNINDENT
.sp
Those are two DAV calendar collections. Their collection names will be \fBtest\fP
and \fB3b4c9995\-5c67\-4021\-9fa0\-be4633623e1c\fP respectively, so you don\(aqt have a
single name you can address them both with. You will need to manually \(dqpair\(dq
(no pun intended) those collections up like this:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[pair doublecloud]
a = \(dqmy_nextcloud\(dq
b = \(dqmy_icloud\(dq
collections = [[\(dqmytest\(dq, \(dqtest\(dq, \(dq3b4c9995\-5c67\-4021\-9fa0\-be4633623e1c\(dq]]
.EE
.UNINDENT
.UNINDENT
.sp
\fBmytest\fP gives that combination of calendars a nice name you can use when
talking about it, so you would use \fBvdirsyncer sync doublecloud/mytest\fP to
say: \(dqOnly synchronize these two storages, nothing else that may be
configured\(dq.
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
Why not use displaynames?
.sp
You may wonder why vdirsyncer just couldn\(aqt figure this out by itself. After
all, you did name both collections \(dqTest\(dq (which is called \(dqthe
displayname\(dq), so why not pair collections by that value?
.sp
There are a few problems with this idea:
.INDENT 0.0
.IP \(bu 2
Two calendars may have the same exact displayname.
.IP \(bu 2
A calendar may not have a (non\-empty) displayname.
.IP \(bu 2
The displayname might change. Either you rename the calendar, or the
calendar renames itself because you change a language setting.
.UNINDENT
.sp
In the end, that property was never designed to be parsed by machines.
.UNINDENT
.UNINDENT
.SH SSL AND CERTIFICATE VALIDATION
.sp
All SSL configuration is done per\-storage.
.SS Pinning by fingerprint
.sp
To pin the certificate by fingerprint:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
type = \(dqcaldav\(dq
\&...
verify_fingerprint = \(dq6D:83:EA:32:6C:39:BA:08:ED:EB:C9:BC:BE:12:BB:BF:0F:D9:83:00:CC:89:7E:C7:32:05:94:96:CA:C5:59:5E\(dq
.EE
.UNINDENT
.UNINDENT
.sp
SHA256\-Fingerprints must be used, MD5 and SHA\-1 are insecure and not supported.
CA validation is disabled when pinning a fingerprint.
.sp
You can use the following command for obtaining a SHA256 fingerprint:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
echo \-n | openssl s_client \-connect unterwaditzer.net:443 | openssl x509 \-noout \-fingerprint \-sha256
.EE
.UNINDENT
.UNINDENT
.sp
However, please consider using Let\(aqs Encrypt \% such
that you can forget about all of that. It is easier to deploy a free
certificate from them than configuring all of your clients to accept the
self\-signed certificate.
.SS Custom root CAs
.sp
To point vdirsyncer to a custom set of root CAs:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
type = \(dqcaldav\(dq
\&...
verify = \(dq/path/to/cert.pem\(dq
.EE
.UNINDENT
.UNINDENT
.sp
Vdirsyncer uses the aiohttp \% library, which uses the default
.nf
\(gassl.SSLContext
https://docs.python.org/3/library/ssl.html#ssl.SSLContext\(ga_
.fi
by default.
.sp
There are cases where certificate validation fails even though you can access
the server fine through e.g. your browser. This usually indicates that your
installation of \fBpython\fP or the \fBaiohttp\fP or library is somehow broken. In
such cases, it makes sense to explicitly set \fBverify\fP or
\fBverify_fingerprint\fP as shown above.
.SS Client Certificates
.sp
Client certificates may be specified with the \fBauth_cert\fP parameter. If the
key and certificate are stored in the same file, it may be a string:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
type = \(dqcaldav\(dq
\&...
auth_cert = \(dq/path/to/certificate.pem\(dq
.EE
.UNINDENT
.UNINDENT
.sp
If the key and certificate are separate, a list may be used:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
type = \(dqcaldav\(dq
\&...
auth_cert = [\(dq/path/to/certificate.crt\(dq, \(dq/path/to/key.key\(dq]
.EE
.UNINDENT
.UNINDENT
.SH STORING PASSWORDS
.sp
Changed in version 0.7.0: Password configuration got completely overhauled.
.sp
Vdirsyncer can fetch passwords from several sources other than the config file.
.SS Command
.sp
Say you have the following configuration:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
type = \(dqcaldav\(dq
url = ...
username = \(dqfoo\(dq
password = \(dqbar\(dq
.EE
.UNINDENT
.UNINDENT
.sp
But it bugs you that the password is stored in cleartext in the config file.
You can do this:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
type = \(dqcaldav\(dq
url = ...
username = \(dqfoo\(dq
password.fetch = [\(dqcommand\(dq, \(dq~/get\-password.sh\(dq, \(dqmore\(dq, \(dqargs\(dq]
.EE
.UNINDENT
.UNINDENT
.sp
You can fetch the username as well:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
type = \(dqcaldav\(dq
url = ...
username.fetch = [\(dqcommand\(dq, \(dq~/get\-username.sh\(dq]
password.fetch = [\(dqcommand\(dq, \(dq~/get\-password.sh\(dq]
.EE
.UNINDENT
.UNINDENT
.sp
Or really any kind of parameter in a storage section.
.sp
You can also pass the command as a string to be executed in a shell:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
\&...
password.fetch = [\(dqshell\(dq, \(dq~/.local/bin/get\-my\-password | head \-n1\(dq]
.EE
.UNINDENT
.UNINDENT
.sp
With pass \% for example, you might find yourself writing something like this in
your configuration file:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
password.fetch = [\(dqcommand\(dq, \(dqpass\(dq, \(dqcaldav\(dq]
.EE
.UNINDENT
.UNINDENT
.SS Accessing the system keyring
.sp
As shown above, you can use the \fBcommand\fP strategy to fetch your credentials
from arbitrary sources. A very common usecase is to fetch your password from
the system keyring.
.sp
The keyring \% Python package contains a command\-line utility for fetching
passwords from the OS\(aqs password store. Installation:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pip install keyring
.EE
.UNINDENT
.UNINDENT
.sp
Basic usage:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
password.fetch = [\(dqcommand\(dq, \(dqkeyring\(dq, \(dqget\(dq, \(dqexample.com\(dq, \(dqfoouser\(dq]
.EE
.UNINDENT
.UNINDENT
.SS Password Prompt
.sp
You can also simply prompt for the password:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
type = \(dqcaldav\(dq
username = \(dqmyusername\(dq
password.fetch = [\(dqprompt\(dq, \(dqPassword for CalDAV\(dq]
.EE
.UNINDENT
.UNINDENT
.SS Environment variable
.sp
To read the password from an environment variable:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage foo]
type = \(dqcaldav\(dq
username = \(dqmyusername\(dq
password.fetch = [\(dqcommand\(dq, \(dqprintenv\(dq, \(dqDAV_PW\(dq]
.EE
.UNINDENT
.UNINDENT
.sp
This is especially handy if you use the same password multiple times
(say, for a CardDAV and a CalDAV storage).
On bash, you can read and export the password without printing:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
read \-s DAV_PW \(dqDAV Password: \(dq && export DAV_PW
.EE
.UNINDENT
.UNINDENT
.SH SYNCING WITH READ-ONLY STORAGES
.sp
If you want to subscribe to a public, read\-only WebCAL \%\-calendar but neither your server nor
your calendar apps support that (or support it insufficiently), vdirsyncer can
be used to synchronize such a public calendar \fBA\fP with a new calendar \fBB\fP
of your own and keep \fBB\fP updated.
.SS Step 1: Create the target calendar
.sp
First you need to create the calendar you want to sync the WebCAL\-calendar
with. Most servers offer a web interface for this. You then need to note the
CalDAV URL of your calendar. Note that this URL should directly point to the
calendar you just created, which means you would have one such URL for each
calendar you have.
.SS Step 2: Creating the config
.sp
Paste this into your vdirsyncer config:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[pair holidays]
a = \(dqholidays_public\(dq
b = \(dqholidays_private\(dq
collections = null
[storage holidays_public]
type = \(dqhttp\(dq
# The URL to your iCalendar file.
url = \(dq...\(dq
[storage holidays_private]
type = \(dqcaldav\(dq
# The direct URL to your calendar.
url = \(dq...\(dq
# The credentials to your CalDAV server
username = \(dq...\(dq
password = \(dq...\(dq
.EE
.UNINDENT
.UNINDENT
.sp
Then run \fBvdirsyncer discover holidays\fP and \fBvdirsyncer sync holidays\fP, and
your previously created calendar should be filled with events.
.SS Step 3: The partial_sync parameter
.sp
Added in version 0.14.
.sp
You may get into a situation where you want to hide or modify some events from
your \fBholidays\fP calendar. If you try to do that at this point, you\(aqll notice
that vdirsyncer will revert any changes you\(aqve made after a few times of
running \fBsync\fP\&. This is because vdirsyncer wants to keep everything in sync,
and it can\(aqt synchronize changes to the public holidays\-calendar because it
doesn\(aqt have the rights to do so.
.sp
For such purposes you can set the \fBpartial_sync\fP parameter to \fBignore\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[pair holidays]
a = \(dqholidays_public\(dq
b = \(dqholidays_private\(dq
collections = null
partial_sync = ignore
.EE
.UNINDENT
.UNINDENT
.sp
See the config docs \%<#\:partial-sync-def> for more information.
.SH FULL CONFIGURATION MANUAL
.sp
Vdirsyncer uses an ini\-like format for storing its configuration. All values
are JSON, invalid JSON will get interpreted as string:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
x = \(dqfoo\(dq # String
x = foo # Shorthand for same string
x = 42 # Integer
x = [\(dqa\(dq, \(dqb\(dq, \(dqc\(dq] # List of strings
x = true # Boolean
x = false
x = null # Also known as None
.EE
.UNINDENT
.UNINDENT
.SS General Section
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[general]
status_path = ...
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.IP \(bu 2
\fBstatus_path\fP: A directory where vdirsyncer will store some additional data
for the next sync.
.sp
The data is needed to determine whether a new item means it has been added on
one side or deleted on the other. Relative paths will be interpreted as
relative to the configuration file\(aqs directory.
.sp
See A simple synchronization algorithm \% for what exactly is in
there.
.UNINDENT
.SS Pair Section
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[pair pair_name]
a = ...
b = ...
#collections = null
#conflict_resolution = null
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.IP \(bu 2
Pair names can consist of any alphanumeric characters and the underscore.
.IP \(bu 2
\fBa\fP and \fBb\fP reference the storages to sync by their names.
.IP \(bu 2
\fBcollections\fP: A list of collections to synchronize when \fBvdirsyncer
sync\fP is executed. See also More information about collections \%<#\:collections-tutorial>\&.
.sp
The special values \fB\(dqfrom a\(dq\fP and \fB\(dqfrom b\(dq\fP, tell vdirsyncer to try
autodiscovery on a specific storage. It means all the collections on side A /
side B.
.sp
If the collection you want to sync doesn\(aqt have the same name on each side,
you may also use a value of the form \fB[\(dqconfig_name\(dq, \(dqname_a\(dq, \(dqname_b\(dq]\fP\&.
This will synchronize the collection \fBname_a\fP on side A with the collection
\fBname_b\fP on side B. The \fBconfig_name\fP will be used for representation in
CLI arguments and logging.
.sp
Examples:
.INDENT 2.0
.IP \(bu 2
\fBcollections = [\(dqfrom b\(dq, \(dqfoo\(dq, \(dqbar\(dq]\fP makes vdirsyncer synchronize all
the collections from side B, and also the collections named \(dqfoo\(dq and \(dqbar\(dq.
.IP \(bu 2
\fBcollections = [\(dqfrom b\(dq, \(dqfrom a\(dq]\fP makes vdirsyncer synchronize all
existing collections on either side.
.IP \(bu 2
\fBcollections = [[\(dqbar\(dq, \(dqbar_a\(dq, \(dqbar_b\(dq], \(dqfoo\(dq]\fP makes vdirsyncer
synchronize \fBbar_a\fP from side A with \fBbar_b\fP from side B, and also
synchronize \fBfoo\fP on both sides with each other.
.UNINDENT
.IP \(bu 2
\fBconflict_resolution\fP: Optional, define how conflicts should be handled. A
conflict occurs when one item (event, task) changed on both sides since the
last sync. See also Conflict resolution \%<#\:conflict-resolution-tutorial>\&.
.sp
Valid values are:
.INDENT 2.0
.IP \(bu 2
\fBnull\fP, where an error is shown and no changes are done.
.IP \(bu 2
\fB\(dqa wins\(dq\fP and \fB\(dqb wins\(dq\fP, where the whole item is taken from one side.
.IP \(bu 2
\fB[\(dqcommand\(dq, \(dqvimdiff\(dq]\fP: \fBvimdiff \fP will be called where
\fB\fP and \fB\fP are temporary files that contain the item of each side
respectively. The files need to be exactly the same when the command
returns.
.INDENT 2.0
.IP \(bu 2
\fBvimdiff\fP can be replaced with any other command. For example, in POSIX
\fB[\(dqcommand\(dq, \(dqcp\(dq]\fP is equivalent to \fB\(dqa wins\(dq\fP\&.
.IP \(bu 2
Additional list items will be forwarded as arguments. For example,
\fB[\(dqcommand\(dq, \(dqvimdiff\(dq, \(dq\-\-noplugin\(dq]\fP runs \fBvimdiff \-\-noplugin\fP\&.
.UNINDENT
.UNINDENT
.sp
Vdirsyncer never attempts to \(dqautomatically merge\(dq the two items.
.UNINDENT
.INDENT 0.0
.IP \(bu 2
\fBpartial_sync\fP: Assume A is read\-only, B not. If you change items on B,
vdirsyncer can\(aqt sync the changes to A. What should happen instead?
.INDENT 2.0
.IP \(bu 2
\fBerror\fP: An error is shown.
.IP \(bu 2
\fBignore\fP: The change is ignored. However: Events deleted in B still
reappear if they\(aqre updated in A.
.IP \(bu 2
\fBrevert\fP (default): The change is reverted on next sync.
.UNINDENT
.sp
See also Syncing with read\-only storages \%<#\:partial-sync-tutorial>\&.
.IP \(bu 2
\fBmetadata\fP: Metadata keys that should be synchronized when \fBvdirsyncer
metasync\fP is executed. Example:
.INDENT 2.0
.INDENT 3.5
.sp
.EX
metadata = [\(dqcolor\(dq, \(dqdisplayname\(dq, \(dqdescription\(dq, \(dqorder\(dq]
.EE
.UNINDENT
.UNINDENT
.sp
This synchronizes the following properties:
.INDENT 2.0
.IP \(bu 2
color: \fBhttp://apple.com/ns/ical/:calendar\-color\fP
.IP \(bu 2
displayname: \fBDAV:displayname\fP
.IP \(bu 2
description: \fBCalDAV:calendar\-description\fP and \fBCardDAV:addressbook\-description\fP
.IP \(bu 2
order: \fBhttp://apple.com/ns/ical/:calendar\-order\fP
.UNINDENT
.sp
The \fBconflict_resolution\fP parameter applies for these properties too.
.UNINDENT
.INDENT 0.0
.IP \(bu 2
\fBimplicit\fP: Opt into implicitly creating collections. Example:
.INDENT 2.0
.INDENT 3.5
.sp
.EX
implicit = \(dqcreate\(dq
.EE
.UNINDENT
.UNINDENT
.sp
When set to \(dqcreate\(dq, missing collections are automatically created on both
sides during sync without prompting the user. This simplifies workflows where
all collections should be synchronized bidirectionally.
.UNINDENT
.SS Storage Section
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage storage_name]
type = ...
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.IP \(bu 2
Storage names can consist of any alphanumeric characters and the underscore.
.IP \(bu 2
\fBtype\fP defines which kind of storage is defined. See Supported Storages\&.
.IP \(bu 2
\fBread_only\fP defines whether the storage should be regarded as a read\-only
storage. The value \fBtrue\fP means synchronization will discard any changes
made to the other side. The value \fBfalse\fP implies normal 2\-way
synchronization.
.IP \(bu 2
Any further parameters are passed on to the storage class.
.UNINDENT
.SS Supported Storages
.SS CalDAV and CardDAV
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
Please also see Servers \%<#\:supported-servers>, as some servers may not work
well.
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B caldav
CalDAV.
.INDENT 7.0
.INDENT 3.5
.sp
.EX
[storage example_for_caldav]
type = \(dqcaldav\(dq
#start_date = null
#end_date = null
#item_types = []
url = \(dq...\(dq
#username = \(dq\(dq
#password = \(dq\(dq
#verify = /path/to/custom_ca.pem
#auth = null
#useragent = \(dqvdirsyncer/0.16.4\(dq
#verify_fingerprint = null
#auth_cert = null
.EE
.UNINDENT
.UNINDENT
.sp
You can set a timerange to synchronize with the parameters \fBstart_date\fP
and \fBend_date\fP\&. Inside those parameters, you can use any Python
expression to return a valid \fBdatetime.datetime\fP object. For
example, the following would synchronize the timerange from one year in the
past to one year in the future:
.INDENT 7.0
.INDENT 3.5
.sp
.EX
start_date = \(dqdatetime.now() \- timedelta(days=365)\(dq
end_date = \(dqdatetime.now() + timedelta(days=365)\(dq
.EE
.UNINDENT
.UNINDENT
.sp
Either both or none have to be specified. The default is to synchronize
everything.
.sp
You can set \fBitem_types\fP to restrict the \fIkind of items\fP you want to
synchronize. For example, if you want to only synchronize events (but don\(aqt
download any tasks from the server), set \fBitem_types = [\(dqVEVENT\(dq]\fP\&. If
you want to synchronize events and tasks, but have some \fBVJOURNAL\fP items
on the server you don\(aqt want to synchronize, use \fBitem_types = [\(dqVEVENT\(dq,
\(dqVTODO\(dq]\fP\&.
.INDENT 7.0
.TP
.B Parameters
.INDENT 7.0
.IP \(bu 2
\fBstart_date\fP \-\- Start date of timerange to show, default \-inf.
.IP \(bu 2
\fBend_date\fP \-\- End date of timerange to show, default +inf.
.IP \(bu 2
\fBitem_types\fP \-\- Kind of items to show. The default, the empty list, is
to show all. This depends on particular features on the server, the
results are not validated.
.IP \(bu 2
\fBurl\fP \-\- Base URL or an URL to a calendar.
.IP \(bu 2
\fBusername\fP \-\- Username for authentication.
.IP \(bu 2
\fBpassword\fP \-\- Password for authentication.
.IP \(bu 2
\fBverify\fP \-\- Optional. Local path to a self\-signed SSL certificate.
See SSL and certificate validation \%<#\:ssl-tutorial> for more information.
.IP \(bu 2
\fBverify_fingerprint\fP \-\- Optional. SHA256 fingerprint of the expected
server certificate. See SSL and certificate validation \%<#\:ssl-tutorial> for more information.
.IP \(bu 2
\fBauth\fP \-\- Optional. Either \fBbasic\fP, \fBdigest\fP or \fBguess\fP\&. The
default is preemptive Basic auth, sending credentials even if server
didn\(aqt request them. This saves from an additional roundtrip per
request. Consider setting \fBguess\fP if this causes issues with your
server.
.IP \(bu 2
\fBauth_cert\fP \-\- Optional. Either a path to a certificate with a client
certificate and the key or a list of paths to the files with them.
.IP \(bu 2
\fBuseragent\fP \-\- Default \fBvdirsyncer\fP\&.
.UNINDENT
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B carddav
CardDAV.
.INDENT 7.0
.INDENT 3.5
.sp
.EX
[storage example_for_carddav]
type = \(dqcarddav\(dq
url = \(dq...\(dq
#username = \(dq\(dq
#password = \(dq\(dq
#verify = /path/to/custom_ca.pem
#auth = null
#useragent = \(dqvdirsyncer/0.16.4\(dq
#verify_fingerprint = null
#auth_cert = null
#use_vcard_4 = false
.EE
.UNINDENT
.UNINDENT
.INDENT 7.0
.TP
.B Parameters
.INDENT 7.0
.IP \(bu 2
\fBurl\fP \-\- Base URL or an URL to an addressbook.
.IP \(bu 2
\fBusername\fP \-\- Username for authentication.
.IP \(bu 2
\fBpassword\fP \-\- Password for authentication.
.IP \(bu 2
\fBverify\fP \-\- Optional. Local path to a self\-signed SSL certificate.
See SSL and certificate validation \%<#\:ssl-tutorial> for more information.
.IP \(bu 2
\fBverify_fingerprint\fP \-\- Optional. SHA256 fingerprint of the expected
server certificate. See SSL and certificate validation \%<#\:ssl-tutorial> for more information.
.IP \(bu 2
\fBauth\fP \-\- Optional. Either \fBbasic\fP, \fBdigest\fP or \fBguess\fP\&. The
default is preemptive Basic auth, sending credentials even if
server didn\(aqt request them. This saves from an additional
roundtrip per request. Consider setting \fBguess\fP if this
causes issues with your server.
.IP \(bu 2
\fBauth_cert\fP \-\- Optional. Either a path to a certificate with a client
certificate and the key or a list of paths to the files
with them.
.IP \(bu 2
\fBuseragent\fP \-\- Default \fBvdirsyncer\fP\&.
.IP \(bu 2
\fBuse_vcard_4\fP \-\- Whether the server use vCard 4.0.
.UNINDENT
.UNINDENT
.UNINDENT
.SS Google
.sp
Vdirsyncer supports synchronization with Google calendars with the restriction
that \fBVTODO\fP files are rejected by the server.
.sp
Synchronization with Google contacts is less reliable due to negligence of
Google\(aqs CardDAV API. \fBGoogle\(aqs CardDAV implementation is allegedly a disaster
in terms of data safety\fP\&. See this blog post \% for the details. Always back
up your data.
.sp
Another caveat is that Google group labels are not synced with vCard\(aqs
CATEGORIES \% property
(also see issue #814 \% and
upstream issue #36761530 \%
for reference) and the
BDAY \% property is not
synced when only partial date information is present (e.g. the year is missing).
.sp
At first run you will be asked to authorize application for Google account
access.
.sp
To use this storage type, you need to install some additional dependencies:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pip install vdirsyncer[google]
.EE
.UNINDENT
.UNINDENT
.sp
Furthermore you need to register vdirsyncer as an application yourself to
obtain \fBclient_id\fP and \fBclient_secret\fP, as it is against Google\(aqs Terms of
Service to hardcode those into opensource software [googleterms] \%<#\:googleterms>:
.INDENT 0.0
.IP 1. 3
Go to the Google API Manager \%
.IP 2. 3
Create a new project under any name.
.UNINDENT
.INDENT 0.0
.IP 2. 3
Within that project, enable the \(dqCalDAV\(dq and \(dqCardDAV\(dq APIs (\fBnot\fP the
Calendar and Contacts APIs, those are different and won\(aqt work). There should
be a search box where you can just enter those terms.
.IP 3. 3
In the sidebar, select \(dqCredentials\(dq, then \(dqCreate Credentials\(dq and create a
new \(dqOAuth Client ID\(dq.
.sp
You\(aqll be prompted to create a OAuth consent screen first. Fill out that
form however you like.
.sp
After setting up the consent screen, finish creating the new \(dqOAuth Client
ID\(aq. The correct application type is \(dqDesktop application\(dq.
.IP 4. 3
Finally you should have a Client ID and a Client secret. Provide these in
your storage config.
.UNINDENT
.sp
The \fBtoken_file\fP parameter should be a path to a file where vdirsyncer can
later store authentication\-related data. You do not need to create the file
itself or write anything to it.
.IP [googleterms] 5
See ToS \%,
section \(dqConfidential Matters\(dq.
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
You need to configure which calendars Google should offer vdirsyncer using
a secret settings page \%\&.
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B google_calendar
Google calendar.
.INDENT 7.0
.INDENT 3.5
.sp
.EX
[storage example_for_google_calendar]
type = \(dqgoogle_calendar\(dq
token_file = \(dq...\(dq
client_id = \(dq...\(dq
client_secret = \(dq...\(dq
#start_date = null
#end_date = null
#item_types = []
.EE
.UNINDENT
.UNINDENT
.sp
Please refer to \fBcaldav\fP regarding the \fBitem_types\fP and timerange parameters.
.INDENT 7.0
.TP
.B Parameters
.INDENT 7.0
.IP \(bu 2
\fBtoken_file\fP \-\- A filepath where access tokens are stored.
.IP \(bu 2
\fBclient_id/client_secret\fP \-\- OAuth credentials, obtained from the Google
API Manager.
.UNINDENT
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B google_contacts
Google contacts.
.INDENT 7.0
.INDENT 3.5
.sp
.EX
[storage example_for_google_contacts]
type = \(dqgoogle_contacts\(dq
token_file = \(dq...\(dq
client_id = \(dq...\(dq
client_secret = \(dq...\(dq
.EE
.UNINDENT
.UNINDENT
.INDENT 7.0
.TP
.B Parameters
.INDENT 7.0
.IP \(bu 2
\fBtoken_file\fP \-\- A filepath where access tokens are stored.
.IP \(bu 2
\fBclient_id/client_secret\fP \-\- OAuth credentials, obtained from the Google
API Manager.
.UNINDENT
.UNINDENT
.UNINDENT
.sp
The current flow is not ideal, but Google has deprecated the previous APIs used
for this without providing a suitable replacement. See issue #975 \% for discussion
on the topic.
.SS Local
.INDENT 0.0
.TP
.B filesystem
Saves each item in its own file, given a directory.
.INDENT 7.0
.INDENT 3.5
.sp
.EX
[storage example_for_filesystem]
type = \(dqfilesystem\(dq
path = \(dq...\(dq
fileext = \(dq...\(dq
#encoding = \(dqutf\-8\(dq
#post_hook = null
#pre_deletion_hook = null
#fileignoreext = \(dq.tmp\(dq
.EE
.UNINDENT
.UNINDENT
.sp
Can be used with khal \%\&. See The Vdir Storage Format \%<> for
a more formal description of the format.
.sp
Directories with a leading dot are ignored to make usage of e.g. version
control easier.
.INDENT 7.0
.TP
.B Parameters
.INDENT 7.0
.IP \(bu 2
\fBpath\fP \-\- Absolute path to a vdir/collection. If this is used in
combination with the \fBcollections\fP parameter in a pair\-section, this
should point to a directory of vdirs instead.
.IP \(bu 2
\fBfileext\fP \-\- The file extension to use (e.g. \fB\&.txt\fP). Contained in the
href, so if you change the file extension after a sync, this will
trigger a re\-download of everything (but \fIshould\fP not cause data\-loss
of any kind). To be compatible with the \fBvset\fP format you have
to either use \fB\&.vcf\fP or \fB\&.ics\fP\&. Note that metasync won\(aqt work
if you use an empty string here.
.IP \(bu 2
\fBencoding\fP \-\- File encoding for items, both content and filename.
.IP \(bu 2
\fBpost_hook\fP \-\- A command to call for each item creation and
modification. The command will be called with the path of the
new/updated file.
.IP \(bu 2
\fBpre_deletion_hook\fP \-\- A command to call for each item deletion.
The command will be called with the path of the deleted file.
.IP \(bu 2
\fBfileeignoreext\fP \-\- The file extention to ignore. It is only useful
if fileext is set to the empty string. The default is \fB\&.tmp\fP\&.
.UNINDENT
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B singlefile
Save data in single local \fB\&.vcf\fP or \fB\&.ics\fP file.
.sp
The storage basically guesses how items should be joined in the file.
.sp
Added in version 0.1.6.
.sp
\fBNote:\fP
.INDENT 7.0
.INDENT 3.5
This storage is very slow, and that is unlikely to change. You should
consider using \fBfilesystem\fP if it fits your usecase.
.UNINDENT
.UNINDENT
.INDENT 7.0
.TP
.B Parameters
.INDENT 7.0
.IP \(bu 2
\fBpath\fP \-\- The filepath to the file to be written to. If collections are
used, this should contain \fB%s\fP as a placeholder for the collection
name.
.IP \(bu 2
\fBencoding\fP \-\- Which encoding the file should use. Defaults to UTF\-8.
.UNINDENT
.UNINDENT
.sp
Example for syncing with \fBcaldav\fP:
.INDENT 7.0
.INDENT 3.5
.sp
.EX
[pair my_calendar]
a = my_calendar_local
b = my_calendar_remote
collections = [\(dqfrom a\(dq, \(dqfrom b\(dq]
[storage my_calendar_local]
type = \(dqsinglefile\(dq
path = ~/.calendars/%s.ics
[storage my_calendar_remote]
type = \(dqcaldav\(dq
url = https://caldav.example.org/
#username =
#password =
.EE
.UNINDENT
.UNINDENT
.sp
Example for syncing with \fBcaldav\fP using a \fBnull\fP collection:
.INDENT 7.0
.INDENT 3.5
.sp
.EX
[pair my_calendar]
a = my_calendar_local
b = my_calendar_remote
[storage my_calendar_local]
type = \(dqsinglefile\(dq
path = ~/my_calendar.ics
[storage my_calendar_remote]
type = \(dqcaldav\(dq
url = https://caldav.example.org/username/my_calendar/
#username =
#password =
.EE
.UNINDENT
.UNINDENT
.UNINDENT
.SS Read\-only storages
.sp
These storages don\(aqt support writing of their items, consequently \fBread_only\fP
is set to \fBtrue\fP by default. Changing \fBread_only\fP to \fBfalse\fP on them
leads to an error.
.INDENT 0.0
.TP
.B http
Use a simple \fB\&.ics\fP file (or similar) from the web.
\fBwebcal://\fP\-calendars are supposed to be used with this, but you have to
replace \fBwebcal://\fP with \fBhttp://\fP, or better, \fBhttps://\fP\&.
.INDENT 7.0
.INDENT 3.5
.sp
.EX
[pair holidays]
a = holidays_local
b = holidays_remote
collections = null
[storage holidays_local]
type = \(dqfilesystem\(dq
path = ~/.config/vdir/calendars/holidays/
fileext = .ics
[storage holidays_remote]
type = \(dqhttp\(dq
url = https://example.com/holidays_from_hicksville.ics
#filter_hook = null
.EE
.UNINDENT
.UNINDENT
.sp
Too many WebCAL providers generate UIDs of all \fBVEVENT\fP\-components
on\-the\-fly, i.e. all UIDs change every time the calendar is downloaded.
This leads many synchronization programs to believe that all events have
been deleted and new ones created, and accordingly causes a lot of
unnecessary uploads and deletions on the other side. Vdirsyncer completely
ignores UIDs coming from \fBhttp\fP and will replace them with a hash
of the normalized item content.
.INDENT 7.0
.TP
.B Parameters
.INDENT 7.0
.IP \(bu 2
\fBurl\fP \-\- URL to the \fB\&.ics\fP file.
.IP \(bu 2
\fBusername\fP \-\- Username for authentication.
.IP \(bu 2
\fBpassword\fP \-\- Password for authentication.
.IP \(bu 2
\fBverify\fP \-\- Optional. Local path to a self\-signed SSL certificate.
See SSL and certificate validation \%<#\:ssl-tutorial> for more information.
.IP \(bu 2
\fBverify_fingerprint\fP \-\- Optional. SHA256 fingerprint of the expected
server certificate. See SSL and certificate validation \%<#\:ssl-tutorial> for more information.
.IP \(bu 2
\fBauth\fP \-\- Optional. Either \fBbasic\fP, \fBdigest\fP or \fBguess\fP\&. The
default is preemptive Basic auth, sending credentials even if server
didn\(aqt request them. This saves from an additional roundtrip per
request. Consider setting \fBguess\fP if this causes issues with your
server.
.IP \(bu 2
\fBauth_cert\fP \-\- Optional. Either a path to a certificate with a client
certificate and the key or a list of paths to the files with them.
.IP \(bu 2
\fBuseragent\fP \-\- Default \fBvdirsyncer\fP\&.
.IP \(bu 2
\fBfilter_hook\fP \-\- Optional. A filter command to call for each fetched
item, passed in raw form to stdin and returned via stdout.
If nothing is returned by the filter command, the item is skipped.
This can be used to alter fields as needed when dealing with providers
generating malformed events.
.UNINDENT
.UNINDENT
.UNINDENT
.SH OTHER TUTORIALS
.sp
The following section contains tutorials not explicitly about any particular
core function of vdirsyncer. They usually show how to integrate vdirsyncer with
third\-party software. Because of that, it may be that the information regarding
that other software only applies to specific versions of them.
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
Please contribute \%<> your own tutorials too! Pages are
often only stubs and are lacking full examples.
.UNINDENT
.UNINDENT
.SS Client applications
.SS Vdirsyncer with Claws Mail
.sp
First of all, Claws\-Mail only supports \fBread\-only\fP functions for vCards. It
can only read contacts, but there\(aqs no editor.
.SS Preparation
.sp
We need to install vdirsyncer, for that look here \%<>\&. Then
we need to create some folders:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
mkdir ~/.vdirsyncer
mkdir ~/.contacts
.EE
.UNINDENT
.UNINDENT
.SS Configuration
.sp
Now we create the configuration for vdirsyncer. Open
\fB~/.vdirsyncer/config\fP with a text editor. The config should look like
this:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[general]
status_path = \(dq~/.vdirsyncer/status/\(dq
[storage local]
type = \(dqsinglefile\(dq
path = \(dq~/.contacts/%s.vcf\(dq
[storage online]
type = \(dqcarddav\(dq
url = \(dqCARDDAV_LINK\(dq
username = \(dqUSERNAME\(dq
password = \(dqPASSWORD\(dq
read_only = true
[pair contacts]
a = \(dqlocal\(dq
b = \(dqonline\(dq
collections = [\(dqfrom a\(dq, \(dqfrom b\(dq]
conflict_resolution = \(dqb wins\(dq
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.IP \(bu 2
In the general section, we define the status folder path, for discovered
collections and generally stuff that needs to persist between syncs.
.IP \(bu 2
In the local section we define that all contacts should be sync in a single
file and the path for the contacts.
.IP \(bu 2
In the online section you must change the url, username and password to your
setup. We also set the storage to read\-only such that no changes get
synchronized back. Claws\-Mail should not be able to do any changes anyway,
but this is one extra safety step in case files get corrupted or vdirsyncer
behaves erratically. You can leave that part out if you want to be able to
edit those files locally.
.IP \(bu 2
In the last section we configure that online contacts win in a conflict
situation. Configure this part however you like. A correct value depends on
which side is most likely to be up\-to\-date.
.UNINDENT
.SS Sync
.sp
Now we discover and sync our contacts:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
vdirsyncer discover contacts
vdirsyncer sync contacts
.EE
.UNINDENT
.UNINDENT
.SS Claws Mail
.sp
Open Claws\-Mail. Go to \fBTools\fP => \fBAddressbook\fP\&.
.sp
Click on \fBAddressbook\fP => \fBNew vCard\fP\&. Choose a name for the book.
.sp
Then search for the for the vCard in the folder \fB~/.contacts/\fP\&. Click
ok, and you we will see your contacts.
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
Claws\-Mail shows only contacts that have a mail address.
.UNINDENT
.UNINDENT
.SS Crontab
.sp
On the end we create a crontab, so that vdirsyncer syncs automatically
every 30 minutes our contacts:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
crontab \-e
.EE
.UNINDENT
.UNINDENT
.sp
On the end of that file enter this line:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
*/30 * * * * /usr/local/bin/vdirsyncer sync > /dev/null
.EE
.UNINDENT
.UNINDENT
.sp
And you\(aqre done!
.SS Running as a systemd.timer
.sp
vdirsyncer includes unit files to run at an interval (by default every 15±5
minutes).
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
These are not installed when installing via pip, only via distribution
packages. If you installed via pip, or your distribution doesn\(aqt ship systemd
unit files, you\(aqll need to download vdirsyncer.service \% and vdirsyncer.timer \%
into either \fB/etc/systemd/user/\fP or \fB~/.local/share/systemd/user\fP\&.
.UNINDENT
.UNINDENT
.SS Activation
.sp
To activate the timer, just run \fBsystemctl \-\-user enable vdirsyncer.timer\fP\&.
To see logs of previous runs, use \fBjournalctl \-\-user \-u vdirsyncer\fP\&.
.SS Configuration
.sp
It\(aqs quite possible that the default \(dqevery fifteen minutes\(dq interval isn\(aqt to
your liking. No default will suit everybody, but this is configurable by simply
running:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
systemctl \-\-user edit vdirsyncer.timer
.EE
.UNINDENT
.UNINDENT
.sp
This will open a blank editor, where you can override the timer by including:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
OnBootSec=5m # This is how long after boot the first run takes place.
OnUnitActiveSec=15m # This is how often subsequent runs take place.
.EE
.UNINDENT
.UNINDENT
.SS Todoman
.sp
The iCalendar format also supports saving tasks in form of \fBVTODO\fP\-entries,
with the same file extension as normal events: \fB\&.ics\fP\&. Many CalDAV servers
support synchronizing tasks, vdirsyncer does too.
.sp
todoman \% is a CLI task manager supporting vdir \%<>\&. Its interface is
similar to the ones of Taskwarrior or the todo.txt CLI app. You can use
\fBfilesystem\fP \%<#\:storage-filesystem> with it.
.SS Setting up vdirsyncer
.sp
For this tutorial we will use NextCloud.
.sp
Assuming a config like this:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[general]
status_path = \(dq~/.vdirsyncer/status/\(dq
[pair calendars]
conflict_resolution = \(dqb wins\(dq
a = \(dqcalendars_local\(dq
b = \(dqcalendars_dav\(dq
collections = [\(dqfrom b\(dq]
metadata = [\(dqcolor\(dq, \(dqdisplayname\(dq]
[storage calendars_local]
type = \(dqfilesystem\(dq
path = \(dq~/.calendars/\(dq
fileext = \(dq.ics\(dq
[storage calendars_dav]
type = \(dqcaldav\(dq
url = \(dqhttps://nextcloud.example.net/\(dq
username = \(dq...\(dq
password = \(dq...\(dq
.EE
.UNINDENT
.UNINDENT
.sp
\fBvdirsyncer sync\fP will then synchronize the calendars of your NextCloud \%
instance to subfolders of \fB~/.calendar/\fP\&.
.SS Setting up todoman
.sp
Write this to \fB~/.config/todoman/config.py\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
path = \(dq~/.calendars/*\(dq
.EE
.UNINDENT
.UNINDENT
.sp
The glob \% pattern in \fBpath\fP will match all subfolders in \fB~/.calendars/\fP,
which is exactly the tasklists we want. Now you can use \fBtodoman\fP as
described in its documentation \% and run \fBvdirsyncer sync\fP to synchronize the changes to NextCloud.
.SS Other clients
.sp
The following client applications also synchronize over CalDAV:
.INDENT 0.0
.IP \(bu 2
The Tasks\-app found on iOS
.IP \(bu 2
OpenTasks for Android \%
.IP \(bu 2
The Tasks \%\-app for NextCloud\(aqs web UI
.UNINDENT
.sp
Further applications, with missing pages:
.INDENT 0.0
.IP \(bu 2
khal \%, a CLI calendar application supporting vdir \%<>\&. You can use
\fBfilesystem\fP \%<#\:storage-filesystem> with it.
.IP \(bu 2
Many graphical calendar apps such as dayplanner \%, Orage \% or rainlendar \% save
a calendar in a single \fB\&.ics\fP file. You can use \fBsinglefile\fP \%<#\:storage-singlefile> with
those.
.IP \(bu 2
khard \%, a commandline addressbook supporting vdir \%<>\&. You can use
\fBfilesystem\fP \%<#\:storage-filesystem> with it.
.IP \(bu 2
contactquery.c \%, a small program explicitly written for querying vdirs from
mutt.
.IP \(bu 2
mates \%, a commandline addressbook supporting vdir \%<>\&.
.IP \(bu 2
vdirel \%, access vdir \%<> contacts from Emacs.
.UNINDENT
.SS Servers
.SS Baikal
.sp
Vdirsyncer is continuously tested against the latest version of Baikal \%\&.
.INDENT 0.0
.IP \(bu 2
Baikal up to \fB0.2.7\fP also uses an old version of SabreDAV, with the same
issue as ownCloud, see issue #160 \%\&. This issue is fixed in later versions.
.UNINDENT
.SS DavMail (Exchange, Outlook)
.sp
DavMail \% is a proxy program that allows you to use Card\- and CalDAV clients
with Outlook. That allows you to use vdirsyncer with Outlook.
.sp
In practice your success with DavMail may wildly vary. Depending on your
Exchange server you might get confronted with weird errors of all sorts
(including data\-loss).
.sp
\fBMake absolutely sure you use the latest DavMail\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage outlook]
type = \(dqcaldav\(dq
url = \(dqhttp://localhost:1080/users/user@example.com/calendar/\(dq
username = \(dquser@example.com\(dq
password = \(dq...\(dq
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.IP \(bu 2
Older versions of DavMail handle URLs case\-insensitively. See issue #144 \%\&.
.IP \(bu 2
DavMail is handling malformed data on the Exchange server very poorly. In
such cases the Calendar Checking Tool for Outlook \% might
help.
.IP \(bu 2
In some cases, you may see errors about duplicate events. It may look
something like this:
.INDENT 2.0
.INDENT 3.5
.sp
.EX
error: my_calendar/calendar: Storage \(dqmy_calendar_remote/calendar\(dq contains multiple items with the same UID or even content. Vdirsyncer will now abort the synchronization of this collection, because the fix for this is not clear; It could be the result of a badly behaving server. You can try running:
error:
error: vdirsyncer repair my_calendar_remote/calendar
error:
error: But make sure to have a backup of your data in some form. The offending hrefs are:
[...]
.EE
.UNINDENT
.UNINDENT
.sp
In order to fix this, you can try the Remove\-DuplicateAppointments.ps1 \%
PowerShell script that Microsoft has come up with in order to remove duplicates.
.UNINDENT
.SS FastMail
.sp
Vdirsyncer is continuously tested against FastMail \%, thanks to them for
providing a free account for this purpose. There are no known issues with it.
FastMail\(aqs support pages \% provide
the settings to use:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage cal]
type = \(dqcaldav\(dq
url = \(dqhttps://caldav.fastmail.com/\(dq
username = \(dq...\(dq
password = \(dq...\(dq
[storage card]
type = \(dqcarddav\(dq
url = \(dqhttps://carddav.fastmail.com/\(dq
username = \(dq...\(dq
password = \(dq...\(dq
.EE
.UNINDENT
.UNINDENT
.SS Google
.sp
Using vdirsyncer with Google Calendar is possible as of 0.10, but it is not
tested frequently. You can use \fBgoogle_contacts\fP \%<#\:storage-google_contacts> and
\fBgoogle_calendar\fP \%<#\:storage-google_calendar>\&.
.sp
For more information see issue #202 \% and issue #8 \%\&.
.SS iCloud
.sp
Vdirsyncer is regularly tested against iCloud \%\&.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage cal]
type = \(dqcaldav\(dq
url = \(dqhttps://caldav.icloud.com/\(dq
username = \(dq...\(dq
password = \(dq...\(dq
[storage card]
type = \(dqcarddav\(dq
url = \(dqhttps://contacts.icloud.com/\(dq
username = \(dq...\(dq
password = \(dq...\(dq
.EE
.UNINDENT
.UNINDENT
.sp
Problems:
.INDENT 0.0
.IP \(bu 2
Vdirsyncer can\(aqt do two\-factor auth with iCloud (there doesn\(aqt seem to be a
way to do two\-factor auth over the DAV APIs) You\(aqll need to use app\-specific
passwords \% instead.
.IP \(bu 2
iCloud has a few special requirements when creating collections. In principle
vdirsyncer can do it, but it is recommended to create them from an Apple
client (or the iCloud web interface).
.INDENT 2.0
.IP \(bu 2
iCloud requires a minimum length of collection names.
.IP \(bu 2
Calendars created by vdirsyncer cannot be used as tasklists.
.UNINDENT
.UNINDENT
.SS nextCloud
.sp
Vdirsyncer is continuously tested against the latest version of nextCloud \%:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage cal]
type = \(dqcaldav\(dq
url = \(dqhttps://nextcloud.example.com/\(dq
username = \(dq...\(dq
password = \(dq...\(dq
[storage card]
type = \(dqcarddav\(dq
url = \(dqhttps://nextcloud.example.com/\(dq
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.IP \(bu 2
WebCAL\-subscriptions can\(aqt be discovered by vdirsyncer. See this relevant
issue \%\&.
.UNINDENT
.SS ownCloud
.sp
Vdirsyncer is continuously tested against the latest version of ownCloud \%:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage cal]
type = \(dqcaldav\(dq
url = \(dqhttps://example.com/remote.php/dav/\(dq
username = ...
password = ...
[storage card]
type = \(dqcarddav\(dq
url = \(dqhttps://example.com/remote.php/dav/\(dq
username = ...
password = ...
.EE
.UNINDENT
.UNINDENT
.INDENT 0.0
.IP \(bu 2
\fIVersions older than 7.0.0:\fP ownCloud uses SabreDAV, which had problems
detecting collisions and race\-conditions. The problems were reported and are
fixed in SabreDAV\(aqs repo, and the corresponding fix is also in ownCloud since
7.0.0. See issue #16 \% for more information.
.UNINDENT
.SS Radicale
.sp
Radicale \% is a very lightweight server, however, it intentionally doesn\(aqt
implement the CalDAV and CardDAV standards completely, which might lead to
issues even with very well\-written clients. Apart from its non\-conformity with
standards, there are multiple other problems with its code quality and the way
it is maintained. Consider using e.g. Xandikos \%<> instead.
.sp
That said, vdirsyncer is continuously tested against the git version and the
latest PyPI release of Radicale.
.INDENT 0.0
.IP \(bu 2
Vdirsyncer can\(aqt create collections on Radicale.
.IP \(bu 2
Radicale doesn\(aqt support time ranges in the calendar\-query of CalDAV \%, so setting \fBstart_date\fP
and \fBend_date\fP for \fBcaldav\fP \%<#\:storage-caldav> will have no or unpredicted
consequences.
.IP \(bu 2
Versions of Radicale older than 0.9b1 choke on RFC\-conform queries for all
items of a collection \%\&.
.sp
You have to set \fBitem_types = [\(dqVTODO\(dq, \(dqVEVENT\(dq]\fP in
\fBcaldav\fP \%<#\:storage-caldav> for vdirsyncer to work with those versions.
.UNINDENT
.SS Xandikos
.sp
Xandikos \% is a lightweight, yet complete CalDAV and CardDAV server, backed by
git. Vdirsyncer is continuously tested against its latest version.
.sp
After running \fB\&./bin/xandikos \-\-defaults \-d $HOME/dav\fP, you should be able to
point vdirsyncer against the root of Xandikos like this:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
[storage cal]
type = \(dqcaldav\(dq
url = \(dqhttps://xandikos.example.com/\(dq
username = \(dq...\(dq
password = \(dq...\(dq
[storage card]
type = \(dqcarddav\(dq
url = \(dqhttps://xandikos.example.com/\(dq
username = \(dq...\(dq
password = \(dq...\(dq
.EE
.UNINDENT
.UNINDENT
.SH KNOWN PROBLEMS
.sp
For any unanswered questions or problems, see Support and Contact \%<>\&.
.SS Requests\-related ImportErrors
.INDENT 0.0
.INDENT 3.5
ImportError: No module named packages.urllib3.poolmanager
.sp
ImportError: cannot import name iter_field_objects
.UNINDENT
.UNINDENT
.sp
Debian and nowadays even other distros make modifications to the \fBrequests\fP
package that don\(aqt play well with packages assuming a normal \fBrequests\fP\&. This
is due to stubbornness on both sides.
.sp
See issue #82 \% and issue #140 \% for past discussions. You have one option to work
around this, that is, to install vdirsyncer in a virtual environment, see
Manual installation \%<#\:manual-installation>\&.
.SH CONTRIBUTING TO THIS PROJECT
.sp
\fBNote:\fP
.INDENT 0.0
.INDENT 3.5
.INDENT 0.0
.IP \(bu 2
Please read Support and Contact \%<> for questions and support requests.
.IP \(bu 2
All participants must follow the pimutils Code of Conduct \%\&.
.UNINDENT
.UNINDENT
.UNINDENT
.SS The issue tracker
.sp
We use GitHub issues \% for
organizing bug reports and feature requests.
.sp
The following labels \% are of
interest:
.INDENT 0.0
.IP \(bu 2
\(dqPlanning\(dq is for issues that are still undecided, but where at least some
discussion exists.
.IP \(bu 2
\(dqBlocked\(dq is for issues that can\(aqt be worked on at the moment because some
other unsolved problem exists. This problem may be a bug in some software
dependency, for instance.
.IP \(bu 2
\(dqReady\(dq contains issues that are ready to work on.
.UNINDENT
.sp
If you just want to get started with contributing, the \(dqready\(dq issues are an
option. Issues that are still in \(dqPlanning\(dq are also an option, but require
more upfront thinking and may turn out to be impossible to solve, or at least
harder than anticipated. On the flip side those tend to be the more interesting
issues as well, depending on how one looks at it.
.sp
All of those labels are also available as a kanban board on waffle.io \%\&. It is really just an alternative
overview over all issues, but might be easier to comprehend.
.sp
Feel free to contact \%<> me or comment on the relevant issues for
further information.
.SS Reporting bugs
.INDENT 0.0
.IP \(bu 2
Make sure your problem isn\(aqt already listed in Known Problems \%<>\&.
.IP \(bu 2
Make sure you have the absolutely latest version of vdirsyncer. For users of
some Linux distributions such as Debian or Fedora this may not be the version
that your distro offers. In those cases please file a bug against the distro
package, not against upstream vdirsyncer.
.IP \(bu 2
Use \fB\-\-verbosity=DEBUG\fP when including output from vdirsyncer.
.UNINDENT
.SS Suggesting features
.sp
If you\(aqre suggesting a feature, keep in mind that vdirsyncer tries not to be a
full calendar or contacts client, but rather just the piece of software that
synchronizes all the data. Take a look at the documentation for software
working with vdirsyncer \%<>\&.
.SS Submitting patches, pull requests
.INDENT 0.0
.IP \(bu 2
\fBDiscuss everything in the issue tracker first\fP (or contact me somehow
else) before implementing it.
.IP \(bu 2
Make sure the tests pass. See below for running them.
.IP \(bu 2
But not because you wrote too few tests.
.IP \(bu 2
Add yourself to \fBAUTHORS.rst\fP, and add a note to \fBCHANGELOG.rst\fP too.
.UNINDENT
.SS Running tests, how to set up your development environment
.sp
For many patches, it might suffice to just let CI run the tests. However,
CI is slow, so you might want to run them locally too. For this, set up a
virtualenv \% and run this inside of it:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
# Install development dependencies, including:
# \- vdirsyncer from the repo into the virtualenv
# \- style checks and formatting (ruff)
make install\-dev
# Install git commit hook for some extra linting and checking
pre\-commit install
.EE
.UNINDENT
.UNINDENT
.sp
Then you can run:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pytest # The normal testsuite
pre\-commit run \-\-all # Run all linters (which also run via pre\-commit)
make \-C docs html # Build the HTML docs, output is at docs/_build/html/
make \-C docs linkcheck # Check docs for any broken links
.EE
.UNINDENT
.UNINDENT
.sp
The \fBMakefile\fP has a lot of options that allow you to control which tests are
run, and which servers are tested. Take a look at its code where they are all
initialized and documented.
.sp
To tests against a specific DAV server, use \fBDAV_SERVER\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
make DAV_SERVER=xandikos test
.EE
.UNINDENT
.UNINDENT
.sp
The server will be initialised in a docker container and terminated at the end
of the test suite.
.sp
If you have any questions, feel free to open issues about it.
.SS Structure of the testsuite
.sp
Within \fBtests/\fP, there are three main folders:
.INDENT 0.0
.IP \(bu 2
\fBsystem\fP contains system\- and also integration tests. A rough rule is: If
the test is using temporary files, put it here.
.IP \(bu 2
\fBunit\fP, where each testcase tests a single class or function.
.IP \(bu 2
\fBstorage\fP runs a generic storage testsuite against all storages.
.UNINDENT
.sp
The reason for this separation is: We are planning to generate separate
coverage reports for each of those testsuites. Ideally \fBunit\fP would generate
palatable coverage of the entire codebase \fIon its own\fP, and the \fIcombination\fP
of \fBsystem\fP and \fBstorage\fP as well.
.SH THE VDIR STORAGE FORMAT
.sp
This document describes a standard for storing calendars and contacts on a
filesystem, with the main goal of being easy to implement.
.sp
Vdirsyncer synchronizes to vdirs via \fBfilesystem\fP \%<#\:storage-filesystem>\&. Each vdir
(basically just a directory with some files in it) represents a calendar or
addressbook.
.SS Basic Structure
.sp
The main folder (root) contains an arbitrary number of subfolders
(collections), which contain only files (items). Synonyms for \(dqcollection\(dq may
be \(dqaddressbook\(dq or \(dqcalendar\(dq.
.sp
An item is:
.INDENT 0.0
.IP \(bu 2
A vCard \% file, in which case the file extension \fImust\fP be \fI\&.vcf\fP, \fIor\fP
.IP \(bu 2
An iCalendar \% file, in which case the file extension \fImust\fP be \fI\&.ics\fP\&.
.UNINDENT
.sp
An item \fIshould\fP contain a \fBUID\fP property as described by the vCard and
iCalendar standards. If it contains more than one \fBUID\fP property, the values
of those \fImust\fP not differ.
.sp
The file \fImust\fP contain exactly one event, task or contact. In most cases this
also implies only one \fBVEVENT\fP/\fBVTODO\fP/\fBVCARD\fP component per file, but
e.g. recurrence exceptions would require multiple \fBVEVENT\fP components per
event.
.sp
The filename should have similar properties as the \fBUID\fP of the file content.
However, there is no requirement for these two to be the same. Programs may
choose to store additional metadata in that filename, however, at the same time
they \fImust not\fP assume that the metadata they included will be preserved by
other programs.
.SS Metadata
.sp
Any of the below metadata files may be absent. None of the files listed below
have any file extensions.
.INDENT 0.0
.IP \(bu 2
A file called \fBcolor\fP inside the vdir indicates the vdir\(aqs color, a
property that is only relevant in UI design.
.sp
Its content is an ASCII\-encoded hex\-RGB value of the form \fB#RRGGBB\fP\&. For
example, a file content of \fB#FF0000\fP indicates that the vdir has a red
(user\-visible) color. No short forms or informal values such as \fBred\fP (as
known from CSS, for example) are allowed. The prefixing \fB#\fP must be
present.
.IP \(bu 2
Files called \fBdisplayname\fP and \fBdescription\fP contain a UTF\-8 encoded label/
description, that may be used to represent the vdir in UIs.
.IP \(bu 2
A file called \fBorder\fP inside the vdir includes the relative order
of the calendar, a property that is only relevant in UI design.
.UNINDENT
.SS Writing to vdirs
.sp
Creating and modifying items or metadata files \fIshould\fP happen atomically \%\&.
.sp
Writing to a temporary file on the same physical device, and then moving it to
the appropriate location is usually a very effective solution. For this
purpose, files with the extension \fB\&.tmp\fP may be created inside collections.
.sp
When changing an item, the original filename \fImust\fP be used.
.SS Reading from vdirs
.INDENT 0.0
.IP \(bu 2
Any file ending with the \fB\&.tmp\fP or no file extension \fImust not\fP be treated
as an item.
.IP \(bu 2
The \fBident\fP part of the filename \fIshould not\fP be parsed to improve the
speed of item lookup.
.UNINDENT
.SS Considerations
.sp
The primary reason this format was chosen is due to its compatibility with the
CardDAV \% and CalDAV \% standards.
.SS Performance
.sp
Currently, vdirs suffer from a rather major performance problem, one which
current implementations try to mitigate by building up indices of the
collections for faster search and lookup.
.sp
The reason items\(aq filenames don\(aqt contain any extra information is simple: The
solutions presented induced duplication of data, where one duplicate might
become out of date because of bad implementations. As it stands right now, an
index format could be formalized separately though.
.sp
vdirsyncer doesn\(aqt really have to bother about efficient item lookup, because
its synchronization algorithm needs to fetch the whole list of items anyway.
Detecting changes is easily implemented by checking the files\(aq modification
time.
.SH PACKAGING GUIDELINES
.sp
Thank you very much for packaging vdirsyncer! The following guidelines should
help you to avoid some common pitfalls.
.sp
If you find yourself needing to patch anything, or going in a different direction,
please open an issue so we can also address in a way that works for everyone. Otherwise
we get bug reports for code or scenarios that don\(aqt exist in upstream vdirsycner.
.SS Obtaining the source code
.sp
The main distribution channel is PyPI \%, and source tarballs can be
obtained there. We mirror the same package tarball and wheel as GitHub
releases. Please do not confuse these with the auto\-generated GitHub \(dqSource
Code\(dq tarball. Those are missing some important metadata and your build will fail.
.sp
We give each release a tag in the git repo. If you want to get notified of new
releases, GitHub\(aqs feed \% is a good way.
.sp
Tags will be signed by the maintainer who is doing the release (starting with
0.16.8), and generation of the tarball and wheel is done by CI. Hence, only the
tag itself is signed.
.SS Dependency versions
.sp
As with most Python packages, \fBsetup.py\fP denotes the dependencies of
vdirsyncer. It also contains lower\-bound versions of each dependency. Older
versions will be rejected by the testsuite.
.SS Testing
.sp
Everything testing\-related goes through the \fBMakefile\fP in the root of the
repository or PyPI package. Trying to e.g. run \fBpytest\fP directly will
require a lot of environment variables to be set (for configuration) and you
probably don\(aqt want to deal with that.
.sp
You can install the all development dependencies with:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
make install\-dev
.EE
.UNINDENT
.UNINDENT
.sp
You probably don\(aqt want this since it will use pip to download the
dependencies. Alternatively test dependencies are listed as \fBtest\fP optional
dependencies in \fBpyproject.toml\fP, again with lower\-bound version
requirements.
.sp
You also have to have vdirsyncer fully installed at this point. Merely
\fBcd\fP\-ing into the tarball will not be sufficient.
.sp
Running the tests happens with:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pytest
.EE
.UNINDENT
.UNINDENT
.sp
Hypothesis will randomly generate test input. If you care about deterministic
tests, set the \fBDETERMINISTIC_TESTS\fP variable to \fB\(dqtrue\(dq\fP:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
make DETERMINISTIC_TESTS=true test
.EE
.UNINDENT
.UNINDENT
.sp
There are a lot of additional variables that allow you to test vdirsyncer
against a particular server. Those variables are not \(dqstable\(dq and may change
drastically between minor versions. Just don\(aqt use them, you are unlikely to
find bugs that vdirsyncer\(aqs CI hasn\(aqt found.
.SS Documentation
.sp
Using Sphinx \% you can generate the documentation you\(aqre reading right now in a
variety of formats, such as HTML, PDF, or even as a manpage. That said, I only
take care of the HTML docs\(aq formatting.
.sp
You can find a list of dependencies in \fBpyproject.toml\fP, in the
\fBproject.optional\-dependencies\fP section as \fBdocs\fP\&. Again, you can install
those using pip with:
.INDENT 0.0
.INDENT 3.5
.sp
.EX
pip install \(aq.[docs]\(aq
.EE
.UNINDENT
.UNINDENT
.sp
Then change into the \fBdocs/\fP directory and build whatever format you want
using the \fBMakefile\fP in there (run \fBmake\fP for the formats you can build).
.SS Contrib files
.sp
Reference \fBsystemd.service\fP and \fBsystemd.timer\fP unit files are provided. It
is recommended to install this if your distribution is systemd\-based.
.SH SUPPORT AND CONTACT
.INDENT 0.0
.IP \(bu 2
The \fB#pimutils\fP IRC channel on Libera.Chat \%
might be active, depending on your timezone. Use it for support and general
(including off\-topic) discussion.
.IP \(bu 2
Open a GitHub issue \% for
concrete bug reports and feature requests.
.IP \(bu 2
For security issues, contact \fBcontact@pimutils.org\fP\&.
.UNINDENT
.SH CHANGELOG
.sp
This changelog only contains information that might be useful to end users and
package maintainers. For further info, see the git commit log.
.sp
Package maintainers and users who have to manually update their installation
may want to subscribe to GitHub\(aqs tag feed \%\&.
.SS Version 0.21.0
.INDENT 0.0
.IP \(bu 2
Implement retrying for \fBgoogle\fP storage type when a rate limit is reached.
.IP \(bu 2
\fBtenacity\fP is now a required dependency.
.IP \(bu 2
Drop support for Python 3.8.
.IP \(bu 2
Retry transient network errors for nullipotent requests.
.IP \(bu 2
Add support for Python 3.14.
.UNINDENT
.SS Version 0.20.0
.INDENT 0.0
.IP \(bu 2
Remove dependency on abandoned \fBatomicwrites\fP library.
.IP \(bu 2
Implement \fBfilter_hook\fP for the HTTP storage.
.IP \(bu 2
Drop support for Python 3.7.
.IP \(bu 2
Add support for Python 3.12 and Python 3.13.
.IP \(bu 2
Properly close the status database after using. This especially affects tests,
where we were leaking a large amount of file descriptors.
.IP \(bu 2
Extend supported versions of \fBaiostream\fP to include 0.7.x.
.UNINDENT
.SS Version 0.19.3
.INDENT 0.0
.IP \(bu 2
Added a no_delete option to the storage configuration. issue #1090 \%
.IP \(bu 2
Fix crash when running \fBvdirsyncer repair\fP on a collection. issue #1019 \%
.IP \(bu 2
Add an option to request vCard v4.0. issue #1066 \%
.IP \(bu 2
Require matching \fBBEGIN\fP and \fBEND\fP lines in vobjects. issue #1103 \%
.IP \(bu 2
A Docker environment for Vdirsyncer has been added Vdirsyncer DOCKERIZED \%\&.
.IP \(bu 2
Implement digest auth. issue #1137 \%
.IP \(bu 2
Add \fBfilter_hook\fP parameter to \fBhttp\fP \%<#\:storage-http>\&. issue #1136 \%
.UNINDENT
.SS Version 0.19.2
.INDENT 0.0
.IP \(bu 2
Improve the performance of \fBSingleFileStorage\fP\&. issue #818 \%
.IP \(bu 2
Properly document some caveats of the Google Contacts storage.
.IP \(bu 2
Fix crash when using auth certs. issue #1033 \%
.IP \(bu 2
The \fBfilesystem\fP storage can be specified with \fBtype =
\(dqfilesystem/icalendar\(dq\fP or \fBtype = \(dqfilesystem/vcard\(dq\fP\&. This has not
functional impact, and is merely for forward compatibility with the Rust
implementation of vdirsyncer.
.IP \(bu 2
Python 3.10 and 3.11 are officially supported.
.IP \(bu 2
Instructions for integrating with Google CalDav/CardDav have changed.
Applications now need to be registered as \(dqDesktop applications\(dq. Using \(dqWeb
application\(dq no longer works due to changes on Google\(aqs side. issue #1078 \%
.UNINDENT
.SS Version 0.19.1
.INDENT 0.0
.IP \(bu 2
Fixed crash when operating on Google Contacts. issue #994 \%
.IP \(bu 2
The \fBHTTP_PROXY\fP and \fBHTTPS_PROXY\fP are now respected. issue #1031 \%
.IP \(bu 2
Instructions for integrating with Google CalDav/CardDav have changed.
Applications now need to be registered as \(dqWeb Application\(dq. issue #975 \%
.IP \(bu 2
Various documentation updates.
.UNINDENT
.SS Version 0.19.0
.INDENT 0.0
.IP \(bu 2
Add \(dqshell\(dq password fetch strategy to pass command string to a shell.
.IP \(bu 2
Add \(dqdescription\(dq and \(dqorder\(dq as metadata. These fetch the CalDAV:
calendar\-description, \fBCardDAV:addressbook\-description\fP and
\fBapple\-ns:calendar\-order\fP properties respectively.
.IP \(bu 2
Add a new \fBshowconfig\fP status. This prints \fIsome\fP configuration values as
JSON. This is intended to be used by external tools and helpers that interact
with \fBvdirsyncer\fP, and considered experimental.
.IP \(bu 2
Add \fBimplicit\fP option to the pair section \%<#\:pair-config>\&. When set to
\(dqcreate\(dq, it implicitly creates missing collections during sync without user
prompts. This simplifies workflows where collections should be automatically
created on both sides.
.IP \(bu 2
Update TLS\-related tests that were failing due to weak MDs. issue #903 \%
.IP \(bu 2
\fBpytest\-httpserver\fP and \fBtrustme\fP are now required for tests.
.IP \(bu 2
\fBpytest\-localserver\fP is no longer required for tests.
.IP \(bu 2
Multithreaded support has been dropped. The \fB\(dq\-\-max\-workers\fP has been removed.
.IP \(bu 2
A new \fBasyncio\fP backend is now used. So far, this shows substantial speed
improvements in \fBdiscovery\fP and \fBmetasync\fP, but little change in \fIsync\fP\&.
This will likely continue improving over time. issue #906 \%
.IP \(bu 2
The \fBgoogle\fP storage types no longer require \fBrequests\-oauthlib\fP, but
require \fBpython\-aiohttp\-oauthlib\fP instead.
.IP \(bu 2
Vdirsyncer no longer includes experimental support for EteSync \%\&. The existing integration had not been supported
for a long time and no longer worked. Support for external storages may be
added if anyone is interested in maintaining an EteSync plugin. EteSync
users should consider using etesync\-dav \%\&.
.IP \(bu 2
The \fBplist\fP for macOS has been dropped. It was broken and homebrew
generates their own based on package metadata. macOS users are encouraged to
use that as a reference.
.UNINDENT
.SS Changes to SSL configuration
.sp
Support for \fBmd5\fP and \fBsha1\fP certificate fingerprints has been dropped. If
you\(aqre validating certificate fingerprints, use \fBsha256\fP instead.
.sp
When using a custom \fBverify_fingerprint\fP, CA validation is always disabled.
.sp
If \fBverify_fingerprint\fP is unset, CA verification is always active. Disabling
both features is insecure and no longer supported.
.sp
The \fBverify\fP parameter no longer takes boolean values, it is now optional and
only takes a string to a custom CA for verification.
.sp
The \fBverify\fP and \fBverify_fingerprint\fP will likely be merged into a single
parameter in future.
.SS Version 0.18.0
.sp
Note: Version 0.17 has some alpha releases but ultimately was never finalised.
0.18 actually continues where 0.16 left off.
.INDENT 0.0
.IP \(bu 2
Support for Python 3.5 and 3.6 has been dropped. This release mostly focuses
on keeping vdirsyncer compatible with newer environments.
.IP \(bu 2
click 8 and click\-threading 0.5.0 are now required.
.IP \(bu 2
For those using \fBpipsi\fP, we now recommend using \fBpipx\fP, it\(aqs successor.
.IP \(bu 2
Python 3.9 is now supported.
.IP \(bu 2
Our Debian/Ubuntu build scripts have been updated. New versions should be
pushed to those repositories soon.
.UNINDENT
.SS Version 0.16.8
.sp
\fIreleased 09 June 2020\fP
.INDENT 0.0
.IP \(bu 2
Support Python 3.7 and 3.8.
.UNINDENT
.sp
This release is functionally identical to 0.16.7.
It\(aqs been tested with recent Python versions, and has been marked as supporting
them. It will also be the final release supporting Python 3.5 and 3.6.
.SS Version 0.16.7
.sp
\fIreleased on 19 July 2018\fP
.INDENT 0.0
.IP \(bu 2
Fixes for Python 3.7
.UNINDENT
.SS Version 0.16.6
.sp
\fIreleased on 13 June 2018\fP
.INDENT 0.0
.IP \(bu 2
\fBPackagers:\fP Documentation building no longer needs a working installation
of vdirsyncer.
.UNINDENT
.SS Version 0.16.5
.sp
\fIreleased on 13 June 2018\fP
.INDENT 0.0
.IP \(bu 2
\fBPackagers:\fP click\-log 0.3 is required.
.IP \(bu 2
All output will now happen on stderr (because of the upgrade of \fBclick\-log\fP).
.UNINDENT
.SS Version 0.16.4
.sp
\fIreleased on 05 February 2018\fP
.INDENT 0.0
.IP \(bu 2
Fix tests for new Hypothesis version. (Literally no other change included)
.UNINDENT
.SS Version 0.16.3
.sp
\fIreleased on 03 October 2017\fP
.INDENT 0.0
.IP \(bu 2
First version with custom Debian and Ubuntu packages. See issue #663 \%\&.
.IP \(bu 2
Remove invalid ASCII control characters from server responses. See issue #626 \%\&.
.IP \(bu 2
\fBpackagers:\fP Python 3.3 is no longer supported. See pull request #674 \%\&.
.UNINDENT
.SS Version 0.16.2
.sp
\fIreleased on 24 August 2017\fP
.INDENT 0.0
.IP \(bu 2
Fix crash when using daterange or item_type filters in
\fBgoogle_calendar\fP \%<#\:storage-google_calendar>, see issue #657 \%\&.
.IP \(bu 2
\fBPackagers:\fP Fixes for new version \fB0.2.0\fP of \fBclick\-log\fP\&. The version
requirements for the dependency \fBclick\-log\fP changed.
.UNINDENT
.SS Version 0.16.1
.sp
\fIreleased on 8 August 2017\fP
.INDENT 0.0
.IP \(bu 2
Removed remoteStorage support, see issue #647 \%\&.
.IP \(bu 2
Fixed test failures caused by latest requests version, see issue #660 \%\&.
.UNINDENT
.SS Version 0.16.0
.sp
\fIreleased on 2 June 2017\fP
.INDENT 0.0
.IP \(bu 2
Strip \fBMETHOD:PUBLISH\fP added by some calendar providers, see issue #502 \%\&.
.IP \(bu 2
Fix crash of Google storages when saving token file.
.IP \(bu 2
Make DAV discovery more RFC\-conformant, see pull request #585 \%\&.
.IP \(bu 2
Vdirsyncer is now tested against Xandikos, see pull request #601 \%\&.
.IP \(bu 2
Subfolders with a leading dot are now ignored during discover for
\fBfilesystem\fP storage. This makes it easier to combine it with version
control.
.IP \(bu 2
Statuses are now stored in a sqlite database. Old data is automatically
migrated. Users with really large datasets should encounter performance
improvements. This means that \fBsqlite3 is now a dependency of vdirsyncer\fP\&.
.IP \(bu 2
\fBVdirsyncer is now licensed under the 3\-clause BSD license\fP, see issue #610 \%\&.
.IP \(bu 2
Vdirsyncer now includes experimental support for EteSync \%, see pull request #614 \%\&.
.IP \(bu 2
Vdirsyncer now uses more filesystem metadata for determining whether an item
changed. You will notice a \fBpossibly heavy CPU/IO spike on the first sync
after upgrading\fP\&.
.IP \(bu 2
\fBPackagers:\fP Reference \fBsystemd.service\fP and \fBsystemd.timer\fP unit files
are provided. It is recommended to install these as documentation if your
distribution is systemd\-based.
.UNINDENT
.SS Version 0.15.0
.sp
\fIreleased on 28 February 2017\fP
.INDENT 0.0
.IP \(bu 2
Deprecated syntax for configuration values is now completely rejected. All
values now have to be valid JSON.
.IP \(bu 2
A few UX improvements for Google storages, see issue #549 \% and issue #552 \%\&.
.IP \(bu 2
Fix collection discovery for \fBgoogle_contacts\fP \%<#\:storage-google_contacts>, see issue #564 \%\&.
.IP \(bu 2
iCloud is now tested on Travis, see issue #567 \%\&.
.UNINDENT
.SS Version 0.14.1
.sp
\fIreleased on 05 January 2017\fP
.INDENT 0.0
.IP \(bu 2
\fBvdirsyncer repair\fP no longer changes \(dqunsafe\(dq UIDs by default, an extra
option has to be specified. See issue #527 \%\&.
.IP \(bu 2
A lot of important documentation updates.
.UNINDENT
.SS Version 0.14.0
.sp
\fIreleased on 26 October 2016\fP
.INDENT 0.0
.IP \(bu 2
\fBvdirsyncer sync\fP now continues other uploads if one upload failed. The
exit code in such situations is still non\-zero.
.IP \(bu 2
Add \fBpartial_sync\fP option to pair section. See the config docs \%<#\:partial-sync-def>\&.
.IP \(bu 2
Vdirsyncer will now warn if there\(aqs a string without quotes in your config.
Please file issues if you find documentation that uses unquoted strings.
.IP \(bu 2
Fix an issue that would break khal\(aqs config setup wizard.
.UNINDENT
.SS Version 0.13.1
.sp
\fIreleased on 30 September 2016\fP
.INDENT 0.0
.IP \(bu 2
Fix a bug that would completely break collection discovery.
.UNINDENT
.SS Version 0.13.0
.sp
\fIreleased on 29 September 2016\fP
.INDENT 0.0
.IP \(bu 2
Python 2 is no longer supported at all. See issue #219 \%\&.
.IP \(bu 2
Config sections are now checked for duplicate names. This also means that you
cannot have a storage section \fB[storage foo]\fP and a pair \fB[pair foo]\fP in
your config, they have to have different names. This is done such that
console output is always unambiguous. See issue #459 \%\&.
.IP \(bu 2
Custom commands can now be used for conflict resolution during sync. See
issue #127 \%\&.
.IP \(bu 2
\fBhttp\fP \%<#\:storage-http> now completely ignores UIDs. This avoids a lot of unnecessary
down\- and uploads.
.UNINDENT
.SS Version 0.12.1
.sp
\fIreleased on 20 August 2016\fP
.INDENT 0.0
.IP \(bu 2
Fix a crash for Google and DAV storages. See pull request #492 \%\&.
.IP \(bu 2
Fix an URL\-encoding problem with DavMail. See issue #491 \%\&.
.UNINDENT
.SS Version 0.12
.sp
\fIreleased on 19 August 2016\fP
.INDENT 0.0
.IP \(bu 2
\fBsinglefile\fP \%<#\:storage-singlefile> now supports collections. See pull request #488 \%\&.
.UNINDENT
.SS Version 0.11.3
.sp
\fIreleased on 29 July 2016\fP
.INDENT 0.0
.IP \(bu 2
Default value of \fBauth\fP parameter was changed from \fBguess\fP to \fBbasic\fP
to resolve issues with the Apple Calendar Server (issue #457 \%) and improve
performance. See issue #461 \%\&.
.IP \(bu 2
\fBPackagers:\fP The \fBclick\-threading\fP requirement is now \fB>=0.2\fP\&. It was
incorrect before. See issue #478 \%\&.
.IP \(bu 2
Fix a bug in the DAV XML parsing code that would make vdirsyncer crash on
certain input. See issue #480 \%\&.
.IP \(bu 2
Redirect chains should now be properly handled when resolving \fBwell\-known\fP
URLs. See pull request #481 \%\&.
.UNINDENT
.SS Version 0.11.2
.sp
\fIreleased on 15 June 2016\fP
.INDENT 0.0
.IP \(bu 2
Fix typo that would break tests.
.UNINDENT
.SS Version 0.11.1
.sp
\fIreleased on 15 June 2016\fP
.INDENT 0.0
.IP \(bu 2
Fix a bug in collection validation.
.IP \(bu 2
Fix a cosmetic bug in debug output.
.IP \(bu 2
Various documentation improvements.
.UNINDENT
.SS Version 0.11.0
.sp
\fIreleased on 19 May 2016\fP
.INDENT 0.0
.IP \(bu 2
Discovery is no longer automatically done when running \fBvdirsyncer sync\fP\&.
\fBvdirsyncer discover\fP now has to be explicitly called.
.IP \(bu 2
Add a \fB\&.plist\fP example for Mac OS X.
.IP \(bu 2
Usage under Python 2 now requires a special config parameter to be set.
.IP \(bu 2
Various deprecated configuration parameters do no longer have specialized
errormessages. The generic error message for unknown parameters is shown.
.INDENT 2.0
.IP \(bu 2
Vdirsyncer no longer warns that the \fBpasswordeval\fP parameter has been
renamed to \fBpassword_command\fP\&.
.IP \(bu 2
The \fBkeyring\fP fetching strategy has been dropped some versions ago, but
the specialized error message has been dropped.
.IP \(bu 2
An old status format from version 0.4 is no longer supported. If you\(aqre
experiencing problems, just delete your status folder.
.UNINDENT
.UNINDENT
.SS Version 0.10.0
.sp
\fIreleased on 23 April 2016\fP
.INDENT 0.0
.IP \(bu 2
New storage types \fBgoogle_calendar\fP \%<#\:storage-google_calendar> and \fBgoogle_contacts\fP \%<#\:storage-google_contacts>
have been added.
.IP \(bu 2
New global command line option \fI\-\-config\fP, to specify an alternative config
file. See issue #409 \%\&.
.IP \(bu 2
The \fBcollections\fP parameter can now be used to synchronize
differently\-named collections with each other.
.IP \(bu 2
\fBPackagers:\fP The \fBlxml\fP dependency has been dropped.
.IP \(bu 2
XML parsing is now a lot stricter. Malfunctioning servers that used to work
with vdirsyncer may stop working.
.UNINDENT
.SS Version 0.9.3
.sp
\fIreleased on 22 March 2016\fP
.INDENT 0.0
.IP \(bu 2
\fBsinglefile\fP \%<#\:storage-singlefile> and \fBhttp\fP \%<#\:storage-http> now handle recurring events
properly.
.IP \(bu 2
Fix a typo in the packaging guidelines.
.IP \(bu 2
Moved to \fBpimutils\fP organization on GitHub. Old links \fIshould\fP redirect,
but be aware of client software that doesn\(aqt properly handle redirects.
.UNINDENT
.SS Version 0.9.2
.sp
\fIreleased on 13 March 2016\fP
.INDENT 0.0
.IP \(bu 2
Fixed testsuite for environments that don\(aqt have any web browser installed.
See pull request #384 \%\&.
.UNINDENT
.SS Version 0.9.1
.sp
\fIreleased on 13 March 2016\fP
.INDENT 0.0
.IP \(bu 2
Removed leftover debug print statement in \fBvdirsyncer discover\fP, see commit
\fB3d856749f37639821b148238ef35f1acba82db36\fP\&.
.IP \(bu 2
\fBmetasync\fP will now strip whitespace from the start and the end of the
values. See issue #358 \%\&.
.IP \(bu 2
New \fBPackaging Guidelines\fP have been added to the documentation.
.UNINDENT
.SS Version 0.9.0
.sp
\fIreleased on 15 February 2016\fP
.INDENT 0.0
.IP \(bu 2
The \fBcollections\fP parameter is now required in pair configurations.
Vdirsyncer will tell you what to do in its error message. See issue #328 \%\&.
.UNINDENT
.SS Version 0.8.1
.sp
\fIreleased on 30 January 2016\fP
.INDENT 0.0
.IP \(bu 2
Fix error messages when invalid parameter fetching strategy is used. This is
important because users would receive awkward errors for using deprecated
\fBkeyring\fP fetching.
.UNINDENT
.SS Version 0.8.0
.sp
\fIreleased on 27 January 2016\fP
.INDENT 0.0
.IP \(bu 2
Keyring support has been removed, which means that \fBpassword.fetch =
[\(dqkeyring\(dq, \(dqexample.com\(dq, \(dqmyuser\(dq]\fP doesn\(aqt work anymore.
.sp
For existing setups: Use \fBpassword.fetch = [\(dqcommand\(dq, \(dqkeyring\(dq, \(dqget\(dq,
\(dqexample.com\(dq, \(dqmyuser\(dq]\fP instead, which is more generic. See the
documentation for details.
.IP \(bu 2
Now emitting a warning when running under Python 2. See issue #219 \%\&.
.UNINDENT
.SS Version 0.7.5
.sp
\fIreleased on 23 December 2015\fP
.INDENT 0.0
.IP \(bu 2
Fixed a bug in \fBremotestorage\fP that would try to open a CLI browser
for OAuth.
.IP \(bu 2
Fix a packaging bug that would prevent vdirsyncer from working with newer
lxml versions.
.UNINDENT
.SS Version 0.7.4
.sp
\fIreleased on 22 December 2015\fP
.INDENT 0.0
.IP \(bu 2
Improved error messages instead of faulty server behavior, see issue #290 \% and
issue #300 \%\&.
.IP \(bu 2
Safer shutdown of threadpool, avoid exceptions, see issue #291 \%\&.
.IP \(bu 2
Fix a sync bug for read\-only storages see commit
\fBed22764921b2e5bf6a934cf14aa9c5fede804d8e\fP\&.
.IP \(bu 2
Etag changes are no longer sufficient to trigger sync operations. An actual
content change is also necessary. See issue #257 \%\&.
.IP \(bu 2
\fBremotestorage\fP now automatically opens authentication dialogs in
your configured GUI browser.
.IP \(bu 2
\fBPackagers:\fP \fBlxml>=3.1\fP is now required (newer lower\-bound version).
.UNINDENT
.SS Version 0.7.3
.sp
\fIreleased on 05 November 2015\fP
.INDENT 0.0
.IP \(bu 2
Make remotestorage\-dependencies actually optional.
.UNINDENT
.SS Version 0.7.2
.sp
\fIreleased on 05 November 2015\fP
.INDENT 0.0
.IP \(bu 2
Un\-break testsuite.
.UNINDENT
.SS Version 0.7.1
.sp
\fIreleased on 05 November 2015\fP
.INDENT 0.0
.IP \(bu 2
\fBPackagers:\fP The setuptools extras \fBkeyring\fP and \fBremotestorage\fP have
been added. They\(aqre basically optional dependencies. See \fBsetup.py\fP for
more details.
.IP \(bu 2
Highly experimental remoteStorage support has been added. It may be
completely overhauled or even removed in any version.
.IP \(bu 2
Removed mentions of old \fBpassword_command\fP in documentation.
.UNINDENT
.SS Version 0.7.0
.sp
\fIreleased on 27 October 2015\fP
.INDENT 0.0
.IP \(bu 2
\fBPackagers:\fP New dependencies are \fBclick_threading\fP, \fBclick_log\fP and
\fBclick>=5.0\fP\&.
.IP \(bu 2
\fBpassword_command\fP is gone. Keyring support got completely overhauled. See
Storing passwords \%<>\&.
.UNINDENT
.SS Version 0.6.0
.sp
\fIreleased on 06 August 2015\fP
.INDENT 0.0
.IP \(bu 2
\fBpassword_command\fP invocations with non\-zero exit code are now fatal (and
will abort synchronization) instead of just producing a warning.
.IP \(bu 2
Vdirsyncer is now able to synchronize metadata of collections. Set \fBmetadata
= [\(dqdisplayname\(dq]\fP and run \fBvdirsyncer metasync\fP\&.
.IP \(bu 2
\fBPackagers:\fP Don\(aqt use the GitHub tarballs, but the PyPI ones.
.IP \(bu 2
\fBPackagers:\fP \fBbuild.sh\fP is gone, and \fBMakefile\fP is included in
tarballs. See the content of \fBMakefile\fP on how to run tests post\-packaging.
.IP \(bu 2
\fBverify_fingerprint\fP doesn\(aqt automatically disable \fBverify\fP anymore.
.UNINDENT
.SS Version 0.5.2
.sp
\fIreleased on 15 June 2015\fP
.INDENT 0.0
.IP \(bu 2
Vdirsyncer now checks and corrects the permissions of status files.
.IP \(bu 2
Vdirsyncer is now more robust towards changing UIDs inside items.
.IP \(bu 2
Vdirsyncer is now handling unicode hrefs and UIDs correctly. Software that
produces non\-ASCII UIDs is broken, but apparently it exists.
.UNINDENT
.SS Version 0.5.1
.sp
\fIreleased on 29 May 2015\fP
.INDENT 0.0
.IP \(bu 2
\fBN.b.: The PyPI upload of 0.5.0 is completely broken.\fP
.IP \(bu 2
Raise version of required requests\-toolbelt to \fB0.4.0\fP\&.
.IP \(bu 2
Command line should be a lot faster when no work is done, e.g. for help
output.
.IP \(bu 2
Fix compatibility with iCloud again.
.IP \(bu 2
Use only one worker if debug mode is activated.
.IP \(bu 2
\fBverify=false\fP is now disallowed in vdirsyncer, please use
\fBverify_fingerprint\fP instead.
.IP \(bu 2
Fixed a bug where vdirsyncer\(aqs DAV storage was not using the configured
useragent for collection discovery.
.UNINDENT
.SS Version 0.4.4
.sp
\fIreleased on 12 March 2015\fP
.INDENT 0.0
.IP \(bu 2
Support for client certificates via the new \fBauth_cert\fP
parameter, see issue #182 \% and pull request #183 \%\&.
.IP \(bu 2
The \fBicalendar\fP package is no longer required.
.IP \(bu 2
Several bugfixes related to collection creation.
.UNINDENT
.SS Version 0.4.3
.sp
\fIreleased on 20 February 2015\fP
.INDENT 0.0
.IP \(bu 2
More performance improvements to \fBsinglefile\fP\-storage.
.IP \(bu 2
Add \fBpost_hook\fP param to \fBfilesystem\fP\-storage.
.IP \(bu 2
Collection creation now also works with SabreDAV\-based servers, such as
Baikal or ownCloud.
.IP \(bu 2
Removed some workarounds for Radicale. Upgrading to the latest Radicale will
fix the issues.
.IP \(bu 2
Fixed issues with iCloud discovery.
.IP \(bu 2
Vdirsyncer now includes a simple \fBrepair\fP command that seeks to fix some
broken items.
.UNINDENT
.SS Version 0.4.2
.sp
\fIreleased on 30 January 2015\fP
.INDENT 0.0
.IP \(bu 2
Vdirsyncer now respects redirects when uploading and updating items. This
might fix issues with Zimbra.
.IP \(bu 2
Relative \fBstatus_path\fP values are now interpreted as relative to the
configuration file\(aqs directory.
.IP \(bu 2
Fixed compatibility with custom SabreDAV servers. See issue #166 \%\&.
.IP \(bu 2
Catch harmless threading exceptions that occur when shutting down vdirsyncer.
See issue #167 \%\&.
.IP \(bu 2
Vdirsyncer now depends on \fBatomicwrites\fP\&.
.IP \(bu 2
Massive performance improvements to \fBsinglefile\fP\-storage.
.IP \(bu 2
Items with extremely long UIDs should now be saved properly in
\fBfilesystem\fP\-storage. See issue #173 \%\&.
.UNINDENT
.SS Version 0.4.1
.sp
\fIreleased on 05 January 2015\fP
.INDENT 0.0
.IP \(bu 2
All \fBcreate\fP arguments from all storages are gone. Vdirsyncer now asks if
it should try to create collections.
.IP \(bu 2
The old config values \fBTrue\fP, \fBFalse\fP, \fBon\fP, \fBoff\fP and \fBNone\fP are
now invalid.
.IP \(bu 2
UID conflicts are now properly handled instead of ignoring one item. Card\-
and CalDAV servers are already supposed to take care of those though.
.IP \(bu 2
Official Baikal support added.
.UNINDENT
.SS Version 0.4.0
.sp
\fIreleased on 31 December 2014\fP
.INDENT 0.0
.IP \(bu 2
The \fBpasswordeval\fP parameter has been renamed to \fBpassword_command\fP\&.
.IP \(bu 2
The old way of writing certain config values such as lists is now gone.
.IP \(bu 2
Collection discovery has been rewritten. Old configuration files should be
compatible with it, but vdirsyncer now caches the results of the collection
discovery. You have to run \fBvdirsyncer discover\fP if collections were added
or removed on one side.
.IP \(bu 2
Pair and storage names are now restricted to certain characters. Vdirsyncer
will issue a clear error message if your configuration file is invalid in
that regard.
.IP \(bu 2
Vdirsyncer now supports the XDG\-Basedir specification. If the
\fBVDIRSYNCER_CONFIG\fP environment variable isn\(aqt set and the
\fB~/.vdirsyncer/config\fP file doesn\(aqt exist, it will look for the
configuration file at \fB$XDG_CONFIG_HOME/vdirsyncer/config\fP\&.
.IP \(bu 2
Some improvements to CardDAV and CalDAV discovery, based on problems found
with FastMail. Support for \fB\&.well\-known\fP\-URIs has been added.
.UNINDENT
.SS Version 0.3.4
.sp
\fIreleased on 8 December 2014\fP
.INDENT 0.0
.IP \(bu 2
Some more bugfixes to config handling.
.UNINDENT
.SS Version 0.3.3
.sp
\fIreleased on 8 December 2014\fP
.INDENT 0.0
.IP \(bu 2
Vdirsyncer now also works with iCloud. Particularly collection discovery and
etag handling were fixed.
.IP \(bu 2
Vdirsyncer now encodes Cal\- and CardDAV requests differently. This hasn\(aqt
been well\-tested with servers like Zimbra or SoGo, but isn\(aqt expected to
cause any problems.
.IP \(bu 2
Vdirsyncer is now more robust regarding invalid responses from CalDAV
servers. This should help with future compatibility with Davmail/Outlook.
.IP \(bu 2
Fix a bug when specifying \fBitem_types\fP of \fBcaldav\fP \%<#\:storage-caldav> in the
deprecated config format.
.IP \(bu 2
Fix a bug where vdirsyncer would ignore all but one character specified in
\fBunsafe_href_chars\fP of \fBcaldav\fP \%<#\:storage-caldav> and \fBcarddav\fP \%<#\:storage-carddav>\&.
.UNINDENT
.SS Version 0.3.2
.sp
\fIreleased on 3 December 2014\fP
.INDENT 0.0
.IP \(bu 2
The current config format has been deprecated, and support for it will be
removed in version 0.4.0. Vdirsyncer warns about this now.
.UNINDENT
.SS Version 0.3.1
.sp
\fIreleased on 24 November 2014\fP
.INDENT 0.0
.IP \(bu 2
Fixed a bug where vdirsyncer would delete items if they\(aqre deleted on side A
but modified on side B. Instead vdirsyncer will now upload the new items to
side A. See issue #128 \%\&.
.IP \(bu 2
Synchronization continues with the remaining pairs if one pair crashes, see
issue #121 \%\&.
.IP \(bu 2
The \fBprocesses\fP config key is gone. There is now a \fB\-\-max\-workers\fP option
on the CLI which has a similar purpose. See pull request #126 \%\&.
.IP \(bu 2
The Read The Docs\-theme is no longer required for building the docs. If it is
not installed, the default theme will be used. See issue #134 \%\&.
.UNINDENT
.SS Version 0.3.0
.sp
\fIreleased on 20 September 2014\fP
.INDENT 0.0
.IP \(bu 2
Add \fBverify_fingerprint\fP parameter to \fBhttp\fP \%<#\:storage-http>, \fBcaldav\fP \%<#\:storage-caldav>
and \fBcarddav\fP \%<#\:storage-carddav>, see issue #99 \% and pull request #106 \%\&.
.IP \(bu 2
Add \fBpasswordeval\fP parameter to General Section \%<#\:general-config>, see issue #108 \% and
pull request #117 \%\&.
.IP \(bu 2
Emit warnings (instead of exceptions) about certain invalid responses from
the server, see issue #113 \%\&. This is apparently required for compatibility
with Davmail.
.UNINDENT
.SS Version 0.2.5
.sp
\fIreleased on 27 August 2014\fP
.INDENT 0.0
.IP \(bu 2
Don\(aqt ask for the password of one server more than once and fix multiple
concurrency issues, see issue #101 \%\&.
.IP \(bu 2
Better validation of DAV endpoints.
.UNINDENT
.SS Version 0.2.4
.sp
\fIreleased on 18 August 2014\fP
.INDENT 0.0
.IP \(bu 2
Include workaround for collection discovery with latest version of Radicale.
.IP \(bu 2
Include metadata files such as the changelog or license in source
distribution, see issue #97 \% and issue #98 \%\&.
.UNINDENT
.SS Version 0.2.3
.sp
\fIreleased on 11 August 2014\fP
.INDENT 0.0
.IP \(bu 2
Vdirsyncer now has a \fB\-\-version\fP flag, see issue #92 \%\&.
.IP \(bu 2
Fix a lot of bugs related to special characters in URLs, see issue #49 \%\&.
.UNINDENT
.SS Version 0.2.2
.sp
\fIreleased on 04 August 2014\fP
.INDENT 0.0
.IP \(bu 2
Remove a security check that caused problems with special characters in DAV
URLs and certain servers. On top of that, the security check was nonsensical.
See issue #87 \% and issue #91 \%\&.
.IP \(bu 2
Change some errors to warnings, see issue #88 \%\&.
.IP \(bu 2
Improve collection autodiscovery for servers without full support.
.UNINDENT
.SS Version 0.2.1
.sp
\fIreleased on 05 July 2014\fP
.INDENT 0.0
.IP \(bu 2
Fix bug where vdirsyncer shows empty addressbooks when using CardDAV with
Zimbra.
.IP \(bu 2
Fix infinite loop when password doesn\(aqt exist in system keyring.
.IP \(bu 2
Colorized errors, warnings and debug messages.
.IP \(bu 2
vdirsyncer now depends on the \fBclick\fP package instead of argvard.
.UNINDENT
.SS Version 0.2.0
.sp
\fIreleased on 12 June 2014\fP
.INDENT 0.0
.IP \(bu 2
vdirsyncer now depends on the \fBicalendar\fP package from PyPI, to get rid of
its own broken parser.
.IP \(bu 2
vdirsyncer now also depends on \fBrequests_toolbelt\fP\&. This makes it possible
to guess the authentication type instead of blankly assuming \fBbasic\fP\&.
.IP \(bu 2
Fix a semi\-bug in caldav and carddav storages where a tuple (href, etag)
instead of the proper etag would have been returned from the upload method.
vdirsyncer might do unnecessary copying when upgrading to this version.
.IP \(bu 2
Add the storage \fBsinglefile\fP \%<#\:storage-singlefile>\&. See issue #48 \%\&.
.IP \(bu 2
The \fBcollections\fP parameter for pair sections now accepts the special
values \fBfrom a\fP and \fBfrom b\fP for automatically discovering collections.
See Pair Section \%<#\:pair-config>\&.
.IP \(bu 2
The \fBread_only\fP parameter was added to storage sections. See
Storage Section \%<#\:storage-config>\&.
.UNINDENT
.SS Version 0.1.5
.sp
\fIreleased on 14 May 2014\fP
.INDENT 0.0
.IP \(bu 2
Introduced changelogs
.IP \(bu 2
Many bugfixes
.IP \(bu 2
Many doc fixes
.IP \(bu 2
vdirsyncer now doesn\(aqt necessarily need UIDs anymore for synchronization.
.IP \(bu 2
vdirsyncer now aborts if one collection got completely emptied between
synchronizations. See issue #42 \%\&.
.UNINDENT
.SH CREDITS AND LICENSE
.SS Contributors
.sp
In alphabetical order:
.INDENT 0.0
.IP \(bu 2
Ben Boeckel
.IP \(bu 2
Bleala
.IP \(bu 2
Christian Geier
.IP \(bu 2
Clément Mondon
.IP \(bu 2
Corey Hinshaw
.IP \(bu 2
Kai Herlemann
.IP \(bu 2
Hugo Osvaldo Barrera
.IP \(bu 2
Jason Cox
.IP \(bu 2
Julian Mehne
.IP \(bu 2
Malte Kiefer
.IP \(bu 2
Marek Marczykowski\-Górecki
.IP \(bu 2
Markus Unterwaditzer
.IP \(bu 2
Michael Adler
.IP \(bu 2
rEnr3n
.IP \(bu 2
Thomas Weißschuh
.IP \(bu 2
Witcher01
.IP \(bu 2
samm81
.UNINDENT
.sp
Special thanks goes to:
.INDENT 0.0
.IP \(bu 2
FastMail \% sponsors a
paid account for testing their servers.
.IP \(bu 2
Packagecloud \% provide repositories for
vdirsyncer\(aqs Debian packages.
.UNINDENT
.SS License
.sp
Copyright (c) 2014\-2020 by Markus Unterwaditzer & contributors. See
AUTHORS.rst for more details.
.sp
Some rights reserved.
.sp
Redistribution and use in source and binary forms of the software as well
as documentation, with or without modification, are permitted provided
that the following conditions are met:
.INDENT 0.0
.IP \(bu 2
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
.IP \(bu 2
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
.IP \(bu 2
The names of the contributors may not be used to endorse or
promote products derived from this software without specific
prior written permission.
.UNINDENT
.sp
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS \(dqAS IS\(dq AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
.SH DONATIONS
.sp
vdirsyncer is and will always be free and open source software. We appreciate
sponsors willing to fund our continued work on it.
.sp
If you found my work useful, please consider donating. Thank you!
.INDENT 0.0
.IP \(bu 2
Bitcoin: \fB13p42uWDL62bNRH3KWA6cSpSgvnHy1fs2E\fP\&.
.IP \(bu 2
Sponsor via one\-time tips or recurring donations via Ko\-fi \%\&.
.IP \(bu 2
Sponsor via recurring donations via liberapay \%\&.
.UNINDENT
.SH Author
Markus Unterwaditzer
.SH Copyright
2014-2026, Markus Unterwaditzer & contributors
.\" End of generated man page.