Introduction
My backup server ran Debian 11 with rdiff-backup 2.0.5. It had to back up clients running the same OS version (obviously not a problem) and clients running Debian 12 with rdiff-backup 2.2.2, which I solved by using the virtualenv
command to download and compile rdiff-backup 2.0.5 and then use that to communicate with the Debian 12 clients.
However, recently, I upgraded my backup server to Debian 12 with rdiff-backup 2.2.2. It still has to back up the same clients, which means it has to back up clients running the same OS version (obviously not a problem) and clients running Debian 11 with rdiff-backup 2.0.5, which I solved, but which was more troublesome than it should have been!
Firstly, I expected virtualenv
to have been able to do this, but it could not compile rdiff-backup, producing the errors:
src/_librsyncmodule.c:543:36: error: lvalue required as left operand of assignment 543 | Py_TYPE(&_librsync_SigMakerType) = &PyType_Type; | ^ src/_librsyncmodule.c:544:38: error: lvalue required as left operand of assignment 544 | Py_TYPE(&_librsync_DeltaMakerType) = &PyType_Type; | ^
This bug has been reported in a few places (e.g. here and here).
Secondly, I hoped virtualenv
could build its own python version, but it seems that virtualenv
and other similar tools will build modules against an already-installed python, but they will not build a new python.
Thirdly, I downloaded the sources for the version of python that comes with Debian 11, which was 3.9, and although I could compile that, I could not then use its pip3
to build rdiff-backup.
Finally, I tried debootstrap
, which was suprisingly easy!
Procedure
- Create a suitable directory to host rdiff-backup 2.0.5, let’s call it $CHROOT_DIR:
CHROOT_DIR=<whatever> mkdir -p $CHROOT_DIR
- Install debootstrap, if it is not already installed:
apt-get -y install debootstrap
- Populate it with a minimal Debian 11 (bullseye) installation and give it a copy of /proc and /sys so that more commands work:
debootstrap --arch amd64 bullseye $CHROOT_DIR \ http://deb.debian.org/debian/ > /dev/null mount -t proc proc $CHROOT_DIR/proc mount -t sysfs sysfs $CHROOT_DIR/sys cp /etc/hosts $CHROOT_DIR/etc/hosts # debootstrap shouldn't have created /etc/mtab # in the chroot env, but let's be sure! rm -f $MY_CHROOT/etc/mtab ln -s ../proc/self/mounts $MY_CHROOT/etc/mtab
- At this point we can install rdiff-backup in the chroot:
chroot $CHROOT_DIR /bin/bash -c "apt-get -y install rdiff-backup"
- rdiff-backup refers to python3.9 inside the chroot …
damson# grep '#!' $CHROOT_DIR/usr/bin/rdiff-backup #!/usr/bin/python3 damson#
… so – as it stands – it will only work if we chroot into $CHROOT_DIR and run it there, but in such an environment it won’t be able to access any backup media, which are probably mounted outside $CHROOT_DIR! So we need to change that ‘
#!
‘ path to refer to the python inside $CHROOT_DIR but to refer to it in such a way that we call it from outside $CHROOT_DIR. We do this by running:sed -i "s@/usr/bin/python3@$CHROOT_DIR/usr/bin/python3@" $CHROOT_DIR/usr/bin/rdiff-backup
- Unmount the copy of /proc and /sys, which are no longer needed:
umount $CHROOT_DIR/sys umount $CHROOT_DIR/proc
- Verify that it basically works and reports the right version:
damson# $CHROOT_DIR/usr/bin/rdiff-backup --version rdiff-backup 2.0.5 damson#
- Obviously you should also verify that it actually can successfully back up and restore stuff, which I did, but explaining that is outside the scope of this short procedure.