Надежные бэкапы — это не «архив на всякий случай», а строгий процесс: автоматическая выгрузка, шифрование, хранение в независимом хранилище и регулярная проверка восстановления. В этой инструкции соберем рабочую схему автобэкапов сайта и баз данных в S3/Object Storage. Возьмем два проверенных инструмента — restic (нативно умеет S3 и шифрует «из коробки») и borg (используем для локального репозитория с последующей репликацией в S3). Покажу, как организовать дампы через mysqldump и pg_dump, ротацию, тестовые восстановления и типовые проверки целостности.
Материал рассчитан на админов/девопсов на VDS или хостинге с shell-доступом и cron. В примерах — Linux (Debian/Ubuntu, актуальные версии). Команды и пути адаптируйте под свою систему.
Правило №1: бэкап, который вы ни разу не пробовали восстановить, нужно считать отсутствующим.
Что именно бэкапим и почему
Для типового веб-проекта «сайт + база» минимальный набор данных для резервного копирования выглядит так:
- файлы приложения: корень сайта (например, /var/www/example), загруженные пользователями файлы, статические ассеты;
- конфигурации: важные конфиги веб-сервера и приложений (Nginx, PHP-FPM, .env — с аккуратным обращением к секретам);
- база данных: регулярные дампы MySQL/MariaDB (mysqldump) и/или PostgreSQL (pg_dump);
- скрипты деплоя и инфраструктурные метаданные (опционально, но полезно для ускорения DR-процедуры).
Бэкап одной только файловой директории без дампа БД или наоборот — частая ошибка. При аварии вам нужна согласованная точка восстановления. Поэтому бэкап-скрипт должен сначала формировать дампы, затем в одну транзакцию бэкапа забирать и файлы, и свежие дампы.
Архитектура: S3/Object Storage как удаленное хранилище
S3-совместимое Object Storage удобно для резервного копирования: отличается высокой доступностью, масштабируемостью, поддерживает версии, шифрование и политики жизненного цикла. Инструменты уровня restic умеют прямо писать в S3 и шифровать данные на стороне клиента, а значит содержимое будет защищено даже при компрометации хранилища.
Базовые принципы, которые помогут избежать проблем и лишних расходов:
- минимизируйте объём: исключайте кеши, временные и сборочные каталоги;
- используйте дедупликацию и инкременты (restic делает это «из коробки»);
- включайте ротацию и политики хранения (например, 7 дневных, 4 недельных, 6 месячных);
- храните доступы к S3 с минимальными правами (доступ только к нужному бакету/префиксу).
Доступ к Object Storage: ключи и переменные окружения
Для работы с S3 понадобятся хост эндпоинта, имя бакета и ключи доступа. Удобнее всего передавать их в утилиты через переменные окружения. Создайте файл окружения с правами 600, чтобы не светить секреты в cron и истории команд:
# /etc/restic.env
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_DEFAULT_REGION="eu-central-1"
export RESTIC_PASSWORD="длинный_уникальный_пароль_от_репозитория"
export RESTIC_REPOSITORY="s3:s3.example.com/mybucket"
Файл читается скриптами через стандартную конструкцию . /etc/restic.env
перед вызовом restic. Пароль репозитория не должен совпадать с паролями сервисов, а права на файл — только для root (или системного пользователя бэкапов).

restic: быстрый старт
restic удобен тем, что из коробки шифрует данные, дедуплицирует блоки и работает с S3. Установка в Debian/Ubuntu:
apt update && apt install -y restic
Инициализируйте репозиторий (выполняйте один раз):
. /etc/restic.env
restic init
Подготовка дампов БД
Чтобы не держать пароли в командной строке, используйте конфигурационные файлы с ограничением прав:
# /root/.my.cnf
[client]
user=backup
password=СЕКРЕТ
host=localhost
# /root/.pgpass
localhost:5432:mydb:backup:СЕКРЕТ
Права:
chown root:root /root/.my.cnf /root/.pgpass
chmod 600 /root/.my.cnf /root/.pgpass
Где пользователь backup
имеет только необходимые права на чтение (для MySQL — SELECT
, LOCK TABLES
при необходимости консистентных дампов; для PostgreSQL — права на базу). Каталог для временных дампов:
mkdir -p /var/backups/sql
chmod 700 /var/backups/sql
Скрипт автобэкапа с ротацией
Пример скрипта, который делает дампы MySQL/PostgreSQL, бэкапит файлы сайта и конфиги в S3 через restic, выполняет ротацию, а затем удаляет локальные дампы:
# /usr/local/bin/backup-s3.sh
#!/usr/bin/env bash
set -euo pipefail
umask 077
LOCK="/var/lock/backup-s3.lock"
exec 9>&"$LOCK"
flock -n 9 || { echo "Уже запущено"; exit 1; }
. /etc/restic.env
TS=$(date +"%Y%m%d-%H%M%S")
BACKUP_ROOT="/var/backups/sql/$TS"
SITE_DIR="/var/www/example"
CONF_DIRS=(/etc/nginx /etc/php /etc/letsencrypt)
mkdir -p "$BACKUP_ROOT"
# Дампы MySQL (все базы)
if command -v mysqldump >/dev/null; then
mysqldump --all-databases --single-transaction --quick --routines \
| gzip -9 > "$BACKUP_ROOT/mysql-all.sql.gz"
fi
# Дампы PostgreSQL (пример одной БД)
if command -v pg_dump >/dev/null; then
PGPASSFILE=/root/.pgpass pg_dump -h localhost -p 5432 -U backup \
-d mydb -F c -f "$BACKUP_ROOT/pg-mydb.dump"
fi
# Файл исключений для restic
EXC="/tmp/restic-excludes.txt"
cat > "$EXC" <<'EOF'
# Кеши и временные файлы
**/.cache
**/cache
**/tmp
**/node_modules
**/vendor/cache
EOF
# Бэкап в S3: сайт, конфиги, дампы
restic backup \
--tag "site" --tag "db" --tag "$TS" \
--exclude-file "$EXC" \
"$SITE_DIR" "${CONF_DIRS[@]}" "$BACKUP_ROOT"
# Ротация (пример: 7 дневных, 4 недельных, 6 месячных)
restic forget --prune \
--keep-daily 7 --keep-weekly 4 --keep-monthly 6
# Убираем локальные дампы
rm -rf "$BACKUP_ROOT" "$EXC"
echo "OK: backup $TS завершен"
Сделайте файл исполняемым и добавьте в cron, например, ежедневно в 03:15:
chmod +x /usr/local/bin/backup-s3.sh
crontab -e
# 15 3 * * * /usr/local/bin/backup-s3.sh >> /var/log/backup-s3.log 2>&1
В лог пишите кратко: начало, список задач, размер/скорость, успешное завершение. При ошибке возвращайте ненулевой код — так проще мониторить.
Проверка целостности и тестовое восстановление
Проверяйте снимки и читаемость данных. Быстрый вариант — выбрать подмножество блоков:
. /etc/restic.env
restic check --read-data-subset=10%
Для восстановления файлов последнего снимка в отдельный каталог:
mkdir -p /restore-test
restic restore latest --target /restore-test
Проверка БД — попытка реального восстановления на тестовый инстанс (локальный или отдельный). Для MySQL:
gunzip -c /restore-test/var/backups/sql/20240101-031500/mysql-all.sql.gz \
| mysql -u root -p test_restore
Для PostgreSQL:
createdb test_restore
pg_restore -d test_restore /restore-test/var/backups/sql/20240101-031500/pg-mydb.dump
Автоматизируйте такую проверку раз в неделю/месяц отдельной cron-задачей: восстанавливайте в «песочницу», прогоняйте простые health-check’и приложения (миграции, чтение таблиц, проверка конфигов), удаляйте временные данные. Если планируете перенос на новый сервер без простоя — пригодится материал о миграции без даунтайма: перенос сайта без простоя.
borg: локальный репозиторий + репликация в S3
borg — отличный инструмент для дедуплицированных бэкапов с сильным шифрованием и быстрым восстановлением, но прямой поддержки S3 в стабильной ветке нет. Практичный паттерн: хранить основной borg-репозиторий локально (на сервере или подключенном блочном диске), а затем реплицировать его в Object Storage с помощью синхронизации на уровне файлов (например, через утилиту, работающую с S3-каталогами). Это дает:
- максимально быстрые локальные бэкапы/восстановления через borg;
- вторую копию вне сервера (offsite) в S3 для аварийных случаев;
- минимальный трафик за счет дедупликации и сжатия borg.
Инициализация локального репозитория и базовый бэкап выглядят так:
apt update && apt install -y borgbackup
export BORG_REPO=/var/backups/borg
export BORG_PASSPHRASE="длинный_уникальный_пароль"
borg init --encryption=repokey-blake2 "$BORG_REPO"
borg create --stats --progress \
"$BORG_REPO"::site-{now} \
/var/www/example /etc/nginx /etc/php
borg prune -v --list "$BORG_REPO" \
--keep-daily=7 --keep-weekly=4 --keep-monthly=6
Далее реплицируйте каталог /var/backups/borg
в S3. Важно: репликация должна передавать неизмененные файлы как есть, не распаковывая их содержимое и не создавая «влажных» копий. Восстановление аварии можно проводить из локальной копии borg при ее наличии, а при полном отсутствии сервера — из реплики, предварительно скачав каталог репозитория из S3 обратно на новый хост.
Проверки borg: borg check
(интегритет репозитория), а также регулярное пробное восстановление конкретного архива на тестовый путь и сравнение контрольных сумм важных файлов.
Ротация, политики и стоимость хранения
Как выбрать политику хранения? Сочетайте бизнес-требования и здравый смысл. Хороший старт: 7 дневных, 4 недельных, 6 месячных и 1–2 годовых. Для проектов с интенсивными изменениями статических файлов можно увеличить глубину дневных копий. В Object Storage настройте правила жизненного цикла: перевод старых объектов в «холодные» классы, удаление очень старых, включение версионирования по ситуации.
Чтобы не переплачивать:
- исключайте каталоги с кешами и временными данными (см.
--exclude-file
); - не бэкапьте логи, которые и так ротацией удаляются;
- периодически аудитируйте размер репозитория (
restic stats
,borg info
); - следите за частотой запусков cron: разумно разнести дневные/недельные/месячные задачи.
Безопасность: шифрование и управление секретами
Вся схема опирается на клиентское шифрование: и restic, и borg шифруют данные до отправки в S3. Защищайте ключи и пароли: права 600 на файлы, отдельный системный пользователь для бэкапов, отсутствие секретов в аргументах команд (они попадают в историю и могут светиться в процессах). Пароль репозитория храните отдельно от ключей доступа к S3. Опционально включайте MFA для панели хранилища и ограничивайте сеть (VPC/ACL) для эндпоинтов. Базовая гигиена доступа на сервере — в статье про SSH и фаервол: настройка SSH и firewall.
Проверьте журналы: не выводите полные пути к секретам и не логируйте содержимое дампов. В cron используйте абсолютные пути к бинарям и файлам окружения. Для долгоживущих заданий имеет смысл добавить таймауты и метрики (времени, объёма, количества файлов).
Тест восстановления: сценарий «чистый сервер»
Документируйте процедуру Disaster Recovery. Минимальный черновик:
- Развернуть чистую систему (удобно на VDS), установить restic/borg и зависимости БД.
- Подготовить доступ к S3 (файл окружения), проверить подключение к репозиторию.
- Восстановить файловую часть в временной каталог, сверить контрольные суммы критичных файлов.
- Создать пустые БД, восстановить дампы, прогнать миграции и тесты приложения.
- Включить сервисы, проверить логи и работоспособность.
Время от времени прогоняйте этот сценарий целиком. Это отлавливает зависимые артефакты (шрифты, ключи, расширения БД), которые легко забыть в списке бэкапов.
Типовые проблемы и их диагностика
- restic: «repository is locked» — зависший процесс или незавершённый предыдущий запуск. Используйте блокировку в скрипте (flock),
restic unlock
при необходимости, проверьте overlapping в cron. - Медленный бэкап — проверьте сетевую задержку до S3, включите многопоточность (переменные окружения не мешают), оптимизируйте исключения (папки кешей), включите сжатие дампов БД.
- Неконсистентные дампы MySQL — используйте
--single-transaction
, по возможности--routines
, и снимайте дамп при низкой нагрузке (ночью через cron). - PostgreSQL: ошибка прав — убедитесь, что пользователь имеет привилегии на нужные схемы/объекты, а
.pgpass
принадлежит root и имеет права 600. - Переполненный диск для временных дампов — храните дампы на отдельном разделе или делайте стриминг (сжатие в stdout и немедленный бэкап), своевременно удаляйте временные файлы.
Минимальная конфигурация для хостинга без привилегий
Если у вас общий хостинг с ограничениями, но есть shell и cron, можно упростить схему: делать дампы в домашнюю директорию, упаковывать сайт в архив, а затем передавать архив в Object Storage через совместимый клиент. При этом помните про шифрование перед отправкой (например, через инструмент, который шифрует на клиенте). Ротацию реализуйте по датам в именах файлов и удалению старых архивов. Для проектов на виртуальном хостинге это минимально жизнеспособная стратегия, пока не переедете на VDS с полноценными инструментами бэкапа.

Итоги
Рабочая схема автобэкапа выглядит так: cron формирует консистентные дампы БД, restic (или связка borg + репликация) забирает файлы и дампы, шифрует и отправляет в S3/Object Storage, затем выполняется ротация. Раз в неделю проводится быстрая проверка целостности, раз в месяц — пробное восстановление «как вживую». Такая дисциплина превращает «бэкап сайта» в управляемый процесс «резервного копирования» с понятными RPO/RTO и прогнозируемыми затратами.
Главное — автоматизировать не только выгрузку, но и проверку восстановления. Тогда в критический момент ваш план действительно сработает.