VDIRSYNCER(1) | vdirsyncer | VDIRSYNCER(1) |
vdirsyncer - vdirsyncer Documentation
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.
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.
It aims to be for calendars and contacts what OfflineIMAP is for emails.
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're faced with the question how to synchronize that data across multiple devices, they seemed to have reached the dead end with their novel idea: "Let's just use Dropbox".
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.
A better idea would've been to use git to synchronize the todo.txt file, which is at least able to resolve some basic conflicts.
Since vdirs are just a bunch of files, it is obvious to try file synchronization for synchronizing your data between multiple computers, such as:
The disadvantages of those solutions largely depend on the exact file sync program chosen:
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. khal, since there are now two events with the same UID.
This point doesn't apply to git: It has very good merging capabilities, better than what vdirsyncer currently has.
The following packages are community-contributed and were up-to-date at the time of writing:
We only support the latest version of vdirsyncer, which is at the time of this writing 0.19.0. Please do not file bugs if you use an older version.
Some distributions have multiple release channels. Debian and Fedora for example have a "stable" release channel that ships an older version of vdirsyncer. Those versions aren't supported either.
If there is no suitable package for your distribution, you'll 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.
If your distribution doesn't provide a package for vdirsyncer, you still can use Python's package manager "pip". First, you'll have to check that the following things are installed:
On Linux systems, using the distro's package manager is the best way to do this, for example, using Ubuntu:
sudo apt-get install libxml2 libxslt1.1 zlib1g python
Then you have several options. The following text applies for most Python software by the way.
The easiest way to install vdirsyncer at this point would be to run:
pip install --user --ignore-installed vdirsyncer
This method has a major flaw though: Pip doesn't keep track of the files it installs. Vdirsyncer's files would be located somewhere in ~/.local/lib/python*, but you can't 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.
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:
virtualenv ~/vdirsyncer_env ~/vdirsyncer_env/bin/pip install vdirsyncer alias vdirsyncer="~/vdirsyncer_env/bin/vdirsyncer"
You'll have to put the last line into your .bashrc or .bash_profile.
This method has two advantages:
pipx is a new package manager for Python-based software that automatically sets up a virtualenv for each program you install. Assuming you have it installed on your operating system, you can do:
pipx install vdirsyncer
and ~/.local/pipx/venvs/vdirsyncer will be your new vdirsyncer installation. To update vdirsyncer to the latest version:
pipx upgrade vdirsyncer
If you're done with vdirsyncer, you can do:
pipx uninstall vdirsyncer
and vdirsyncer will be uninstalled, including its dependencies.
Before starting, consider if you actually need vdirsyncer. There are better alternatives available for particular usecases.
See Installation.
NOTE:
By default, vdirsyncer looks for its configuration file in the following locations:
The config file should start with a general section, where the only required parameter is status_path. The following is a minimal example:
[general] status_path = "~/.vdirsyncer/status/"
After the general section, an arbitrary amount of pair and storage sections might come.
In vdirsyncer, synchronization is always done between two storages. Such storages are defined in storage sections, and which pairs of storages should actually be synchronized is defined in pair section. This format is copied from OfflineIMAP, where storages are called repositories and pairs are called accounts.
The following example synchronizes ownCloud's addressbooks to ~/.contacts/:
[pair my_contacts] a = "my_contacts_local" b = "my_contacts_remote" collections = ["from a", "from b"] [storage my_contacts_local] type = "filesystem" path = "~/.contacts/" fileext = ".vcf" [storage my_contacts_remote] type = "carddav" # We can simplify this URL here as well. In theory it shouldn't matter. url = "https://owncloud.example.com/remote.php/carddav/" username = "bob" password = "asdf"
NOTE:
After running vdirsyncer discover and vdirsyncer sync, ~/.contacts/ will contain subfolders for each addressbook, which in turn will contain a bunch of .vcf files which all contain a contact in VCARD 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 vdirsyncer sync again. For further reference, it uses the storages filesystem and carddav.
However, if new collections are created on the server, it will not automatically start synchronizing those [2]. You need to run vdirsyncer discover again to re-fetch this list instead.
What if the same item is changed on both sides? What should vdirsyncer do? Three options are currently provided:
Options 2 and 3 require adding a "conflict_resolution" parameter to the pair section. Option 2 requires giving either "a wins" or "b wins" as value to the parameter:
[pair my_contacts] ... conflict_resolution = "b wins"
Earlier we wrote that b = "my_contacts_remote", 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.
Option 3 requires specifying as value of "conflict_resolution" an array starting with "command" and containing paths and arguments to a command. For example:
[pair my_contacts] ... conflict_resolution = ["command", "vimdiff"]
In this example, vimdiff <a> <b> will be called with <a> and <b> 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.
See Pair Section for the reference documentation.
Besides items, vdirsyncer can also synchronize metadata like the addressbook's or calendar's "human-friendly" name (internally called "displayname") or the color associated with a calendar. For the purpose of explaining this feature, let's switch to a different base example. This time we'll synchronize calendars:
[pair my_calendars] a = "my_calendars_local" b = "my_calendars_remote" collections = ["from a", "from b"] metadata = ["color"] [storage my_calendars_local] type = "filesystem" path = "~/.calendars/" fileext = ".ics" [storage my_calendars_remote] type = "caldav" url = "https://owncloud.example.com/remote.php/caldav/" username = "bob" password = "asdf"
Run vdirsyncer discover for discovery. Then you can use vdirsyncer metasync to synchronize the color property between your local calendars in ~/.calendars/ and your ownCloud. Locally the color is just represented as a file called color within the calendar folder.
"Collection" is a collective term for addressbooks and calendars. Each collection from a storage has a "collection name", a unique identifier for each collection. In the case of 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 collections parameter in the pair-section.
This identifier doesn't change even if you rename your calendar in whatever UI you have, because that only changes the so-called "displayname" property [3]. On some servers (iCloud, Google) this identifier is randomly generated and has no correlation with the displayname you chose.
There are three collection names that have a special meaning:
The last one requires a bit more explanation. Assume this config which synchronizes two directories of addressbooks:
[pair foobar] a = "foo" b = "bar" collections = ["from a", "from b"] [storage foo] type = "filesystem" fileext = ".vcf" path = "./contacts_foo/" [storage bar] type = "filesystem" fileext = ".vcf" path = "./contacts_bar/"
As we saw previously this will synchronize all collections in ./contacts_foo/ with each same-named collection in ./contacts_bar/. If there's a collection that exists on one side but not the other, vdirsyncer will ask whether to create that folder on the other side.
If we set collections = null, ./contacts_foo/ and ./contacts_bar/ are no longer treated as folders with collections, but as collections themselves. This means that ./contacts_foo/ and ./contacts_bar/ will contain .vcf-files, not subfolders that contain .vcf-files.
This is useful in situations where listing all collections fails because your DAV-server doesn't support it, for example. In this case, you can set url of your carddav- or caldav-storage to a URL that points to your CalDAV/CardDAV collection directly.
Note that not all storages support the null-collection, for example google_contacts and google_calendar don't.
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 already existing collections which you want to synchronize.
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 "Test", one on a NextCloud server and one on iCloud, using their respective web interfaces. The URLs look something like this:
NextCloud: https://example.com/remote.php/dav/calendars/user/test/ iCloud: https://p-XX.caldav.icloud.com/YYY/calendars/3b4c9995-5c67-4021-9fa0-be4633623e1c
Those are two DAV calendar collections. Their collection names will be test and 3b4c9995-5c67-4021-9fa0-be4633623e1c respectively, so you don't have a single name you can address them both with. You will need to manually "pair" (no pun intended) those collections up like this:
[pair doublecloud] a = "my_nextcloud" b = "my_icloud" collections = [["mytest", "test", "3b4c9995-5c67-4021-9fa0-be4633623e1c"]]
mytest gives that combination of calendars a nice name you can use when talking about it, so you would use vdirsyncer sync doublecloud/mytest to say: "Only synchronize these two storages, nothing else that may be configured".
NOTE:
You may wonder why vdirsyncer just couldn't figure this out by itself. After all, you did name both collections "Test" (which is called "the displayname"), so why not pair collections by that value?
There are a few problems with this idea:
In the end, that property was never designed to be parsed by machines.
All SSL configuration is done per-storage.
To pin the certificate by fingerprint:
[storage foo] type = "caldav" ... verify_fingerprint = "94:FD:7A:CB:50:75:A4:69:82:0A:F8:23:DF:07:FC:69:3E:CD:90:CA"
SHA256-Fingerprints can be used. CA validation is disabled when pinning a fingerprint.
You can use the following command for obtaining a SHA-1 fingerprint:
echo -n | openssl s_client -connect unterwaditzer.net:443 | openssl x509 -noout -fingerprint
However, please consider using Let's 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.
To point vdirsyncer to a custom set of root CAs:
[storage foo] type = "caldav" ... verify = "/path/to/cert.pem"
Vdirsyncer uses the requests library, which, by default, uses its own set of trusted CAs.
However, the actual behavior depends on how you have installed it. Many Linux distributions patch their python-requests package to use the system certificate CAs. Normally these two stores are similar enough for you to not care.
But 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 the requests library is somehow broken. In such cases, it makes sense to explicitly set verify or verify_fingerprint as shown above.
Client certificates may be specified with the auth_cert parameter. If the key and certificate are stored in the same file, it may be a string:
[storage foo] type = "caldav" ... auth_cert = "/path/to/certificate.pem"
If the key and certificate are separate, a list may be used:
[storage foo] type = "caldav" ... auth_cert = ["/path/to/certificate.crt", "/path/to/key.key"]
Changed in version 0.7.0: Password configuration got completely overhauled.
Vdirsyncer can fetch passwords from several sources other than the config file.
Say you have the following configuration:
[storage foo] type = "caldav" url = ... username = "foo" password = "bar"
But it bugs you that the password is stored in cleartext in the config file. You can do this:
[storage foo] type = "caldav" url = ... username = "foo" password.fetch = ["command", "~/get-password.sh", "more", "args"]
You can fetch the username as well:
[storage foo] type = "caldav" url = ... username.fetch = ["command", "~/get-username.sh"] password.fetch = ["command", "~/get-password.sh"]
Or really any kind of parameter in a storage section.
You can also pass the command as a string to be executed in a shell:
[storage foo] ... password.fetch = ["shell", "~/.local/bin/get-my-password | head -n1"]
With pass for example, you might find yourself writing something like this in your configuration file:
password.fetch = ["command", "pass", "caldav"]
As shown above, you can use the command strategy to fetch your credentials from arbitrary sources. A very common usecase is to fetch your password from the system keyring.
The keyring Python package contains a command-line utility for fetching passwords from the OS's password store. Installation:
pip install keyring
Basic usage:
password.fetch = ["command", "keyring", "get", "example.com", "foouser"]
You can also simply prompt for the password:
[storage foo] type = "caldav" username = "myusername" password.fetch = ["prompt", "Password for CalDAV"]
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 A with a new calendar B of your own and keep B updated.
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.
Paste this into your vdirsyncer config:
[pair holidays] a = "holidays_public" b = "holidays_private" collections = null [storage holidays_public] type = "http" # The URL to your iCalendar file. url = "..." [storage holidays_private] type = "caldav" # The direct URL to your calendar. url = "..." # The credentials to your CalDAV server username = "..." password = "..."
Then run vdirsyncer discover holidays and vdirsyncer sync holidays, and your previously created calendar should be filled with events.
New in version 0.14.
You may get into a situation where you want to hide or modify some events from your holidays calendar. If you try to do that at this point, you'll notice that vdirsyncer will revert any changes you've made after a few times of running sync. This is because vdirsyncer wants to keep everything in sync, and it can't synchronize changes to the public holidays-calendar because it doesn't have the rights to do so.
For such purposes you can set the partial_sync parameter to ignore:
[pair holidays] a = "holidays_public" b = "holidays_private" collections = null partial_sync = ignore
See the config docs for more information.
Vdirsyncer uses an ini-like format for storing its configuration. All values are JSON, invalid JSON will get interpreted as string:
x = "foo" # String x = foo # Shorthand for same string x = 42 # Integer x = ["a", "b", "c"] # List of strings x = true # Boolean x = false x = null # Also known as None
[general] status_path = ...
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's directory.
See A simple synchronization algorithm for what exactly is in there.
[pair pair_name] a = ... b = ... #collections = null #conflict_resolution = null
The special values "from a" and "from b", tell vdirsyncer to try autodiscovery on a specific storage.
If the collection you want to sync doesn't have the same name on each side, you may also use a value of the form ["config_name", "name_a", "name_b"]. This will synchronize the collection name_a on side A with the collection name_b on side B. The config_name will be used for representation in CLI arguments and logging.
Examples:
Valid values are:
Vdirsyncer never attempts to "automatically merge" the two items.
See also Syncing with read-only storages.
metadata = ["color", "displayname", "description", "order"]
This synchronizes the following properties:
The conflict_resolution parameter applies for these properties too.
[storage storage_name] type = ...
NOTE:
[storage example_for_caldav] type = "caldav" #start_date = null #end_date = null #item_types = [] url = "..." #username = "" #password = "" #verify = /path/to/custom_ca.pem #auth = null #useragent = "vdirsyncer/0.16.4" #verify_fingerprint = null #auth_cert = null
You can set a timerange to synchronize with the parameters start_date and end_date. Inside those parameters, you can use any Python expression to return a valid datetime.datetime object. For example, the following would synchronize the timerange from one year in the past to one year in the future:
start_date = "datetime.now() - timedelta(days=365)" end_date = "datetime.now() + timedelta(days=365)"
Either both or none have to be specified. The default is to synchronize everything.
You can set item_types to restrict the kind of items you want to synchronize. For example, if you want to only synchronize events (but don't download any tasks from the server), set item_types = ["VEVENT"]. If you want to synchronize events and tasks, but have some VJOURNAL items on the server you don't want to synchronize, use item_types = ["VEVENT", "VTODO"].
[storage example_for_carddav] type = "carddav" url = "..." #username = "" #password = "" #verify = /path/to/custom_ca.pem #auth = null #useragent = "vdirsyncer/0.16.4" #verify_fingerprint = null #auth_cert = null
Vdirsyncer supports synchronization with Google calendars with the restriction that VTODO files are rejected by the server.
Synchronization with Google contacts is less reliable due to negligence of Google's CardDAV API. Google's CardDAV implementation is allegedly a disaster in terms of data safety. See this blog post for the details. Always back up your data.
At first run you will be asked to authorize application for Google account access.
To use this storage type, you need to install some additional dependencies:
pip install vdirsyncer[google]
Furthermore you need to register vdirsyncer as an application yourself to obtain client_id and client_secret, as it is against Google's Terms of Service to hardcode those into opensource software [googleterms]:
You'll be prompted to create a OAuth consent screen first. Fill out that form however you like.
The token_file parameter should be a filepath where vdirsyncer can later store authentication-related data. You do not need to create the file itself or write anything to it.
NOTE:
[storage example_for_google_calendar] type = "google_calendar" token_file = "..." client_id = "..." client_secret = "..." #start_date = null #end_date = null #item_types = []
Please refer to caldav regarding the item_types and timerange parameters.
[storage example_for_google_contacts] type = "google_contacts" token_file = "..." client_id = "..." client_secret = "..."
[storage example_for_filesystem] type = "filesystem" path = "..." fileext = "..." #encoding = "utf-8" #post_hook = null #fileignoreext = ".tmp"
Can be used with khal. See The Vdir Storage Format for a more formal description of the format.
Directories with a leading dot are ignored to make usage of e.g. version control easier.
The storage basically guesses how items should be joined in the file.
New in version 0.1.6.
NOTE:
Example for syncing with caldav:
[pair my_calendar] a = my_calendar_local b = my_calendar_remote collections = ["from a", "from b"] [storage my_calendar_local] type = "singlefile" path = ~/.calendars/%s.ics [storage my_calendar_remote] type = "caldav" url = https://caldav.example.org/ #username = #password =
Example for syncing with caldav using a null collection:
[pair my_calendar] a = my_calendar_local b = my_calendar_remote [storage my_calendar_local] type = "singlefile" path = ~/my_calendar.ics [storage my_calendar_remote] type = "caldav" url = https://caldav.example.org/username/my_calendar/ #username = #password =
These storages don't support writing of their items, consequently read_only is set to true by default. Changing read_only to false on them leads to an error.
[pair holidays] a = holidays_local b = holidays_remote collections = null [storage holidays_local] type = "filesystem" path = ~/.config/vdir/calendars/holidays/ fileext = .ics [storage holidays_remote] type = "http" url = https://example.com/holidays_from_hicksville.ics
Too many WebCAL providers generate UIDs of all VEVENT-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 http and will replace them with a hash of the normalized item content.
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.
NOTE:
First of all, Claws-Mail only supports read-only functions for vCards. It can only read contacts, but there's no editor.
We need to install vdirsyncer, for that look here. Then we need to create some folders:
mkdir ~/.vdirsyncer mkdir ~/.contacts
Now we create the configuration for vdirsyncer. Open ~/.vdirsyncer/config with a text editor. The config should look like this:
[general] status_path = "~/.vdirsyncer/status/" [storage local] type = "singlefile" path = "~/.contacts/%s.vcf" [storage online] type = "carddav" url = "CARDDAV_LINK" username = "USERNAME" password = "PASSWORD" read_only = true [pair contacts] a = "local" b = "online" collections = ["from a", "from b"] conflict_resolution = "b wins"
Now we discover and sync our contacts:
vdirsyncer discover contacts vdirsyncer sync contacts
Open Claws-Mail. Go to Tools => Addressbook.
Click on Addressbook => New vCard. Choose a name for the book.
Then search for the for the vCard in the folder ~/.contacts/. Click ok, and you we will see your contacts.
NOTE:
On the end we create a crontab, so that vdirsyncer syncs automatically every 30 minutes our contacts:
crontab -e
On the end of that file enter this line:
*/30 * * * * /usr/local/bin/vdirsyncer sync > /dev/null
And you're done!
vdirsyncer includes unit files to run at an interval (by default every 15±5 minutes).
NOTE:
To activate the timer, just run systemctl --user enable vdirsyncer.timer. To see logs of previous runs, use journalctl --user -u vdirsyncer.
It's quite possible that the default "every fifteen minutes" interval isn't to your liking. No default will suit everybody, but this is configurable by simply running:
systemctl --user edit vdirsyncer.timer
This will open a blank editor, where you can override the timer by including:
OnBootSec=5m # This is how long after boot the first run takes place. OnUnitActiveSec=15m # This is how often subsequent runs take place.
The iCalendar format also supports saving tasks in form of VTODO-entries, with the same file extension as normal events: .ics. Many CalDAV servers support synchronizing tasks, vdirsyncer does too.
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 filesystem with it.
For this tutorial we will use NextCloud.
Assuming a config like this:
[general] status_path = "~/.vdirsyncer/status/" [pair calendars] conflict_resolution = "b wins" a = "calendars_local" b = "calendars_dav" collections = ["from b"] metadata = ["color", "displayname"] [storage calendars_local] type = "filesystem" path = "~/.calendars/" fileext = ".ics" [storage calendars_dav] type = "caldav" url = "https://nextcloud.example.net/" username = "..." password = "..."
vdirsyncer sync will then synchronize the calendars of your NextCloud instance to subfolders of ~/.calendar/.
Write this to ~/.config/todoman/todoman.conf:
[main] path = ~/.calendars/*
The glob pattern in path will match all subfolders in ~/.calendars/, which is exactly the tasklists we want. Now you can use todoman as described in its documentation and run vdirsyncer sync to synchronize the changes to NextCloud.
The following client applications also synchronize over CalDAV:
Further applications, with missing pages:
Vdirsyncer is continuously tested against the latest version of Baikal.
DavMail is a proxy program that allows you to use Card- and CalDAV clients with Outlook. That allows you to use vdirsyncer with Outlook.
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).
Make absolutely sure you use the latest DavMail:
[storage outlook] type = "caldav" url = "http://localhost:1080/users/user@example.com/calendar/" username = "user@example.com" password = "..."
error: my_calendar/calendar: Storage "my_calendar_remote/calendar" 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: [...]
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.
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's support pages provide the settings to use:
[storage cal] type = "caldav" url = "https://caldav.fastmail.com/" username = "..." password = "..." [storage card] type = "carddav" url = "https://carddav.fastmail.com/" username = "..." password = "..."
Using vdirsyncer with Google Calendar is possible as of 0.10, but it is not tested frequently. You can use google_contacts and google_calendar.
For more information see issue #202 and issue #8.
Vdirsyncer is regularly tested against iCloud.
[storage cal] type = "caldav" url = "https://caldav.icloud.com/" username = "..." password = "..." [storage card] type = "carddav" url = "https://contacts.icloud.com/" username = "..." password = "..."
Problems:
Vdirsyncer is continuously tested against the latest version of nextCloud:
[storage cal] type = "caldav" url = "https://nextcloud.example.com/" username = "..." password = "..." [storage card] type = "carddav" url = "https://nextcloud.example.com/"
Vdirsyncer is continuously tested against the latest version of ownCloud:
[storage cal] type = "caldav" url = "https://example.com/remote.php/dav/" username = ... password = ... [storage card] type = "carddav" url = "https://example.com/remote.php/dav/" username = ... password = ...
Radicale is a very lightweight server, however, it intentionally doesn't 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.
That said, vdirsyncer is continuously tested against the git version and the latest PyPI release of Radicale.
You have to set item_types = ["VTODO", "VEVENT"] in caldav for vdirsyncer to work with those versions.
Xandikos is a lightweight, yet complete CalDAV and CardDAV server, backed by git. Vdirsyncer is continuously tested against its latest version.
After running ./bin/xandikos --defaults -d $HOME/dav, you should be able to point vdirsyncer against the root of Xandikos like this:
[storage cal] type = "caldav" url = "https://xandikos.example.com/" username = "..." password = "..." [storage card] type = "carddav" url = "https://xandikos.example.com/" username = "..." password = "..."
For any unanswered questions or problems, see Support and Contact.
ImportError: cannot import name iter_field_objects
Debian and nowadays even other distros make modifications to the requests package that don't play well with packages assuming a normal requests. This is due to stubbornness on both sides.
See issue #82 and issue #140 for past discussions. You have one option to work around this, that is, to install vdirsyncer in a virtualenv, see Manual installation.
NOTE:
We use GitHub issues for organizing bug reports and feature requests.
The following labels are of interest:
If you just want to get started with contributing, the "ready" issues are an option. Issues that are still in "Planning" 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.
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.
Feel free to contact me or comment on the relevant issues for further information.
If you're 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.
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:
# Install development dependencies, including: # - vdirsyncer from the repo into the virtualenv # - stylecheckers (flake8) and code formatters (autopep8) make install-dev # Install git commit hook for some extra linting and checking pre-commit install
Then you can run:
make test # The normal testsuite make style # Stylechecker make docs # Build the HTML docs, output is at docs/_build/html/
The Makefile 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.
To tests against a specific DAV server, use DAV_SERVER:
make DAV_SERVER=xandikos test
The server will be initialised in a docker container and terminated at the end of the test suite.
If you have any questions, feel free to open issues about it.
Within tests/, there are three main folders:
The reason for this separation is: We are planning to generate separate coverage reports for each of those testsuites. Ideally unit would generate palatable coverage of the entire codebase on its own, and the combination of system and storage as well.
This document describes a standard for storing calendars and contacts on a filesystem, with the main goal of being easy to implement.
Vdirsyncer synchronizes to vdirs via filesystem. Each vdir (basically just a directory with some files in it) represents a calendar or addressbook.
The main folder (root) contains an arbitrary number of subfolders (collections), which contain only files (items). Synonyms for "collection" may be "addressbook" or "calendar".
An item is:
An item should contain a UID property as described by the vCard and iCalendar standards. If it contains more than one UID property, the values of those must not differ.
The file must contain exactly one event, task or contact. In most cases this also implies only one VEVENT/VTODO/VCARD component per file, but e.g. recurrence exceptions would require multiple VEVENT components per event.
The filename should have similar properties as the UID 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 must not assume that the metadata they included will be preserved by other programs.
Any of the below metadata files may be absent. None of the files listed below have any file extensions.
Its content is an ASCII-encoded hex-RGB value of the form #RRGGBB. For example, a file content of #FF0000 indicates that the vdir has a red (user-visible) color. No short forms or informal values such as red (as known from CSS, for example) are allowed. The prefixing # must be present.
Creating and modifying items or metadata files should happen atomically.
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 .tmp may be created inside collections.
When changing an item, the original filename must be used.
The primary reason this format was chosen is due to its compatibility with the CardDAV and CalDAV standards.
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.
The reason items' filenames don't 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.
vdirsyncer doesn't 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' modification time.
Thank you very much for packaging vdirsyncer! The following guidelines should help you to avoid some common pitfalls.
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't exist in upstream vdirsycner.
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 "Source Code" tarball. Those are missing some important metadata and your build will fail.
We give each release a tag in the git repo. If you want to get notified of new releases, GitHub's feed is a good way.
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.
As with most Python packages, setup.py denotes the dependencies of vdirsyncer. It also contains lower-bound versions of each dependency. Older versions will be rejected by the testsuite.
Everything testing-related goes through the Makefile in the root of the repository or PyPI package. Trying to e.g. run pytest directly will require a lot of environment variables to be set (for configuration) and you probably don't want to deal with that.
You can install the all development dependencies with:
make install-dev
You probably don't want this since it will use pip to download the dependencies. Alternatively you can find the testing dependencies in test-requirements.txt, again with lower-bound version requirements.
You also have to have vdirsyncer fully installed at this point. Merely cd-ing into the tarball will not be sufficient.
Running the tests happens with:
make test
Hypothesis will randomly generate test input. If you care about deterministic tests, set the DETERMINISTIC_TESTS variable to "true":
make DETERMINISTIC_TESTS=true test
There are a lot of additional variables that allow you to test vdirsyncer against a particular server. Those variables are not "stable" and may change drastically between minor versions. Just don't use them, you are unlikely to find bugs that vdirsyncer's CI hasn't found.
Using Sphinx you can generate the documentation you're 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' formatting.
You can find a list of dependencies in docs-requirements.txt. Again, you can install those using pip with:
make install-docs
Then change into the docs/ directory and build whatever format you want using the Makefile in there (run make for the formats you can build).
Reference systemd.service and systemd.timer unit files are provided. It is recommended to install this if your distribution is systemd-based.
This changelog only contains information that might be useful to end users and package maintainers. For further info, see the git commit log.
Package maintainers and users who have to manually update their installation may want to subscribe to GitHub's tag feed.
Support for md5 and sha1 certificate fingerprints has been dropped. If you're validating certificate fingerprints, use sha256 instead.
When using a custom verify_fingerprint, CA validation is always disabled.
If verify_fingerprint is unset, CA verification is always active. Disabling both features is insecure and no longer supported.
The verify parameter no longer takes boolean values, it is now optional and only takes a string to a custom CA for verification.
The verify and verify_fingerprint will likely be merged into a single parameter in future.
Note: Version 0.17 has some alpha releases but ultimately was never finalised. 0.18 actually continues where 0.16 left off.
released 09 June 2020
This release is functionally identical to 0.16.7. It's 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.
released on 19 July 2018
released on 13 June 2018
released on 13 June 2018
released on 05 February 2018
released on 03 October 2017
released on 24 August 2017
released on 8 August 2017
released on 2 June 2017
released on 28 February 2017
released on 05 January 2017
released on 26 October 2016
released on 30 September 2016
released on 29 September 2016
released on 20 August 2016
released on 19 August 2016
released on 29 July 2016
released on 15 June 2016
released on 15 June 2016
released on 19 May 2016
released on 23 April 2016
released on 22 March 2016
released on 13 March 2016
released on 13 March 2016
released on 15 February 2016
released on 30 January 2016
released on 27 January 2016
For existing setups: Use password.fetch = ["command", "keyring", "get", "example.com", "myuser"] instead, which is more generic. See the documentation for details.
released on 23 December 2015
released on 22 December 2015
released on 05 November 2015
released on 05 November 2015
released on 05 November 2015
released on 27 October 2015
released on 06 August 2015
released on 15 June 2015
released on 29 May 2015
released on 12 March 2015
released on 20 February 2015
released on 30 January 2015
released on 05 January 2015
released on 31 December 2014
released on 8 December 2014
released on 8 December 2014
released on 3 December 2014
released on 24 November 2014
released on 20 September 2014
released on 27 August 2014
released on 18 August 2014
released on 11 August 2014
released on 04 August 2014
released on 05 July 2014
released on 12 June 2014
released on 14 May 2014
In alphabetical order:
Special thanks goes to:
vdirsyncer is and will always be free and open source software. We appreciate sponsors willing to fund our continued work on it.
If you found my work useful, please consider donating. Thank you!
Markus Unterwaditzer
2014-2022, Markus Unterwaditzer & contributors
December 17, 2022 | 0.19 |