Duplicity — консольная утилита, которая делает инкрементальные архивы, шифрует их через GnuPG и отправляет на удалённый сервер по sftp, rsync, S3 или WebDAV. Ей не нужен агент на приёмнике и отдельная база данных: достаточно SSH-доступа и места на диске. В Ubuntu 24.04 и Linux Mint 22 поставляется ветка 2.1.x, которой хватает для домашнего сервера и небольшого офиса. Ниже — рабочая схема от создания ключа до проверки восстановления.
Как устроен архив
Duplicity не копирует каждый раз всё дерево. Первый запуск создаёт полный набор томов duplicity-full.*, а последующие — инкременты duplicity-inc.*, в которых лежат только изменившиеся блоки файлов, посчитанные librsync. Каждый инкремент опирается на предыдущий, поэтому архив — это цепочка, а не набор независимых файлов.
- Полный набор создаётся при первом запуске и далее по —full-if-older-than, например раз в месяц.
- Размер тома задаёт —volsize; по умолчанию 200 МБ, для sftp это разумный компромисс.
- Шифрование включается —encrypt-key для асимметричной схемы или переменной PASSPHRASE для симметричной.
- Дедупликации между файлами нет: экономия достигается за счёт дельт librsync, но не за счёт общего хранилища блоков.
Практический вывод: Duplicity удобен, когда нужно складывать каталоги на чужой SSH-сервер и не хочется ставить туда отдельное приложение. Для сотен гигабайт с длинной историей выгоднее restic или borg, зато Duplicity проще в минимальной конфигурации.
Ключ и установка
Пакет ставится одной командой, вместе с ним нужен GnuPG. Ключ лучше создать на отдельной машине, а на сервер перенести только публичную часть: тогда компрометация сервера не даст прочитать архив.
sudo apt update
sudo apt install duplicity gnupg
duplicity --version
gpg --list-keys --with-colons
Для воспроизводимой генерации используем batch-файл: он создаёт первичный ключ подписи и подключ шифрования без интерактивных вопросов.
cat > backup-key.conf <<'EOF'
%no-protection
Key-Type: RSA
Key-Length: 3072
Key-Usage: sign
Subkey-Type: RSA
Subkey-Length: 3072
Subkey-Usage: encr
Name-Real: Backup Server
Name-Email: backup@example.lan
Expire-Date: 0
%commit
EOF
gpg --batch --generate-key backup-key.conf
gpg --armor --export backup@example.lan > backup-pub.asc
Директива %no-protection означает ключ без пароля. Секретный ключ в таком виде нельзя держать на боевом сервере: запишите его на отдельный носитель и уберите в сейф. На сервер импортируется только backup-pub.asc, а отпечаток берётся из gpg —fingerprint.
Первый архив и расписание
Двойной слэш в sftp-URL означает абсолютный путь на приёмнике: один слэш отделяет хост, второй начинает путь. Исключения принято ставить до исходных каталогов, иначе они не сработают.
duplicity --full-if-older-than 1M \
--encrypt-key 0123456789ABCDEF \
--volsize 200 \
--exclude '**/.cache' \
--exclude '**/node_modules' \
/home /srv/data \
sftp://backup@nas.lan//srv/backup/duplicity
Первый прогон создаёт полный архив и может занять часы. Дальше запуск занимает минуты, если объём изменений небольшой. Расписание удобнее держать в systemd: виден результат, журнал и ограничения по ресурсам.
[Unit]
Description=Duplicity backup
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/etc/duplicity/backup.env
ExecStart=/usr/local/bin/duplicity-run.sh
Nice=10
IOSchedulingClass=idle
В backup.env лежат PASSPHRASE для симметричной схемы и параметры SSH, права — 600, владелец — root. Таймер с OnCalendar=daily и Persistent=true догоняет пропущенный запуск после включения машины.
Восстановление и проверка
Все действия выполняются с тем же URL и теми же ключами. Начните с collection-status: команда покажет цепочки, даты и число томов, не скачивая данные.
duplicity collection-status sftp://backup@nas.lan//srv/backup/duplicity
duplicity list-current-files --time 2026-10-01 sftp://backup@nas.lan//srv/backup/duplicity
duplicity restore --path-to-restore srv/data/report.ods --time 2026-10-01 \
sftp://backup@nas.lan//srv/backup/duplicity /tmp/restore
duplicity verify --compare-data --time 2026-10-01 \
sftp://backup@nas.lan//srv/backup/duplicity /srv/data
Путь в —path-to-restore задаётся относительно корня архива, а не от / на диске. Файл попадёт в /tmp/restore с сохранением структуры каталогов. Verify без —compare-data проверяет только целостность томов и подписей; с —compare-data он дополнительно сверяет содержимое с указанным каталогом, поэтому занимает столько же времени, сколько чтение всего архива.
Обслуживание цепочки
Удалять инкременты вручную нельзя: пропавший средний том ломает восстановление всех последующих. Чистку выполняют только штатные команды, которые пересчитывают зависимости.
duplicity remove-older-than 6M --force sftp://backup@nas.lan//srv/backup/duplicity
duplicity remove-all-but-n-full 3 --force sftp://backup@nas.lan//srv/backup/duplicity
duplicity cleanup --force sftp://backup@nas.lan//srv/backup/duplicity
duplicity -v9 backup /etc sftp://backup@nas.lan//srv/backup/etc-test
Без —force команды лишь печатают план. cleanup убирает незавершённые файлы после сбоя и не трогает валидные наборы. Если архив уже повреждён, сначала скопируйте каталог целиком и экспериментируйте на копии, иначе есть шанс потерять последнюю рабочую цепочку.
Что архив не заменит
Duplicity читает файлы на работающей системе, поэтому открытая база данных или виртуальная машина попадёт в копию в несогласованном состоянии. Для PostgreSQL сначала делайте pg_dump, для виртуальных машин — снимок средствами гипервизора. Каталоги /proc, /sys, /dev и сетевые монтирования исключайте: вне работающей системы они бессмысленны. Если нужен снимок большого каталога, снимите LVM-снапшот и копируйте уже его. Флаг —exclude-other-filesystems не даст перейти на чужие диски, а файл .nobackup в каталоге позволяет исключить этот каталог через —exclude-if-present.
Диагностика
- «Permission denied» на sftp: проверьте sftp -v backup@nas.lan и права на каталог приёмника.
- Обрыв на середине: чаще всего место или таймаут. Смотрите df -h на NAS и добавьте ServerAliveInterval в ~/.ssh/config.
- Ошибка GPG: неверный отпечаток, истёкший ключ или отсутствует секретный ключ при восстановлении.
- Долгий первый прогон: нормально; не запускайте его одновременно с индексацией файлов.
Результат последнего запуска виден в journalctl -u duplicity.service -n 100 —no-pager, а код возврата — в systemctl show -p Result. Для разбора поднимайте детализацию до -v9, но не оставляйте её постоянно: журнал разрастётся.
Чек-лист
- Секретный ключ хранится отдельно от сервера, публичный импортирован.
- Полный архив создаётся раз в месяц, старые цепочки удаляются штатно.
- Раз в месяц выполняется verify, раз в квартал — пробное восстановление.
- Копия архива лежит на втором носителе.
- Базы данных выгружаются отдельно: открытые файлы Duplicity не гарантирует.
Итог
Duplicity остаётся рабочим инструментом для шифрованных инкрементальных копий по SSH: понятная модель цепочек, минимум зависимостей и прозрачное восстановление. Главное — не относиться к инкрементам как к независимым файлам и не экономить на проверке. Настройте полный архив раз в месяц, автоматизируйте запуск через systemd, храните ключ отдельно и раз в квартал восстанавливайте данные на тестовую машину. Тогда архив станет реальной страховкой, а не формальностью.