Backup ownCloud Calendar and Contacts

I have my ownCloud instance in a sub-domain at my hosting provider, so I prefer to make a weekly backup of my calendar and contacts. There is no documented way of doing this afaik, but if you run a *nix-like system where wget is installed, it's actually pretty straight forward. In this example owncloud refers to the URL to the root of your ownCloud installation e.g. http://example.com/owncloud, user is your login and password is your password. The URL to use is the same you use if you want to download the calendar or address book manually. In the upper, right corner of the Calendar and the Contacts app, there's a button named respectively Calendars and Address books. When you click on that, you get a dialog box with a list of your calendar(s) and address book(s). The screen shot below is from the Contacts app. To download manually push the Download button button. Instead of doing that, right-click on it, and select "Copy link location" (or whatever your browser calls it) from the context menu. Choose addressbook Your clipboard will now hold a URL looking something owncloud/apps/contacts/export.php?bookid=1 - for the calendar it would look like owncloud/apps/calendar/export.php?calid=1. Make a simple script using those URLs:
#!/bin/bash
DATE=`date +"%Y-%W"`

# Download and gzip contacts.
wget --auth-no-challenge --no-clobber --http-user=user --http-password=password \
  -O $HOME/pimdata_backup/contacts-$DATE.vcf "owncloud/?app=contacts&getfile=export.php?bookid=1"
gzip -f $HOME/pimdata_backup/contacts-$DATE.vcf

# Download and gzip calendar.
wget --auth-no-challenge --no-clobber --http-user=user --http-password=password \
  -O $HOME/pimdata_backup/calendar-$DATE.ics "owncloud/?app=calendar&getfile=export.php?calid=1"
gzip -f $HOME/pimdata_backup/calendar-$DATE.ics
The --auth-no-challenge is to avoid having the server send an authentication challenge, which would mess up the download. The --no-clobber is to avoid downloading a file that already exists. When gzipping the downloaded file it gets a .gz extension appended to the filename, so it should normally not be an issue though. The backup files will now have names containing the year and week number like contacts-2012-17.vcf.gz and calendar-2012-17.ics.gz. If you prefer to backup in another schedule than weekly, you will of course have to change the date command accordingly. Save the script somewhere preferably in your PATH - I use ~/bin for my scripts - and make it executable: chmod u+x ~/bin/owncloud_backup.sh - or whatever you choose to call it. Test if the script works and set it up to run on a regular basis as a cron job or any other job scheduler; I use KAlarm because it's so damn easy to use ;-) You could use curl instead of wget, it's just a matter of preference. Update: As Klaus Muth mentions in a comment, it cannot be stressed enough that this method should not be used in a multi user environment as it places passwords in the process list at runtime.
Update 2 June 13 2012: I have updated the paths for ownCloud >= 4.3 (git master and stable4). HTTP Auth was broken in versions before that.

flattr this!

25 Comments

  1. 1
    Fabian Rodriguez says:

    Keep in mind when you're using wget your security credentials end up in plain text, stored in your providers logs, which may not be what you want.

    Perhaps a better option would be to encrypt the resulting files locally, on the server (using gpg for example) and then download that. The encryption against a public key won't require any passwords.

    • 2
      tanghus says:

      It does require a certain amount of trust in your hosting provider, but they already have (some of) my files and mail ;-)
      Your suggestion is however interesting. How would you automate that? Run a script via ssh that encrypts the file(s) on the server, and then download that?

  2. 3
    Klaus Muth says:

    I strongly advise not to use that in a multi user environment - it places passwords in the process list at runtime. The preferred solution is to put username and password in a .netrc file and protect this file with a chmod 600 .netrc

    Syntax would be something like:
    machine example.com user tanghus password secret

  3. 9
    Erik D says:

    How can i use it with a windows batch file?

  4. 11
    Profpatsch says:

    Thanks, this will be darn helpful.

  5. 12
    mehturt says:

    I was looking for some documentation how to backup things properly. Since my instance of ownCloud is hosted on my local server, do I need to backup just the database, or do I need anything else as well?

    • 13
      tanghus says:

      Maybe have a look at the "User Account Migration" app for doing backups? AFAIRC you can define what it backs up, and I suppose it's possible to automate the process somehow using wget or curl.

  6. 14
    Christian says:

    Hi!

    I have a problem using this script. If I use it as is, I get an error message: 20 redirections exceeded. after a while. If I remove the --auth-no-challenge, I am always downloading the html login page, not the vcf/ics files.
    I'm using Owncloud 4.5 on lighttpd

    Any ideas?
    Thank you!

    • 15
      tanghus says:

      You can try to use the SabreDAV export link directly. Something like this (adjust URL according to server, user name and address book name):

      http://localhost/owncloud/remote.php/carddav/addressbooks/user/contacts?export
      
      • 16
        Christian says:

        Thanks, it works! No idea why, but it works :-)
        Do you happen to know the address for the calendar as well?

        Thank you"

        • 17
          tanghus says:

          Actually it's a bug that the other URL doesn't work, but the routing is so complex that I don't want to go hunting for it - again ;)
          You can get the URL(s) for the calendar(s) by going to the Calendar app, selecting the calendars button in the top-right corner and click on the "CalDAV link" icon.
          It should be something like:

          http://localhost/owncloud/remote.php/caldav/calendars/user/defaultcalendar?export
          
  7. 18
    bongosmurf says:

    I like this concept, since the vcf/ics files are universal and db-independent formats.
    Is there a URL from which the script can find out which bookid (calid) indexes are in use in order to always iterate through all of them without manual reconfiguration?

    • 19
      tanghus says:

      No such thing exists, and I would actually rather recommend using the URLs from my previous comments:

      http://localhost/owncloud/remote.php/caldav/calendars/user/defaultcalendar?export
      http://localhost/owncloud/remote.php/carddav/addressbooks/user/contacts?export

      Maybe if accessing the base principles with curl or something like that, you can get a listing of the calendars/addressbook

      http://localhost/owncloud/remote.php/caldav/calendars/user/
      http://localhost/owncloud/remote.php/carddav/addressbooks/user/

      • 20
        bongosmurf says:

        Thanks tanghus.

        Sadly I am not fluent in php and the code (at least app/calendar/export.php) is quite terse and uncommented, otherwise I might have tried my luck at it. Anyhow, here's my backup script, which I run from cron and which
        - needs to have the users/passwords of the calendar owners configured, as there is currently an issue with exporting shared calendars
        - needs to have the calendar IDs/owners configured, as there is currently no way to query for a list of a user's calendars
        - doesn't work with .netrc, as it needs to access multiple accounts (so don't implement this on an unsecure system, kids!)

        #!/bin/bash

        me=`basename $0`
        echo -n "# $me starting at "
        date

        TGTDIR=/c/Dokumente\ und\ Einstellungen/myuser/Eigene\ Dateien/DATA/Owncloud-Backup

        # user/pass:
        declare -A passh=( ["joe"]="joespassword" ["jim"]="jimspassword" ["albert"]="albert3spassword" )

        # calendarid/calendarname/owner
        declare -A calnameh=( ["12"]="joe-prv" ["25"]="jim-prv" ["22"]="albert-prv" ["23"]="jim-diving" ["18"]="al-church" ["19"]="al-wrk" ["16"]="family" )
        declare -A caluserh=( ["12"]="joe" ["25"]="jim" ["22"]="albert" ["23"]="jim" ["18"]="albert" ["19"]="albert" ["16"]="joe" )

        for calid in "${!calnameh[@]}" ; do \
        calname="${calnameh["$calid"]}"
        user="${caluserh["$calid"]}"
        pass="${passh["$user"]}"
        echo working on user:$user pass:$pass calid:$calid calname:$calname
        wget --no-check-certificate --user $user --password $pass --auth-no-challenge -O "$TGTDIR/${calname}.vcf" "https://oc.example.com:443/owncloud/index.php/apps/calendar/export.php?calid=$calid"
        done

        # git commit (quick and dirty history of changes)
        cd "$TGTDIR"
        git commit -a -m script-autocommit

  8. 21
    Chris says:

    When I try to download the calendards, I get the username / password form only. I don't want to setup .htaccess passwords to make sure that the other owncloud clients are still working. Do I have to change something in the Owncloud setup?

  9. 23
    chris says:

    I haven't tried it yet, but I guess it's the same as in the comment from February 11th 2013 at 19:35 Christian wrote. When I use another link Firefox asks for HTTP authentication.

  10. 24
    david carr says:

    great script. i have been using it for a year ever since i started using owncloud. i have been searching for hours about the new problem i have, which is WGET failing with a "GnuTLS: A TLS warning alert has been received."
    have you had any experience with this problem? it sounds like it might be related to a problem in WGET but im not sure.

4 Trackbacks