Автоматический бэкап домашнего сервера: restic и таймер systemd
Ночное резервное копирование с шифрованием и историей снимков: restic, служба и таймер systemd, выгрузка базы данных перед копией, проверка восстановления. Всё проверено на чистом Debian 12.
Сначала бэкап. Всегда. Эту фразу каждый админ хоть раз произносил вслух — обычно в тот момент, когда бэкапа как раз не оказалось. Давайте сделаем так, чтобы с вами этого не случилось: настроим автоматическое резервное копирование домашнего сервера, которое работает само, шифрует данные и хранит историю.
Инструмент — restic, бесплатная программа для резервного копирования с открытым кодом. Копии она складывает в репозиторий — так называется хранилище копий, по сути каталог на диске. Каждая копия называется снимком: это состояние ваших файлов на момент запуска.
Что получим и что нужно заранее
Результат: каждую ночь сервер сам сохраняет нужные каталоги в зашифрованный репозиторий, хранит 7 ежедневных, 4 еженедельных и 6 ежемесячных копий, а старые удаляет. Всё это — на restic и таймере systemd, без самописных скриптов в cron.
Нужно:
- Debian 13, Debian 12 или Ubuntu 22.04 и новее. Все команды ниже проверены на чистых Debian 13 (restic 0.18) и Debian 12 (restic 0.14) со штатными пакетами;
- права root (
sudo); - отдельный диск для копий — в примере он смонтирован в
/mnt/backup. Копия на том же диске, что и данные, — это не бэкап, это вторая копия одной беды.
Что именно сохранять
Прежде чем набирать команды, решим, что копировать. Типичный домашний сервер:
/etc— настройки системы и программ. Мало места, много ценности;/home— пользовательские файлы;/srvили где у вас лежат данные сервисов — сайты, фото, документы.
Не нужно копировать саму систему (/usr, /var/cache): её проще поставить заново, чем восстанавливать.
Отдельно про базы данных. Файлы работающей базы — PostgreSQL, MySQL — нельзя просто скопировать: в момент копирования база пишет в них, и копия может оказаться несогласованной. Правильно — сначала выгрузить базу в файл её собственным инструментом (pg_dump, mysqldump), а уже этот файл отдать restic. Как это встроить в службу — покажу в конце.
Шаг 1. Ставим restic
sudo apt update
sudo apt install restic
Ставит restic из штатного репозитория дистрибутива.
restic version
Показывает установленную версию — убедимся, что всё на месте.
Шаг 2. Пароль и настройки в одном месте
Restic шифрует всё, что сохраняет. Ключ шифрования — ваш пароль. Что тут происходит, если пароль потерять? Ровно то, что вы подумали: данные не восстановить никак. Поэтому пароль храним в файле и дополнительно записываем в менеджер паролей.
sudo mkdir -p /etc/restic
sudo sh -c 'head -c 32 /dev/urandom | base64 > /etc/restic/password'
sudo chmod 600 /etc/restic/password
Создаём каталог настроек, генерируем случайный пароль в файл и закрываем его от всех, кроме root.
sudo tee /etc/restic/env >/dev/null <<'EOF'
RESTIC_REPOSITORY=/mnt/backup/restic
RESTIC_PASSWORD_FILE=/etc/restic/password
EOF
sudo chmod 600 /etc/restic/env
Файл с переменными окружения: где лежит репозиторий и где взять пароль. Его потом прочитает systemd.
Шаг 3. Создаём репозиторий
sudo sh -c 'set -a; . /etc/restic/env; restic init'
Загружаем переменные из файла и инициализируем пустой зашифрованный репозиторий в /mnt/backup/restic.
Шаг 4. Первая копия руками
sudo sh -c 'set -a; . /etc/restic/env; restic backup /etc /home /srv --exclude-caches'
Сохраняем /etc, /home и /srv; каталоги с меткой кэша (файл CACHEDIR.TAG) пропускаем. Список каталогов поправьте под себя.
sudo sh -c 'set -a; . /etc/restic/env; restic snapshots'
Показывает список снимков — должен появиться первый.
Первая копия идёт долго: restic читает всё целиком. Следующие будут быстрыми — он сохраняет только изменившиеся куски файлов.
Шаг 5. Служба systemd
sudo tee /etc/systemd/system/restic-backup.service >/dev/null <<'EOF'
[Unit]
Description=Резервная копия restic
RequiresMountsFor=/mnt/backup
[Service]
Type=oneshot
EnvironmentFile=/etc/restic/env
CacheDirectory=restic
Environment=RESTIC_CACHE_DIR=/var/cache/restic
ExecStart=/usr/bin/restic backup /etc /home /srv --exclude-caches
ExecStartPost=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
Nice=10
IOSchedulingClass=idle
EOF
Описываем, что запускать. Разберём по строкам:
RequiresMountsFor— не запускаться, если диск для копий не подключён, вместо того чтобы молча писать копию на системный диск.Type=oneshot— служба выполнила работу и завершилась, это не демон.EnvironmentFile— берём репозиторий и пароль из файла шага 2.CacheDirectoryиRESTIC_CACHE_DIR— постоянный кэш в/var/cache/restic. Без него служба, у которой нет домашнего каталога, работает без кэша и каждую ночь заново читает служебные данные репозитория.ExecStartPost— после копии удаляем лишние снимки по правилу «7 дней, 4 недели, 6 месяцев» и освобождаем место (--prune).NiceиIOSchedulingClass=idle— копирование уступает процессор и диск всем остальным.
Шаг 6. Таймер
sudo tee /etc/systemd/system/restic-backup.timer >/dev/null <<'EOF'
[Unit]
Description=Ежедневная резервная копия restic
[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=15min
Persistent=true
[Install]
WantedBy=timers.target
EOF
Запуск каждый день в 03:00 со случайной задержкой до 15 минут. Persistent=true — если сервер был выключен ночью, копия выполнится сразу после включения.
sudo systemd-analyze verify /etc/systemd/system/restic-backup.service /etc/systemd/system/restic-backup.timer
Проверяем оба файла на ошибки до включения. Тишина в ответ — значит, всё в порядке.
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
Перечитываем конфигурацию systemd и включаем таймер — сейчас и после каждой перезагрузки.
systemctl list-timers restic-backup.timer
Показывает, когда таймер сработает в следующий раз и когда срабатывал в последний.
Шаг 7. Проверяем, что копия восстанавливается
Бэкап, из которого ни разу не восстанавливали, — это надежда, а не бэкап. Проверим.
sudo systemctl start restic-backup.service
journalctl -u restic-backup.service -n 30
Запускаем службу вручную и смотрим последние строки её журнала — там будет отчёт restic о сохранённых файлах.
sudo sh -c 'set -a; . /etc/restic/env; restic restore latest --target /tmp/restore --include /etc/hostname'
Восстанавливаем из последнего снимка один файл во временный каталог /tmp/restore — оригинал не трогаем.
sudo sh -c 'set -a; . /etc/restic/env; restic check'
Проверяем целостность репозитория. Делайте это хотя бы раз в месяц.
Шаг 8. Если на сервере есть база данных
Добавим перед копией выгрузку базы. Пример для PostgreSQL:
sudo mkdir -p /srv/dumps
sudo chown postgres:postgres /srv/dumps
sudo chmod 700 /srv/dumps
Каталог для выгрузок внутри /srv — значит, restic подхватит его автоматически. Последняя команда закрывает каталог от всех, кроме владельца: без неё дамп со всеми базами сможет прочитать любой пользователь сервера. Restic работает от root и прочитает его в любом случае.
sudo systemctl edit restic-backup.service
Открывает файл дополнений к службе — исходный файл остаётся нетронутым. Впишите:
[Service]
ExecStartPre=/usr/sbin/runuser -u postgres -- pg_dumpall --file=/srv/dumps/all.sql
Перед каждой копией выгружаем все базы от имени пользователя postgres в один файл. Если выгрузка не удалась, служба остановится и копия не будет сделана, — ошибку вы увидите в journalctl.
Сам дамп на сервере не зашифрован — шифрует restic уже в репозитории. Поэтому так важен chmod 700 выше. Для MySQL и MariaDB строка будет такой же по смыслу, только с mysqldump --all-databases.
Если что-то пошло не так
- «repository is already locked». Restic ставит блокировку на время работы. Если процесс был прерван, блокировка остаётся. Сначала убедитесь, что restic сейчас не запущен (
pgrep restic), и только потом снимайте её:restic unlockс теми же переменными окружения. - «wrong password or no key found». Не тот файл пароля или репозиторий создан с другим паролем. Проверьте
RESTIC_PASSWORD_FILEв/etc/restic/env. - Служба не стартует, в журнале про монтирование. Не подключён диск
/mnt/backup— так и задумано,RequiresMountsForбережёт системный диск. Подключите диск и запустите службу снова. - Кончилось место на диске копий. Уменьшите число хранимых снимков в строке
forgetи запустите службу вручную —--pruneосвободит место. - Таймер не срабатывает. Посмотрите
systemctl list-timers: если таймера нет в списке, его забыли включить командойenable --now.
И последнее. Один диск в той же квартире защищает от сломавшегося накопителя, но не от пожара и не от кражи. Когда этот бэкап заработает, следующим шагом сделайте вторую копию — вне дома. Restic умеет писать и на удалённые хранилища, но это уже тема отдельной статьи.
Это третья часть цикла «Домашний сервер без боли». Предыдущая — «Docker Compose на домашнем сервере». В следующей части — мониторинг: сервер сам сообщит, если бэкап не выполнился.