Skip to content

Restic upgrade on Debian Buster

A while ago I switched backups from "Duplicity" to "Restic". About time: I was using Duplicity for many years (I think I started using it around 2010, long before "Restic" became available) and it served me well. But recently I ran into more and more issues, especially with archives getting larger and larger. There is an 11 years old open bug in the Duplicity bugtracker, which describes a showstopper for backing up larger archives. And it doesn't look like this will be solved anytime soon. Therefore it was time for something new.

Since I'm rolling out my backups with Ansible, it was relatively easy to create a set of scripts for Restic which use almost the same infrastructure as the old Duplicity backups. That works as expected on all our laptops. But the Raspberry Pi, which does the fileserver backups, seem to had a problem. Backups took way longer than before, jumped from 30-60 minutes (depending on the amount of changes) to constantly around 10 hours.

After some investigation (means: --verbose --verbose --verbose debugging), it turns out that Restic identifies most of the files as new, even though they did not change at all. Some background information: the Raspberry mounts the QNAP fileserver using the SMB3 protocol. The "mount -t cifs" uses the "serverino" option, but apparently that is not enough to provide a stable inode number. And if the inode for a file changes, Restic assumes it is a new file.

On the bright side, because the content of the files do not change, the deduplication still works, and no additional content is added to the backup. The size of the backup does not increase. Still, Restic fetches all the data from the server, and that takes a long time.


Restic 0.9.6 has an option to work around that specific problem: "--ignore-inode". This option will ignore any changes in the file inode, and use other means to identify if the file changed or not.

Unfortunately the Raspbian on the Raspberry is based on Debian Buster (Stable, as of March 2020), and only ships Restic 0.9.4 - and that version does not have the "--ignore-inode" option.

I had to choose between updating everything to Testing (Bullseye), or figure out how to upgrade just one package.

The first step was checking the dependencies for the Restic package. The Restic in Bullseye depends only on "libc6 (>= 2.4)", and Buster already has libc6 in version 2.28. So that will work. The Bullseye version also suggests the packages "libjs-jquery" and "libjs-underscore", but does not add any versions - any installed version should do. Both packages are available in Buster. On the dependency side nothing is blocking a single package upgrade.

Debian is using a mechanism called "pinning" to specify which version can be installed from which source. By default, everything comes from the packages repository, and everything has the same priority. But this can be changed, by adding files to "/etc/apt/preferences.d/". Using my Ansible Playbook (I install the Raspberry using Ansible), I did the following:

- name: Install apt-pinning
    src: '{{ playbook_dir }}/files/apt-pinning.txt'
    dest: /etc/apt/preferences.d/50pinning.pref
    owner: root
    group: root
    mode: 0755
  register: apt_pinning

The "apt-pinning.txt" file has the following content:

# 500 <= P < 990: causes a version to be installed unless there is a
# version available belonging to the target release or the installed
# version is more recent

Package: *
Pin: release a=stable
Pin-Priority: 900

# 100 <= P < 500: causes a version to be installed unless there is a
# version available belonging to some other distribution or the installed
# version is more recent

Package: *
Pin: release a=testing
Pin-Priority: 400

Package: restic
Pin: release a=testing
Pin-Priority: 900

"stable" packages become a "900" priority, and "testing" packages a "400" priority. Only the "restic" package in "testing" has a "900" priority.

In order to use "testing" packages, Debian also needs to know where to get these packages from:

- name: Install raspi.list
    src: '{{ playbook_dir }}/files/raspi.list'
    dest: /etc/apt/sources.list.d/raspi.list
    owner: root
    group: root
    mode: 0755
  register: raspi_list

- name: Refresh cache
    update_cache: yes
  when: apt_pinning.changed or raspi_list.changed

An updated source list is installed, and when either the pinning file or the source list file changes, Ansible will update the apt cache. The source list file:

deb buster main
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src buster main

deb bullseye main
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src bullseye main

So far, so good. Last step: install the package from testing. Ansible allows to specify which release should be used for a package:

- name: basic packages
      - cifs-utils
      - vim
      - screen
      - jq
      - fuse
    state: present

- name: basic packages from testing
      - restic
    state: latest
    default_release: testing

After the Playbook ran, a quick version check shows:

root@raspberrypi:/root# restic version
restic 0.9.6 compiled with go1.13.4 on linux/arm

The runtime for the backup is now 30-45 minutes. That's expected.


No Trackbacks


Display comments as Linear | Threaded

BUFU on :

If you have restic 0.94.0 installed via apt-get or whatever you can simply issue the command "restic self-update" and it will update restic to the newest available stable version (as of now 0.12.0).
Comments ()

BUFU on :

Oh, forgot to mention: That works on restic version 0.9.3 and later.
Comments ()

Andreas 'ads' Scherbaum on :

That works, until the next time the OS installs an update - which might be a lower version because Debian/Ubuntu will only install bugfixes.
Comments ()

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
To leave a comment you must approve it via e-mail, which will be sent to your address after submission.
Form options