Backup up Subversion

Overview

This HOWTO covers the creation of hot copies of Subversion repositories. The master server sends the hot copy to a slave server which checks the hot copy into a test repository and checks it out to ensure the hot copy works. Once it verifies the hot copy, it compresses the hot copy and removes all but the last ten copies.

Both machines must be running subversion. The below example shows how to load install subversion on a RedHat based system.

# yum install subversion


Setting up the master server

Installing backup-svn

First we need to install the backup-svn program, which creates an svndump file and sends it via SSH to the slave server.

# mkdir -m 700 /root/bin
# cd /root/bin
# wget -c http://www.antagonism.org/scripts/backup-svn
# chmod 700 backup-svn
# chown root.root backup-svn

Generating SSH keys

Next we need to generate an SSH key pair to allow the master server the ability to log into the slave server without a password. Do not use an existing SSH key pair as this defeats the security model this HOWTO uses. In case of compromise of this SSH key pair, the worst the attacker can do is execute the svn-backup-check script.

On creating the key pair, ssh-keygen will prompt you for a passphrase. When it does, just hit ENTER when it asks. You DO NOT want to create a passphrase on the private key. If you do, every time you run the backup-svn script, it prompt for the passphrase for the slave server. This while providing more security will also remove the ability to automate the solution. As long as the private key is not compromised, the solution should remain secure.

# cd /root/.ssh
# ssh-keygen -t dsa -b 1024 -f id_dsa_svnbackup -C 'svn backup key'
Generating public/private dsa key pair.
Enter passphrase (empty for no passphrase): Just hit ENTER
Enter same passphrase again: Just hit ENTER again
Your identification has been saved in id_dsa_svnbackup.
Your public key has been saved in id_dsa_svnbackup.pub.
The key fingerprint is:
8c:04:2c:f4:a4:c4:8d:6f:eb:aa:f4:f9:76:13:1a:f0 svn backup key
Note: your key fingerprint will almost certainly be different from the example shown here.
# chmod 600 id_dsa_svnbackup

This creates two files, "id_dsa_svnbackup", the private key file and "id_dsa_svnbackup.pub", the public key. The last command in the above example ensures no one but root can read the private key.


Setting up a slave server

Configure sshd to support logins with public keys

sshd must support public key authenication. In order to do so, the below line must be included in the sshd_config file.

PubKeyAuthentication yes

If the above line was not present, you must restart the SSH service. The commands to do will vary from system to system. The below example demonstrates this procedure on CentOS, a RedHat EL clone.

# /etc/init.d/sshd restart
Stopping sshd:     [ OK ]
Starting sshd:     [ OK ]

Install the delbut script

svn-backup-check relies on the delbut. delbut deletes all but the newest number of files specified by the first argument supplied to it. John Simpson wrote delbut and as such you will need his GPG key to verify delbut's signature. The download listed below for delbut is valid for the file as of May 20, 2008. Please check John's code page for the latest download block.

# cd /usr/local/bin
# wget -c http://www.jms1.net/code/delbut
# chmod 755 delbut
# chown root.root delbut

Create the SVN slave user

We need to create a user for the master server to log in as. The name of the user should match the match the $USER in the backup-svn script on the master server.

# useradd svnbackup
New UNIX password:
Retype new UNIX password:

The below section quotes directly for John Simpson's tinydns replication page.

"The next step is to "lock" the passwords of these users. We will do this by replacing the users' encrypted passwords with one or more characters which cannot be part of an encrypted password. For example, the unix crypt() function generates results consisting of upper- and lower-case letters, digits, and the characters "." and "/". If we use one or more "@" characters in the encrypted password, it becomes physically impossible for ANY password to encrypt to that value.

However, we need to be careful in the characters we choose. On most systems, the "!" character means that the account is "locked", and will prevent sshd from allowing that userid to log in, even if they authenticate using a key. On many systems, the "*" character serves as a flag that the user's encrypted password is stored in an NIS database. I'm not aware of "@" having any special meaning, therefore that's what I use.

Most systems provide a command which allows you to manually set a user's encrypted password. Most Linux machines have a "usermod" command, and the *BSD systems have a "chpass" command. Check the documentation on your system, and make sure you understand what you're doing, before using these commands."

For a CentOS system:
# usermod -p '$1$xxxxxxxx$@@-NO-REAL-PASSWORD-@@' svnbackup

Install the svn-backup-check script

We need to install the svn-backup-check program. The program will read the svndump file from STDIN, load it in a test repository, check it out to ensure it loaded correctly, remove the test repository, compresses the svndump file, and stores the last 10 backups.

# cd ~svnbackup
# wget http://www.antagonism.org/scripts/svn-backup-check
# chmod 700 svn-backup-check
# chown svnbackup.svnbackup svn-backup-check

Test the svn-backup-check script

You can test the svn-backup-check script by copying a svndump from the master server by hand using whatever methods you deem necessary. The below example assumes the svndump file is located in the svnbackup's home directory on the slave server.

% cd ~
% mkdir svn_backups
% ./svn-backup-check < svn-backup
Creating test repository
Loading repository
Checking out repository
Cleaning up repository
Compressing svn-backup with timestamp
Cleaning up old backups

Install the ssh public key

We need to the "forced command" to the public key file. A "forced command" only allows the user logging into the system with the private key to execute the "forced command". This prevents them from gaining full access to the system. In the below example, the svnbackup user's home directory is /home/svnbackup. Be sure to change it to fit your system accordingly.

The file already contains...
ssh-dss AAAAB3NzaC1kc3MAAACBAN65...ep/8= svn backup key

Add to the beginning:
command="/home/svnbackup/.ssh/svn-backup-check" AAAAB3NzaC1kc3MAAACBAN65...ep/8= svn backup key

Create the authorized_keys file

Upon adding the forced command to the public key file, you should install the public key file as ~svnbackup/.ssh/authorized_keys within the svnbackup user's home directory.

# cd ~svnbackup
# mkdir -m 700 .ssh
# chown svnbackup.svnbackup .ssh
# mv id_dsa_svnbackup.pub .ssh/authorized_keys
# chown svnbackup.svnbackup .ssh/authorized_keys
# chmod 600 .ssh/authorized_keys

You need to move svn-backup-check to the .ssh directory as listed in the public key.

# mv svn-backup-check .ssh/

Testing the data transfer

On the master server, run the below command. You should see it connect to the slave server, create the test repository, load the svndump, check out the repository, clean up the repository, compress the svndump and remove any old backups.

On the "master" machine
# /root/bin/backup-svn
/---- Start of messages from 1.2.3.4
Creating test repository
Loading repository
Checking out repository
Cleaning up repository
Compressing svn-backup with timestamp
Cleaning up old backups
/---- Start of messages from 1.2.3.4


Downloads

File: delbut
Size: 2,184 bytes
MD5: a761945725f32869a3fb856dfabeff6c
SHA-1: 0131b3d9f048dee27c4ac2e834811366f816051e
RIPEMD-160: 2000ab1f1fb43300ce2235557c12e1dcf1821d0e
PGP Signature: delbut.asc
File: backup-svn
Size: 2,084 bytes
Date: 2008-05-22 12:44:37 -0700
MD5: 2ed1a81b208106d6493b0f4d10d1d0a7
SHA-1: 903c4eaf7841845013931d1ba08ec63490ec796c
RIPEMD-160: f54664c565aa60d279134dfe521357f180b883a1
PGP Signature: backup-svn.asc
File: svn-backup-check
Size: 1,696 bytes
Date: 2008-05-22 12:46:54 -0700
MD5: a77d664d52f9856033538396e9d7a3e3
SHA-1: 0c225baec2bbc97e082ec0b1952983cd006dfefe
RIPEMD-160: d2fe10f82028dd90fd8a295027502d469d1931df
PGP Signature: svn-backup-check.asc