Центр помощи

Пошаговые руководства по серверам, сетям и аккаунту.

Linux-сервер

Автоматические зашифрованные бэкапы VPS с restic и rclone (ежедневно, вне сервера, с проверкой восстановления)

Автоматические зашифрованные бэкапы VPS с restic и rclone (ежедневно, вне сервера, с проверкой восстановления)

Надёжнее всего бэкапить Linux VPS так: каждый день отправлять зашифрованные снапшоты restic в хранилище за пределами сервера, задать понятную политику хранения и регулярно проверять восстановление. В этой инструкции всё это настраивается на Debian 12/13, Ubuntu 22.04/24.04 и Rocky Linux / AlmaLinux: установка restic, выбор внешнего репозитория (S3-совместимое хранилище, SFTP или rclone), дампы баз данных, запуск по таймеру systemd и проверка того, что данные действительно можно вернуть.

Почему бэкапы должны храниться вне VPS

Копия на том же сервере — не бэкап: всё, что удаляет сервер, удаляет и её. На облачном VPS JUSTG данные безвозвратно удаляются и при вполне обычных действиях:

  • Смена локации (Change location): устанавливается новый VPS с новым IP, ничего не копируется. Как только он готов, старый VPS и все его данные удаляются.
  • Просроченное продление: неоплаченная услуга приостанавливается в день окончания срока; если счёт не оплачен и через 7 дней после этой даты, услуга отменяется, а данные удаляются.
  • Переустановка ОС стирает диск, а отмена в режиме Immediate удаляет услугу и данные сразу после обработки запроса.

Прибавьте сюда опечатку в rm -rf, неудачное обновление или взлом — и правило становится очевидным: полагаться можно только на бэкап, который вы сделали сами и храните в другом месте. Перед сменой локации, переустановкой или отменой запустите бэкап вручную и убедитесь, что новый снапшот появился.

restic шифрует данные ещё на VPS, поэтому провайдер хранилища видит только зашифрованные блоки. Кроме того, он дедуплицирует данные: после первой полной выгрузки ежедневный снапшот отправляет только изменения.

Шаг 1: Установите restic

В Debian 12/13, Ubuntu 24.04 и EPEL версия достаточно свежая:

# Debian 12/13, Ubuntu 24.04
apt update && apt install -y restic
restic version

# Rocky Linux / AlmaLinux 8, 9 (from EPEL)
dnf install -y epel-release && dnf install -y restic

В Ubuntu 22.04 стоит restic 0.12: без сжатия и без поддержки актуального формата репозитория. Там установите официальный бинарный файл и проверьте контрольную сумму:

# Official static binary (Ubuntu 22.04 or any distro with an old restic)
VER=0.18.1   # check https://github.com/restic/restic/releases for the latest version
cd /tmp
curl -fLO https://github.com/restic/restic/releases/download/v${VER}/restic_${VER}_linux_amd64.bz2
curl -fLO https://github.com/restic/restic/releases/download/v${VER}/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS      # must print: OK
bunzip2 restic_${VER}_linux_amd64.bz2
install -m 0755 restic_${VER}_linux_amd64 /usr/local/bin/restic
restic version

Шаг 2: Выберите внешний репозиторий

Репозиторий — это место, где хранятся зашифрованные снапшоты. Выберите один вариант и сохраните его в /etc/restic/env (простые строки вида NAME=value).

Вариант A: S3-совместимое объектное хранилище

Подойдёт любой провайдер с S3 API. Создайте бакет и ключ доступа только к нему, а в URL укажите endpoint провайдера:

# /etc/restic/env  (S3-compatible object storage)
RESTIC_REPOSITORY=s3:https://s3.example.com/example-backups/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
AWS_ACCESS_KEY_ID=REPLACE_WITH_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=REPLACE_WITH_SECRET_KEY
# Optional: monitoring ping URL (Step 11)
HC_PING_URL=

Вариант B: SFTP на второй сервер

Используйте другой свой сервер — лучше в другой локации или у другого провайдера — с отдельным пользователем backup, которому принадлежит /srv/restic:

# /etc/restic/env  (SFTP to a second server)
RESTIC_REPOSITORY=sftp:[email protected]:/srv/restic/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
HC_PING_URL=

# One-time SSH key login for root on the VPS
ssh-keygen -t ed25519 -N "" -f /root/.ssh/id_ed25519   # skip if the key exists
ssh-copy-id [email protected]
ssh [email protected] true      # accept the host key once

Вариант C: бэкенд rclone

rclone подключает restic к десяткам сервисов (Backblaze B2, Google Drive, OneDrive, WebDAV и другим):

# Install and configure rclone (interactive wizard, run as root)
apt install -y rclone        # Rocky/Alma: dnf install -y rclone (EPEL)
rclone config                # create a remote, for example named "offsite"

# /etc/restic/env  (any rclone backend)
RESTIC_REPOSITORY=rclone:offsite:example-backups/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
RCLONE_CONFIG=/root/.config/rclone/rclone.conf
HC_PING_URL=
Учётными данными из /etc/restic/env обычно можно и удалять бэкапы, так что злоумышленник, захвативший VPS, способен стереть репозиторий. Для лучшей защиты включите версионирование или object lock для бакета либо используйте хранилище только на дозапись, а пароль от аккаунта хранилища на сервере не держите.

Шаг 3: Создайте файл пароля и репозиторий

install -d -m 0700 /etc/restic
openssl rand -base64 32 > /etc/restic/password
chmod 600 /etc/restic/password
nano /etc/restic/env          # paste one of the examples above
chmod 600 /etc/restic/env

# Load the settings into the current shell and create the repository
set -a; . /etc/restic/env; set +a
restic init
Без пароля расшифровать бэкапы не сможет никто, в том числе вы. Сразу сохраните /etc/restic/password и /etc/restic/env в менеджер паролей или другое надёжное место вне сервера: если VPS пропадёт, для восстановления понадобятся только эти два файла.

Шаг 4: Решите, что включать в бэкап, а что исключать

Бэкапьте конфигурацию и данные, а не всю операционную систему: переустановить ОС быстрее, чем восстанавливать системные файлы, а снапшоты остаются компактными.

# /etc/restic/include  - one path per line; delete lines that do not exist
/etc
/root
/home
/srv
/var/www
/opt
/usr/local
/var/spool/cron
/var/backups/db

# /etc/restic/excludes
/root/.cache
/home/*/.cache
**/node_modules
**/*.tmp
/var/www/*/cache
  • Включайте: /etc, домашние каталоги, корни сайтов, данные приложений, crontab и папку с дампами баз.
  • Пропускайте: /proc, /sys, /dev, /run, /tmp, swap-файлы и кэши. Их нет в списке, поэтому restic их даже не читает.
  • Файлы баз данных (/var/lib/mysql, /var/lib/postgresql), скопированные на работающей базе, могут оказаться несогласованными. Бэкапьте дампы (шаг 5).
  • Docker: не бэкапьте /var/lib/docker целиком; сохраняйте compose-файлы и тома или папки с данными.

Шаг 5: Делайте дамп баз данных перед каждым бэкапом

Скрипт ниже пишет сжатые дампы в /var/backups/db — эта папка уже есть в списке. Выставьте MYSQL и POSTGRES под свой сервер:

#!/bin/bash
# /usr/local/sbin/db-dump.sh - consistent database dumps before each backup
set -euo pipefail
umask 077
MYSQL=yes        # yes / no
POSTGRES=no      # yes / no
OUT=/var/backups/db
mkdir -p "$OUT"

if [ "$MYSQL" = yes ]; then
  DUMP=$(command -v mariadb-dump || command -v mysqldump)
  "$DUMP" --all-databases --single-transaction --quick \
          --routines --events --triggers | gzip > "$OUT/mysql-all.sql.gz.tmp"
  mv "$OUT/mysql-all.sql.gz.tmp" "$OUT/mysql-all.sql.gz"
fi

if [ "$POSTGRES" = yes ]; then
  cd /tmp
  runuser -u postgres -- pg_dumpall | gzip > "$OUT/postgres-all.sql.gz.tmp"
  mv "$OUT/postgres-all.sql.gz.tmp" "$OUT/postgres-all.sql.gz"
fi

--single-transaction даёт согласованный дамп таблиц InnoDB без блокировки сайта. В Debian и Ubuntu root подключается к MariaDB/MySQL через локальный сокет без пароля; если у вас пароль нужен, укажите его в /root/.my.cnf (права 600), а не в командной строке.

Шаг 6: Создайте скрипт бэкапа

Один скрипт делает дампы, бэкап, чистку по политике хранения и еженедельную проверку, а также отчитывается на необязательный URL мониторинга (шаг 10). Любая ошибка останавливает его, так что сбои не проходят незамеченными:

#!/bin/bash
# /usr/local/sbin/restic-backup.sh - dump databases, back up, apply retention
set -euo pipefail
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
set -a; . /etc/restic/env; set +a

fail() {
  [ -n "${HC_PING_URL:-}" ] && curl -fsS -m 10 --retry 3 "$HC_PING_URL/fail" >/dev/null || true
}
trap fail ERR

/usr/local/sbin/db-dump.sh

restic backup \
  --files-from /etc/restic/include \
  --exclude-file /etc/restic/excludes \
  --exclude-caches \
  --tag daily

restic forget --prune \
  --keep-daily 7 --keep-weekly 4 --keep-monthly 6

# Sundays: verify the repository and read back 5% of the data
if [ "$(date +%u)" = 7 ]; then
  restic check --read-data-subset=5%
fi

if [ -n "${HC_PING_URL:-}" ]; then
  curl -fsS -m 10 --retry 3 "$HC_PING_URL" >/dev/null
fi

Сделайте скрипты исполняемыми и запустите первый бэкап вручную. Первый запуск выгружает всё, следующие — только изменения.

chmod 700 /usr/local/sbin/db-dump.sh /usr/local/sbin/restic-backup.sh
/usr/local/sbin/restic-backup.sh      # first run by hand, watch for errors
restic snapshots

Шаг 7: Запуск по таймеру systemd (или через cron)

Таймер systemd — предпочтительный вариант: он пишет в журнал, догоняет пропущенный запуск (Persistent=true) и понижает приоритет задачи по CPU и диску, чтобы сайт не тормозил.

# /etc/systemd/system/restic-backup.service
[Unit]
Description=restic backup to off-site repository
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/restic-backup.sh
Nice=10
IOSchedulingClass=idle

# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Daily restic backup

[Timer]
OnCalendar=*-*-* 03:30:00
RandomizedDelaySec=30min
Persistent=true

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer

# Test the service once and read its log
systemctl start restic-backup.service
journalctl -u restic-backup.service -n 50 --no-pager

Если вам удобнее cron, используйте вместо таймера (не одновременно):

# /etc/cron.d/restic-backup  (only if you do not use the systemd timer)
30 3 * * * root /usr/local/sbin/restic-backup.sh >> /var/log/restic-backup.log 2>&1
Ночной запуск с низким приоритетом бережёт диск и помогает не выходить за правила fair use по дисковому вводу-выводу.

Шаг 8: Политика хранения: restic forget --prune

restic forget решает, какие снапшоты оставить, а --prune удаляет данные, которые больше не нужны ни одному снапшоту. Политика в скрипте хранит:

ПараметрЧто сохраняется
--keep-daily 7последний снапшот каждого из последних 7 дней
--keep-weekly 4по одному снапшоту в неделю за 4 недели
--keep-monthly 6по одному снапшоту в месяц за 6 месяцев

Прежде чем полагаться на новую политику, проверьте её с --dry-run:

set -a; . /etc/restic/env; set +a
restic snapshots
# Preview what a policy would remove, without deleting anything
restic forget --dry-run --keep-daily 7 --keep-weekly 4 --keep-monthly 6
restic stats --mode raw-data

Каждое воскресенье скрипт также запускает restic check. Он проверяет структуру репозитория, а --read-data-subset=5% каждый раз скачивает и сверяет другие 5% данных, так что повреждение обнаружится раньше, чем бэкап понадобится. Для дополнительной уверенности restic check можно запустить вручную в любой момент.

Шаг 9: Проверьте восстановление

Бэкап, из которого вы ни разу не восстанавливались, — это лишь надежда. Раз в месяц восстанавливайте что-нибудь реальное во временную папку и сравнивайте:

set -a; . /etc/restic/env; set +a
restic snapshots
restic ls latest /etc/nginx

# Restore one directory to a scratch location, then compare
restic restore latest --target /tmp/restore-test --include /etc/nginx
diff -r /etc/nginx /tmp/restore-test/etc/nginx && echo "restore OK"

# Check that the database dump is complete (last line: "-- Dump completed on ...")
restic dump latest /var/backups/db/mysql-all.sql.gz | zcat | tail -n 1
rm -rf /tmp/restore-test

Один раз отрепетируйте и худший сценарий, например на запасном VPS: новый сервер, у вас есть только два сохранённых файла.

# On the NEW server: install restic, then restore the two saved files
install -d -m 0700 /etc/restic
nano /etc/restic/password && nano /etc/restic/env
set -a; . /etc/restic/env; set +a

restic restore latest --target /srv/restore
rsync -a /srv/restore/var/www/ /var/www/          # copy back what you need
zcat /srv/restore/var/backups/db/mysql-all.sql.gz | mariadb     # or: mysql
Не запускайте restic restore latest --target / на работающей системе: команда перезапишет живые файлы, включая системные настройки, которые могут не подойти новому серверу. Восстанавливайте в отдельную папку и копируйте обратно только нужное.

Шаг 10: Получайте оповещения о сбоях бэкапа

Бэкапы обычно ломаются тихо: истёк ключ, переполнен бакет, сменился пароль. Помогает сервис по принципу «dead man's switch»: после каждого успешного запуска скрипт обращается к URL, а если обращение не пришло вовремя, вы получаете оповещение. Разверните такой сервис сами (например, open-source Healthchecks) или возьмите любой аналог и добавьте URL проверки в /etc/restic/env:

HC_PING_URL=https://hc.example.com/ping/REPLACE-WITH-YOUR-CHECK-ID

При успехе скрипт обращается к этому URL, при ошибке — к $HC_PING_URL/fail. Задайте период проверки в один день с запасом в несколько часов. Если такого сервиса нет, хотя бы раз в неделю смотрите restic snapshots и journalctl -u restic-backup.service.

FAQ

Сколько места нужно в хранилище?

Для первого снапшота — примерно объём ваших данных (часто меньше благодаря сжатию), дальше немного в день на изменения. Через пару недель запустите restic stats --mode raw-data и посмотрите реальную цифру.

restic пишет, что репозиторий заблокирован. Что делать?

Предыдущий запуск прервался и оставил устаревшую блокировку. Убедитесь, что restic сейчас не работает (pgrep -a restic), затем выполните restic unlock и снова запустите бэкап.

На тарифе с 512 МБ restic расходует слишком много памяти. Можно ли это уменьшить?

Добавьте GOGC=20 в /etc/restic/env, чтобы restic чаще освобождал память, держите список путей компактным и проверьте, что на VPS есть swap. Если памяти всё равно не хватает, повысьте тариф на странице услуги. Нужна помощь — создайте тикет: у JUSTG работает AI-поддержка 24/7 по тикетам, а инженеры подключаются, когда нужен человек.

Помог ли вам данный ответ?
Центр помощи
Linux-сервер Вход по SSH-ключу в Linux: настройка ключей ed25519 и отключение входа по паролю Любой сервер с публичным IPv4 через несколько минут после запуска начинают атаковать боты, перебирающие SSH-пароли. В этой инструкции… Linux-сервер Как безопасно сменить порт SSH и пароль root на Linux VPS Перенос SSH с порта 22 не остановит целенаправленную атаку, но уберёт из логов большую часть автоматического сканирования, а смена пароля… Linux-сервер Настройка файрвола в Linux: UFW и firewalld на VPS (IPv4 и IPv6) Только что установленный Linux-сервер отвечает на любом порту, который открыла какая-либо служба, поэтому файрвол — одна из первых вещей,… Linux-сервер Как добавить swap на Linux VPS (тарифы с 512 МБ и 1 ГБ ОЗУ) На облачном сервере с 512 МБ или 1 ГБ ОЗУ база данных, пул PHP-FPM и обновление пакетов легко исчерпывают память одновременно. Тогда OOM… Linux-сервер Диск заполнен в Linux: как найти и освободить место на VPS Ошибка «No space left on device» ломает на сервере почти всё: базы данных перестают писать, сайты отдают ошибки, обновления пакетов не…
AlipayUnionPayVISAMastercardPayPalUSDTstripe