Это случилось три года назад. Я переносил базу данных с одного сервера на другой, что-то пошло не так с командой, я подтвердил удаление старой базы — и через секунду понял что удалил новую. Ту которая уже работала. С реальными пользователями.
Бэкап был. Трёхнедельной давности.
Три недели данных — это не конец света для того конкретного проекта. Но это был хороший урок. После него я начал относиться к бэкапам как к части архитектуры, а не как к галочке.
Что значит «нормальный бэкап»
Нормальный бэкап — это не просто файл где-то на сервере. Это:
-
Регулярность. Не «когда вспомню» а по расписанию. Для большинства проектов достаточно ежедневного бэкапа. Для критичных данных — чаще.
-
Хранение в другом месте. Бэкап на том же сервере что и данные — это не бэкап. Если сервер горит — горит всё вместе. Минимум: другой сервер или облачное хранилище.
-
Проверка восстановления. Бэкап который никто не проверял — это потенциально сломаный бэкап. Я потратил два часа однажды на «восстановление» из бэкапа который оказался пустым файлом. Всё это время думал что всё под контролем.
-
Ротация. Хранить бесконечно всё не нужно и дорого. Обычная схема: 7 дней ежедневных, 4 недельных, 12 месячных.
Как я делаю бэкапы сейчас
Для PostgreSQL у меня крон-задача которая запускается каждую ночь:
#!/bin/bash
set -e
DB_NAME="myapp"
BACKUP_DIR="/backups/postgres"
DATE=$(date +%Y-%m-%d)
FILENAME="$BACKUP_DIR/$DB_NAME-$DATE.sql.gz"
mkdir -p $BACKUP_DIR
pg_dump $DB_NAME | gzip > $FILENAME
# Загружаем в S3-совместимое хранилище
s3cmd put $FILENAME s3://my-backups/postgres/
# Удаляем локальные бэкапы старше 7 дней
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
echo "Backup completed: $FILENAME"
Для S3 использую Backblaze B2 — дешевле AWS S3 в несколько раз, S3-совместимый API, надёжный.
Файлы — rsync на отдельный сервер плюс копия в облако. Для загруженных пользователями файлов использую restic — он делает дедуплицированные, инкрементальные бэкапы и умеет шифровать.
# Первый раз: инициализация
restic -r s3:s3.us-west-002.backblazeb2.com/my-backups init
# Бэкап
restic -r s3:s3.us-west-002.backblazeb2.com/my-backups backup /var/www/uploads
# Посмотреть снапшоты
restic -r ... snapshots
# Восстановить
restic -r ... restore latest --target /tmp/restore
Мониторинг бэкапов
Бэкап который молча падает — хуже чем отсутствие бэкапа, потому что даёт ложную уверенность.
Я использую healthchecks.io (есть бесплатный план) — сервис который ждёт пинг от вашего скрипта. Если пинг не пришёл в ожидаемое время — шлёт алерт. Добавить в скрипт одну строку:
curl -fsS https://hc-ping.com/your-uuid > /dev/null
Если бэкап упал до этой строки — алерт придёт утром. Просто и надёжно.
Тест восстановления
Раз в квартал я беру бэкап и восстанавливаю его в тестовое окружение. Проверяю что данные читаются, приложение запускается, ничего не сломано.
Это занимает час. Зато я знаю что бэкапы рабочие.
Что в итоге
Бэкапы это скучно. Настраиваешь один раз, они работают тихо в фоне, месяцами ничего не происходит. Именно поэтому их откладывают.
Но когда что-то случается — а рано или поздно случается у всех — разница между «есть бэкап вчерашнего дня» и «бэкап трёхнедельной давности» может быть очень большой.
Я больше не откладываю это на потом.