How-To Backup Gmail with OfflineImap

Gmail’s content can be retrieved via IMAP, and we’ll use this way to backup all our mails thanks to OfflineImap, a generic IMAP synchronization utility.

Let’s start by creating a dedicated configuration file in your home directory. Its content is quite straight-forward, as you can see in my /home/kevin/.offlineimaprc, which backup two Gmail accounts:

[general]
accounts = gmail_account1, gmail_account2
maxsyncaccounts = 3
ui = Noninteractive.Basic

[Account gmail_account1]
localrepository = gmail_account1_local
remoterepository = gmail_account1_remote

[Repository gmail_account1_local]
type = Maildir
localfolders = ~/gmail-backup-account1

[Repository gmail_account1_remote]
type = IMAP
remotehost = imap.gmail.com
remoteport = 993
remoteuser = account1@gmail.com
remotepass = XXXXXXXX
ssl = yes
maxconnections = 1
realdelete = no
folderfilter = lambda foldername: foldername not in ['[Gmail]/%s' % f for f in ['All Mail', 'Trash', 'Spam', 'Starred', 'Important']]

[Account gmail_account2]
localrepository = gmail_account2_local
remoterepository = gmail_account2_remote

[Repository gmail_account2_local]
type = Maildir
localfolders = ~/gmail-backup-account2

[Repository gmail_account2_remote]
type = IMAP
remotehost = imap.gmail.com
remoteport = 993
remoteuser = account2@gmail.com
remotepass = XXXXXXXX
ssl = yes
maxconnections = 1
realdelete = no
folderfilter = lambda foldername: foldername not in ['[Gmail]/%s' % f for f in ['All Mail', 'Trash', 'Spam', 'Starred', 'Important']]

Notice how we use a Python lambda expressions to filter out some Gmail’s virtual folders.

Then all you have to do is to launch the offlineimap command-line itself with the right user, for example in a cron job:

00 20 * * * kevin offlineimap

A final warning: OfflineImap is fully bi-directional. This mean local deletion propagates to the remote server. This is can be quite dangerous so be careful not touching your local folders. If for any reason you’d like to reset your backups, stop OfflineImap processes first, then remove its cache folder (~/.offlineimap/) before removing the local folders themselves (~/gmail-backup-account*).

Also, intensively playing with OfflineImap to adjust its configuration may trigger the infamous Gmail’s “Temporary Error 500″. In this case don’t panic: it seems to be a common Gmail’s auto-immune response against suspect activity. It happened to me and in the end my account and mails were safe: I just had to wait a few hours to let it resume normal operations.

Dump, backup and restore a PostgreSQL database

Between user rights, permissions, templates and encoding, believe me or not, but I had some troubles finding a consistent procedure to dump, backup and restore a PostgreSQL database. That’s expected as I’m new to this RDBMS.

So here is the sequence of commands I use to dump a database from a server and copy it to another:

postgres@source-server:~$ pg_dump my_db -v --format=c --file=./my_db_2011-11-23.dump
postgres@source-server:~$ scp ./my_db_2011-11-23.dump postgres@dest-server:~/

Before importing the dump to a new database:

postgres@dest-server:~$ createdb -E UTF8 -T template0 new_db
postgres@dest-server:~$ pg_restore -U my_user -d new_db ./my_db_2011-11-23.dump
postgres@dest-server:~$ psql --command "ALTER DATABASE new_db OWNER TO my_user;"

This hasn’t failed me yet, and I’ll update that post if it will.

Cloud-based Server Backups with Duplicity and Amazon S3

For years I was backing up my server with website-backup.py, a custom script I wrote to manage data mirroring, do incremental backups and monthly snapshots based on rdiff-backup, rsync, tar and bzip2. All these data were pushed to a storage server hosted at home.

I’ve just replaced my script with duplicity, a tool written by the same author of rdiff-backup. And Amazon S3 cloud storage replaced my home server. Here is how I did it.

First, we need to create an account on Amazon AWS. This is easy and fast. My account was activated in minutes.

Now that you have access to Amazon’s cloud, let’s create a bucket on S3. I used the reversed domain name of the server, which give me a bucket name like com.example.server.backup. With this naming scheme, I can identify the purpose of the bucket by its label only.

Duplicity can use the cheaper RRS storage, but you need at least version 0.6.09. Having a Debian Squeeze, the only way to get a recent version is to install it from the backports:

$ apt-get -t squeeze-backports install duplicity python-boto

Then I created a simple symmetric key with GPG:

$ gpg --gen-key

You absolutely need to provide a passphrase, else Duplicity will refuse to run.

Now update the script below with the GPG key passphrase and your AWS credentials:

# Do not let this script run more than once
[ `ps axu | grep -v "grep" | grep --count "duplicity"` -gt 0 ] && exit 1

# Set some environment variables required by duplicity
export PASSPHRASE=XXXXXXXXXX
export AWS_ACCESS_KEY_ID=XXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXX

# ~/.cache/duplicity/ should be excluded, as explained in http://comments.gmane.org/gmane.comp.sysutils.backup.duplicity.general/4449
PARAMS='--exclude-device-files --exclude-other-filesystems --exclude **/.cache/** --exclude **/.thumbnails/** --exclude /mnt/ --exclude /tmp/ --exclude /dev/ --exclude /sys/ --exclude /proc/ --exclude /media/ --exclude /var/run/ --volsize 10 --s3-use-rrs --asynchronous-upload -vinfo'
DEST='s3+http://com.example.server.backup'

# Export MySQL databases
mysqldump --user=root --opt --all-databases > /home/kevin/mysql-backup.sql

# Do the backup
duplicity $PARAMS --full-if-older-than 1M / $DEST

# Clean things up
duplicity remove-older-than 1Y --force --extra-clean $PARAMS $DEST
duplicity cleanup --force $PARAMS $DEST

# Remove temporary environment variables
unset PASSPHRASE
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY

Before running duplicity, the script will dump all MySQL databases to a plain-text file. Then the first duplicity call will do the backup itself, and the second call will remove all backup older than a year.

I saved the script above in /home/kevin/s3-backup.sh and cron-ed it:

$ chmod 755 /home/kevin/s3-backup.sh
$ echo "
# Backup everything to an Amazon S3 storage
0 1 * * * root /home/kevin/s3-backup.sh
" > /etc/cron.d/s3-backup

I can now sleep better knowing all the work I do on my server will not be lost in case of a catastrophic event. Amazon S3 is today a no-brainer for server backups: your data will be secured and available. And for small quantity of data (like the 10 Go of my server), it’s incredibly cheap. Especially if you compare it to the cost of maintaining a storage server at home.

This solution is so good and obvious, that I don’t know why I haven’t implemented it earlier… :)

How-to extract data trapped into an iPhone

After 2 years using an iPhone 3G, it’s time for me to switch to the Android world. My Apple era is over, I need a plateform that is more linux and open-source friendly.

Before erasing and selling my iPhone, I want to backup and extract all the data I produced with it and that is still trapped inside. This mean photos, SMSs, voice messages, safari bookmarks, etc…

There is a nice OSX app simply called iPhone Backup Extractor which let you get these data. Instead of getting data directly from the iPhone, it reads its backups made by iTunes.

So first thing you have to do is to backup your phone using iTunes:

Then you can download and run the iPhone Backup Extractor app:

Here you just have to click the Read Backups button to get a list of all backups available on your machine. Then choose your latest backup:

You’ll get a list of all installed applications on your iPhone. As we are interested in “core” iPhone apps (SMSs, photos and so on), we’ll choose the “iOS Files” item, then choose a place where to extract:

Then the extraction itself will take place:

You’ve just finished the essential part of the process. You now have a nice folder structure containing all the important informations that was trapped in your phone:

Let’s browse the file structure that was just created. You can see photos are available as is, in the /iOS Files/Media/DCIM/XXXAPPLE/:

Most of other datas are located in the /iOS Files/Library/ folder. For example here are voice messages:

Again, .amr files here are playable as-is, like VLC or mplayer.

And finaly most, if not all, other kind of data and metadata are stored in SQLite databases (.db files). The best GUI I found to manipulate with these files under Mac OSX is SQLite Database Browser. See how I can easily extract to a CSV file all metadatas associated with my voice messages:



How-to export/backup Lotus Notes mails

You are using Lotus Notes as your mail platform. Unfortunately your mailbox has a quota you’ve already reached and you need space. A solution consist in exporting regularly your mails on your local machine to free up your inbox. Here is a little article documenting the export procedure using the fat desktop client.

If screenshots were taken with a french version, instructions given here are for the english one. This will give you enough clues to perform the export whatever the localisation is. The Lotus Notes version I used was the 7.0.2 release.

So first, let’s start Notes and open your mailbox. You should be on a screen similar to this one:

Then, go to the FileDatabaseNew Copy menu:

And you’ll get an export screen that’ll let you choose where to create a local copy of your database:

This will generate a .nsf file containing all your current mail.

Now that you have a backup, you are free to delete all your mails in Lotus Notes. By following this procedure regulary, you can create yearly or monthly archives of you mails without reaching the mailbox quota ! For example, this is how my local archive folder looks like:

Auto-saving a file at regular intervals

editing-cron-with-vi Here is a way to autosave a file at regular intervals: use cron !

The trick is to know that cron need percents to be escaped by a backslash in the command zone. For example, here is my crontab entry to create every 10 minutes a local backup of an important project file I currently work on:

*/10 * * * * kevin cp "/home/kevin/Desktop/Projects/Very Important Project/project.file" "/home/kevin/Desktop/Projects/Very Important Project/project.file-backup-`date +\%s`"

Quick and dirty, but may saves you precious time on unstable machines ! ;)