Appuyez sur Entrée pour voir vos résultats ou Echap pour annuler.

Installer Duplicity sur une Dédibox Debian Wheezy 7.6

Dans le cadre de l’application pour ostéopathe que nous développons avec un ami de 42, nous avons eu besoin de mettre en place une solution de sauvegarde automatique. Alors bien entendu, au vu de la nature des données, il était crucial de faire des sauvegardes qui seraient chiffrées pour éviter les regards indiscrets, mais sans complexité superflue. Étant en phase de start-up, nous avons une architecture encore légère et avec peu de besoins complexes, mon choix s’est donc porté sur des logiciels open-source (surtout qu’il est possible de corriger les bugs « au cas où »).

Pourquoi avoir choisi duplicity ?

Il existe des solutions de sauvegarde open-source professionnelles comme Bacula ou Amanda mais ces deux solutions sont des vrais monstres à configurer et à faire fonctionner selon ses besoins. Ce qui ne me plaisait pas avec Bacula est son système de fichiers propres, qui ne peut être utilisé avec un autre gestionnaire de sauvegardes. Et pour Amanda, son gestionnaire de sauvegarde est parait-il très intelligent mais il faut le laisser faire, et il s’occupe de gérer lui-même le type de sauvegarde (complète ou incrémentale) et les intervalles de sauvegarde.

Alors que dans notre cas, je voulais pouvoir configurer la sauvegarde avec des horaires précis (sauvegarde de nuit et le week-end, lorsqu’aucun ostéopathe ne travaille) et ainsi éviter les ralentissements en journée. Après quelques tests, mon choix s’est porté sur duplicity. Le projet est toujours actif et maintenu, il permet le chiffrement et la signature des archives et il reste simple à configurer à mettre en place et repose sur d’autres logiciels open-source (gpg, tar, rsync). Les données sont donc accessible même sans passer par duplicity. Mais trêve de bavardages, voyons comment installer et configurer le tout.

Instructions pour installer et configurer duplicity

Pour commencer, n’installez pas duplicity via aptitude ou apt-get. En effet, la version des dépôts n’en est qu’à la version 0.6.18 qui date de 2012 alors que la dernière version stable est la 0.6.25. Nous allons donc installer duplicity depuis le repo officiel.

Note rapide avant de commencer, pour savoir si je lance les commandes sur le serveur ou sur ma machine personnelle, regardez le prompt du shell. Si c’est ...@serveur, c’est le serveur et si c’est ...@perso, je suis sur ma machine personnelle 😉

1 – Installation des dépendances

Pour commencer, installons les dépendances, la plupart de ces package devraient déjà être installés sur votre Debian si vous avez installé et configuré d’autres logiciels avant. Dans tous les cas, voici la ligne magique:

achedeuzot@serveur ~ $ sudo apt-get update
[...]
achedeuzot@serveur ~ $ sudo apt-get install ncftp lftp libc6 librsync1 librsync-dev python python-crypto python-pycryptopp python-gnupginterface python-dev python-paramiko python-lockfile python-boto
[...]

2 – Installation de duplicity

Commençons par récupérer les sources puis nous allons passer quelques instants en utilisateur root (voir à ce sujets les commentaires).

achedeuzot ~ $ sudo su -
root@serveur ~ # cd /root
root@serveur ~ # wget https://code.launchpad.net/duplicity/0.6-series/0.6.25/+download/duplicity-0.6.25.tar.gz

Le lien ci-dessus fonctionne (sur code.launchpad.net), au cas où, voici un miroir: http://files.achedeuzot.me/mirror/duplicity-0.6.25.tar.gz

Nous allons maintenant les décompresser et les installer sur le système (toujours en étant root):

root@serveur ~ # tar xzvf duplicity*
[...]
root@serveur ~ # cd duplicity*
root@serveur ~/duplicity-0.6.25 # python setup.py install

Normalement, l’executable duplicity sera placé dans /usr/local/bin/ et est donc disponible immédiatement, je me permets donc d’effacer les sources qui ne nous servent plus à rien:

root@serveur ~/duplicity-0.6.25 # cd /root
root@serveur ~ # rm -rvf duplicity*
[...]
root@serveur ~ # exit
achedeuzot@serveur ~ duplicity --version

Duplicity 0.6 series is being deprecated:
See http://www.nongnu.org/duplicity/

duplicity 0.6.25

Pour effectuer le backup sur le serveur « spécial sauvegarde » de dedibox, nous utilisons du ftp, nous n’avons donc pas besoin de créer de clés ssh. Si vous en avez besoin, demandez moi dans les commentaires ;). Par contre, nous avons besoin de chiffrer nos sauvegardes, nous allons donc générer des clés GPG.

3 – Génération des clés GPG

3.1 – Où générer mes clés

Il est conseillé de générer vos clés de chiffrement sur une machine sûre (une distribution live comme Tails par exemple). Vous ne transfèrerez ensuite que les clés utiles pour duplicity pour la création des archives.

3.2 – Génération

Commençons par générer la clé pour le chiffrement, si vous générez vos clés sur votre machine, l’utilisateur n’est pas important. Par contre, si vous générez les clés directement sur le serveur, il faut être du même utilisateur que celui qui effectuera les sauvegardes (dans cet exemple: root) pour qu’elles soient disponibles lors du backup. Les clés seront stockées dans un dossier caché ~/.gnupg/.

achedeuzot@perso ~ $ gpg --gen-key
gpg (GnuPG) 1.4.12; Copyright (C) 2012 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: Klemen Sever
Email address: klemen[arobase]achedeuzot.me
Comment: Encryption Key
You selected this USER-ID:
    "Klemen Sever (Encryption Key) <klemen[arobase]achedeuzot.me>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.

Enter passphrase: [...]
Repeat passphrase: [...]

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 70BB2A5C marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   4  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 4u
gpg: next trustdb check due at 2015-08-18
pub   4096R/70BB2A5C 2014-12-09
      Key fingerprint = 1016 374E B941 1697 AF55  E78A 4681 8A02 70BB 2A5C
uid                  Klemen Sever (Encryption Key) <klemen[arobase]achedeuzot.me>
sub   4096R/CDC65005 2014-12-09

L’information à noter lors de la génération des clés est l’identifiant de la clé. Ici, la clé est 70BB2A5C, vous pouvez le voir 4 lignes avant la fin pub 4096R/70BB2A5C 2014-12-09.

Si jamais vous obtenez le message suivant

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 280 more bytes)

votre système a besoin de plus d’entropie pour générer des clés cryptographiquement sûres. Il vous suffit pour cela de « faire du bruit »: installer des paquets avec apt, surfer sur le web, vous connecter à une autre machine en SSH, bouger votre souris etc. Bien sûr, l’activité en question est à faire sur la machine où vous générez les clés, s’il s’agit de votre serveur, connectez-vous dessus avec un second shell et lancez des commandes.

Une autre précision. Il est recommandé de faire des clés avec expiration, pour l’exemple, je n’en ai pas fait. Vous pourrez toujours prolonger leur durée de vie si besoin avec la clé privée.

Si vous avez besoin de retrouver les informations sur les clés stockées, vous pouvez effectuer la commande gpg --list-keys et gpg --list-private-keys:

achedeuzot@perso ~ $ gpg --list-keys
/home/achedeuzot/.gnupg/pubring.gpg
------------------------------------
sub   4096R/70BB2A5C 2014-12-09
uid                  Klemen Sever (Encryption Key) <klemen[arobase]achedeuzot.me>
sub   4096R/CDC65005 2014-12-09
achedeuzot ~ $ gpg --list-secret-keys
/home/achedeuzot/.gnupg/secring.gpg
sec   4096R/70BB2A5C 2014-12-09
uid                  Klemen Sever (Encryption Key) <klemen[arobase]achedeuzot.me>
ssb   4096R/CDC65005 2014-12-09

Nous venons de générer des clés pour le chiffrement des archives. Nous aurons aussi à les signer. La procédure est exactement la même pour générer les clés de signature. Je vous invite donc à refaire la même procédure pour générer une seconde clé et n’hésitez pas à mettre un commentaire différent pour les différencier facilement. Notez son identifiant à 8 chiffres également car nous en aurons besoin.

3.3 – Transférer vos clés et mettre à jour leur confiance

Une fois vos clés générées sur votre machine, il va falloir les transférer. Pour cela, il faut d’abord les exporter depuis gpg:

achedeuzot@perso ~ $ gpg --export --armor 70BB2A5C > ~/encryption.asc
achedeuzot@perso ~ $ gpg --export-secret-key --armor 64A984D1 > ~/signing.asc

Nous exportons seulement la clé publique pour le chiffrement, en effet, nous aurons besoin seulement de chiffrer les données de sauvegarde, pas de les déchiffrer (sauf pour les tests et en cas de catastrophe). Par contre, nous avons besoin de la clé privée pour signer les archives, il faut donc exporter la clé privée.

Il nous faut ensuite les transférer sur le serveur, via un simple scp:

achedeuzot@perso ~ $ scp ~/encryption.asc achedeuzot@example.com:/tmp
achedeuzot@perso ~ $ scp ~/signing.asc achedeuzot@example.com:/tmp

Et enfin, nous devons les importer dans le gpg du serveur (et de les supprimer du dossier /tmp, surtout la clé privée):

achedeuzot@serveur ~ $ sudo su -
root@serveur ~ # gpg --import /tmp/encryption.asc
root@serveur ~ # gpg --import /tmp/signing.asc
root@serveur ~ # rm -vf /tmp/encryption.asc
root@serveur ~ # rm -vf /tmp/signing.asc

Une dernière chose avant de configurer duplicity. Il faut mettre à jour la confiance (trust) des clés sur le serveur. Car si vous n’effectuez pas cela, vous obtiendrez l’énigmatique erreur suivante pendant la sauvegarde.

gpg: 70BB2A5C: There is no assurance this key belongs to the named user
It is NOT certain that the key belongs to the person named
in the user ID. 

Vérifions donc et corrigeons la confiance des clés si besoin.

root@serveur ~ # gpg --edit-key 70BB2A5C
gpg (GnuPG) 1.4.12; Copyright (C) 2012 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

pub  4096R/70BB2A5C  created: 2014-12-09  expires: never       usage: SC
                     trust: unknown     validity: unknown
sub  4096R/CDC65005  created: 2014-12-09  expires: never       usage: E
[ unknown] (1). Klemen Sever (Encryption Key) <klemen[arobase]achedeuzot.me>

gpg> trust
pub  4096R/70BB2A5C  created: 2014-12-09  expires: never       usage: SC
                     trust: unknown     validity: unknown
sub  4096R/CDC65005  created: 2014-12-09  expires: never       usage: E
[ unknown] (1). Klemen Sever (Encryption Key) <klemen[arobase]achedeuzot.me>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y

pub  4096R/70BB2A5C  created: 2014-12-09  expires: never       usage: SC
                     trust: ultimate      validity: unknown
sub  4096R/CDC65005  created: 2014-12-09  expires: never       usage: E
[ unknown] (1). Klemen Sever (Encryption Key) <klemen[arobase]achedeuzot.me>
Please note that the shown key validity is not necessarily correct
unless you restart the program.

gpg> quit
root@serveur ~ # gpg --edit-key 70BB2A5C
gpg (GnuPG) 1.4.12; Copyright (C) 2012 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   4  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 4u
gpg: next trustdb check due at 2015-08-18
pub  4096R/70BB2A5C  created: 2014-12-09  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/CDC65005  created: 2014-12-09  expires: never       usage: E
[ultimate] (1). Klemen Sever (Encryption Key) <klemen[arobase]achedeuzot.me>
gpg> quit

Notre clé est maintenant de confiance dans gpg et pourra être utilisée pour chiffrer les archives. Il faut bien entendu faire de même pour la clé qui sert de signature. La procédure est exactement la même.

4 – Configuration de duplicity

Nous approchons de la fin ! Plus qu’un petit script bash à réaliser qui lancera les commandes pour nous et ce sera terminé. La configuration qui suit est très simple mais suffit amplement pour nos besoins. Cette configuration est pour l’instant à l’état de test chez nous, que nous changerons si besoin.

Duplicity reconnait les variables PASSPHRASE pour la clé de chiffrement et SIGN_PASSPHRASE pour la clé de signature. Vous pouvez trouver tous les détails dans le man de duplicity. Enfin, pour l’accès ftp, nous utilisons la variable FTP_PASSWORD. Si des parties ne sont pas limpides, n’hésitez pas à demander des précisions via les commentaires.

root@serveur ~ # vim ~/backup.sh
#/bin/sh

export PASSPHRASE="mot de passe clé chiffrement"
export SIGN_PASSPHRASE="mot de passe clé de signature"
export FTP_PASSWORD="mot de passe serveur ftp de sauvegarde"
ENCRYPTION_KEY='70BB2A5C' # Identifiants des clés de chiffrement gpg
SIGNING_KEY='64A984D1'

## Scripts ou commandes à effectuer avant sauvegarde: dumps MySQL, ...
## 
## Sauvegarde du système
duplicity --verbosity notice \
    --log-file /var/log/duplicity.log \
    --full-if-older-than 2W \    # 2W = 2 Weeks, c'est à dire une sauvegarde
    --sign-key "$SIGNING_KEY" \  # complète toutes les 2 semaines (Weeks)
    --encrypt-key "$ENCRYPTION_KEY" \
    --exclude /sys \     # Exclure les dossiers "inutiles"
    --exclude /dev \
    --exclude /proc \
    --exclude /tmp \
    --exclude /mnt \
    --exclude /media \
    --exclude /var/tmp \
    / ftp://@backup.example.com/duplicity/

## Vous pouvez lancer plusieurs sauvegardes différentes si besoin
## Une pour le système, une pour vos applications, une autre pour la base de donnée, ...
## Ou vers diverses destinations: serveur FTP dans le même datacenter, Amazon S3, ...

## Nettoyage des variables -- IMPORTANT --
unset PASSPHRASE
unset SIGN_PASSPHRASE
unset FTP_PASSWORD

Ce fichier de configuration est assez basique et ne concerne que la sauvegarde. Pour la restauration ou la vérification, je vous invite à consulter la syntaxe de la ligne de commande sur le man de duplicity (en anglais). Je suis également tombé sur un script shell qui peut faire bien plus que mon exemple ci-dessus: duplicity-backup.sh. Malheureusement, il ne vous évite pas toutes les étapes de configuration ci-dessus.

Comme vous pouvez le constater, la liste des --exclude est plutôt longue. J’ai tenté de rendre la commande plus propre en utilisant l’option --exclude-filelist mais j’obtenais constamment une erreur étrange car duplicity essayait de lire mon fichier de configuration deux fois. Bref, si vous trouvez comment faire, faites moi signe !

Pour terminer, protégeons le fichier grâce à chmod (il contient tout de même les mots de passe des clés GPG en clair!), puis testons si tout se lance comme prévu et enfin, ajoutons-le dans le cron.

root@serveur ~ # chmod 700 /root/backup.sh
root@serveur ~ # ./backup.sh
[...]
root@serveur ~ # crontab -e

Et voilà !

Si vous avez des remarques ou améliorations à suggérer, n’hésitez pas à le faire dans les commentaires ou via twitter. Si vous souhaitez que je développe d’autres parties, faites-le moi savoir 😉

Bonne sauvegarde à tous et que le Dieu-des-octets vous les garde 😀 !