Безопасность сайта

Резервные копии WordPress без платных плагинов в 2026

Четыре способа делать рабочие бэкапы WordPress без UpdraftPlus Premium и BackWPup Pro: cron, WP-CLI, ручной скрипт и средства хостинга.

обновлено 10 минут чтения 0 Дмитрий Акиндинов
Содержание
  1. Что должно быть в нормальном бэкапе
  2. Способ 1: ручной cron на shared-хостинге
  3. Способ 2: WP-CLI на серверах с SSH
  4. Способ 3: средства хостинга, если есть
  5. Способ 4: PHP-скрипт без SSH и без cron
  6. Стратегия 3-2-1 для маленького сайта
  7. Что делать раз в месяц, чтобы бэкап не оказался пустым
  8. Сколько хранить и как часто делать
  9. Когда стоит позвать подрядчика
  10. Частые вопросы

Нормальная копия это файлы плюс дамп базы, снятые в один момент и лежащие вне хостинга. Ядро WordPress в архив класть не нужно: оно раздувает файл в разы и при восстановлении не помогает, потому что скачивается заново за минуту.

История повторяется раз в пару месяцев. Звонит человек: сайт падает, в админке белый экран, последний бэкап от прошлого года сделан через бесплатную версию UpdraftPlus, лежит в той же папке wp-content/uploads/, и туда же заехал шифровальщик. Восстанавливать нечего, остаётся доставать кеш Яндекса и собирать структуру из памяти.

Бэкап нужен не для галочки. Бэкап нужен такой, чтобы из него реально можно было поднять сайт за час, и чтобы он лежал не там же, где живой WordPress. Платные плагины это умеют, но за 50-80 долларов в год за один сайт. Я обхожусь без них уже несколько лет, и ниже разберу четыре способа, которые работают на shared-хостинге, на VPS и на изолированной машине.

Папка с иконкой синхронизации с облаком

Что должно быть в нормальном бэкапе

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

WordPress состоит из двух частей. Файлы и база данных. Файлы это сами PHP-скрипты темы и плагинов плюс загрузки из медиабиблиотеки. База это таблицы MySQL или MariaDB с постами, пользователями, опциями, мета-полями. Если у вас бэкап только файлов или только базы, у вас нет бэкапа. У вас половина, и из неё сайт не поднять.

Минимальный набор для одного бэкапа:

  • Дамп базы целиком, со структурой и данными, в формате SQL или сжатый gzip.
  • Архив wp-content/, в котором лежат темы, плагины и uploads/. Без этого админка поднимется, а сайт будет без картинок и без верстки.
  • Файл wp-config.php. В нём логин и пароль к базе, префикс таблиц и соли. Без него даже корректный код WordPress не подключится к восстановленной базе.

Опционально, но желательно:

  • Корень public_html/ с .htaccess, потому что в нём могут быть кастомные редиректы и правила безопасности.
  • mu-plugins/, если вы их используете.

Что не нужно класть в бэкап: ядро WordPress (wp-admin/, wp-includes/ и корневые wp-*.php), потому что оно идентично оригинальному дистрибутиву и доступно бесплатно. Ядро в бэкапе раздувает архив в 4-6 раз и ничем не помогает при восстановлении.

Способ 1: ручной cron на shared-хостинге

Самый надёжный способ для типичного shared-хостинга вроде Timeweb, Beget, Reg.ru. Ничего кроме PHP, MySQL и стандартного cron. Работает на любом тарифе, где разрешён ssh или хотя бы планировщик в панели.

Создайте каталог /home/<user>/backups/, в котором будут лежать архивы. Это не webroot, доступа из браузера к нему нет. Это критично: если бэкапы лежат внутри public_html/, любой, кто угадал имя файла, скачает себе всю базу с паролями.

Скрипт ~/backup.sh:

#!/usr/bin/env bash
set -euo pipefail

WP_DIR="$HOME/saitfix.ru/public_html"
DEST="$HOME/backups"
DATE=$(date +%Y-%m-%d_%H%M)
KEEP_DAYS=14

mkdir -p "$DEST"

# Параметры базы вытаскиваем из wp-config.php
DB_NAME=$(php -r "include '$WP_DIR/wp-config.php'; echo DB_NAME;")
DB_USER=$(php -r "include '$WP_DIR/wp-config.php'; echo DB_USER;")
DB_PASS=$(php -r "include '$WP_DIR/wp-config.php'; echo DB_PASSWORD;")
DB_HOST=$(php -r "include '$WP_DIR/wp-config.php'; echo DB_HOST;")

# Дамп базы
mysqldump --no-tablespaces --single-transaction 
  -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" 
  | gzip -9 > "$DEST/db-$DATE.sql.gz"

# Архив контента
tar czf "$DEST/files-$DATE.tar.gz" 
  -C "$WP_DIR" wp-config.php wp-content .htaccess

# Чистим старые
find "$DEST" -type f -name "*.gz" -mtime +$KEEP_DAYS -delete

# Размер для отчёта в лог
du -sh "$DEST" >> "$HOME/backup.log"
echo "[$(date +%F %T)] backup ok" >> "$HOME/backup.log"

Делаете файл исполняемым: chmod +x ~/backup.sh. Открываете планировщик хостинга и ставите выполнение раз в сутки в 4 утра, когда нагрузка минимальна:

0 4 * * * /usr/bin/env bash $HOME/backup.sh

Готово, бэкапы создаются сами. Через 14 дней старые удаляются, чтобы не съесть весь диск.

Куда увозить бэкап с сервера

Хранить бэкап на том же диске, где живой сайт, бессмысленно. Если хостинг упадёт целиком, вы потеряете и сайт и копии.

Минимум, который я ставлю клиентам, это rclone в Yandex Object Storage или Selectel S3. Один бакет за 50-150 рублей в месяц, ключ доступа в скрипт, и архивы синхронизируются ночью.

Конфиг rclone готовится один раз через rclone config, потом в скрипт добавляется строка:

rclone copy "$DEST" yandex:saitfix-backups/$(hostname) 
  --include "*-$DATE.*" --quiet

Альтернатива для людей, у которых дома есть NAS или просто внешний диск, это rsync по SSH на свою машину. Если у домашнего интернета белый IP или есть VPN до домашней сети, это даже бесплатно.

Способ 2: WP-CLI на серверах с SSH

WP-CLI это утилита для WordPress в командной строке. На большинстве shared-хостингов она уже стоит, проверяется командой wp --info. На Timeweb стоит, на Beget стоит, на Reg.ru стоит у тарифов выше базового.

Бэкап одной командой:

cd ~/saitfix.ru/public_html
wp db export ~/backups/db-$(date +%F).sql --add-drop-table

Файлы тем же tar. Преимущество WP-CLI в том, что он умеет нативно делать поиск-замену в базе перед бэкапом, что критично, если вы готовите дамп для миграции на другой домен:

wp search-replace 'https://staging.saitfix.ru' 'https://saitfix.ru' 
  --export=~/backups/db-prod-$(date +%F).sql --all-tables

Есть нюанс: wp db export делает дамп через mysqldump, поэтому нужны те же права. На некоторых тарифах хостинга mysqldump запрещён в SSH, и WP-CLI падает с ошибкой. Тогда переключаемся на встроенный экспорт через PHP:

wp db export ~/backups/db-$(date +%F).sql --no-tablespaces --skip-lock-tables

Если и это не работает, остаётся вариант через PHP-скрипт без mysqldump. Описан в способе 4 ниже.

Восстановление из WP-CLI бэкапа

Это та часть, которую люди не тестируют, и зря. Бэкап без проверенного восстановления это спокойный сон до первого инцидента.

Создаёте чистую базу или дроп старой:

wp db reset --yes
wp db import ~/backups/db-2026-04-30.sql

Если переезжаете на другой домен, заодно меняете URL:

wp option update home 'https://saitfix.ru'
wp option update siteurl 'https://saitfix.ru'
wp search-replace 'old.saitfix.ru' 'saitfix.ru' --all-tables --skip-columns=guid

Файлы накатываете обратным tar xzf. После восстановления обязательно прогоняете wp core verify-checksums, чтобы убедиться, что ядро не подменено.

Сервер со щитом и иконкой базы данных

Способ 3: средства хостинга, если есть

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

Что точно есть и что точно работает на популярных хостерах в 2026 году:

  • Timeweb. Автоматический бэкап раз в сутки на отдельный сторадж, хранится 14-30 дней в зависимости от тарифа. Восстановление в один клик из панели. Доступно на Premium и выше.
  • Beget. То же самое: ежедневный снапшот, хранится 7-30 дней. Бесплатно с Comfort и выше.
  • Reg.ru. Ежедневные копии, доступны 7 дней назад. На некоторых тарифах нужно заказать отдельно.
  • Selectel и FirstVDS на VPS. Снапшоты тома по расписанию, оплата по времени и объёму.

Использовать встроенные бэкапы стоит как первый уровень защиты. Если человек по ошибке удалил пост, страницу, поломал тему, восстановили из вчерашнего снапшота за 2 минуты. Удобно.

Но как единственный бэкап они не годятся. Причины:

  • Снапшот хостера живёт там же, где сайт. Если кто-то получил доступ к панели или произошёл взлом инфраструктуры, бэкап тоже под угрозой.
  • Глубина истории ограничена 7-14 днями. Если заражение полугодовой давности и активировалось вчера, у вас в каждом снапшоте уже зараженный сайт.
  • При смене хостера снапшоты не переезжают. Если вы решили уйти, на новой площадке бэкапов нет.

Поэтому: используем встроенные снапшоты как удобство, но обязательно дублируем своими.

Способ 4: PHP-скрипт без SSH и без cron

Бывают ситуации, когда у вас совсем дешёвый shared без SSH и без планировщика, а доступ только по FTP и в phpMyAdmin. Звучит нелепо в 2026 году, но я регулярно встречаю такие тарифы у клиентов, которые завели сайт лет десять назад.

Тогда работает старый трюк: PHP-скрипт, который дёргается извне по расписанию.

Заводите файл /home/<user>/backups/run.php (вне webroot, ровно так же):

<?php
$secret = 'V3rySecr3tT0kenChange1tEv3ryW33k';
if (($_GET['k'] ?? '') !== $secret) {
    http_response_code(403);
    exit;
}

$cfg = require __DIR__ . '/../public_html/wp-config.php';
$dest = __DIR__;
$date = date('Y-m-d_Hi');
$db   = DB_NAME;
$user = DB_USER;
$pass = DB_PASSWORD;
$host = DB_HOST;

$dumpCmd = "mysqldump --no-tablespaces -h $host -u $user -p'$pass' $db | gzip > $dest/db-$date.sql.gz";
$tarCmd  = "tar czf $dest/files-$date.tar.gz -C " . dirname(__DIR__) . "/public_html wp-config.php wp-content";

shell_exec($dumpCmd);
shell_exec($tarCmd);

// Чистим старые
foreach (glob("$dest/*-*.gz") as $f) {
    if (filemtime($f) < time() - 14 * 86400) unlink($f);
}

echo 'ok ' . date('c');

Если shell_exec запрещён, делаем экспорт через PHP силами mysqli или PDO. Простой пример с потоковой записью в файл:

$mysqli = new mysqli($host, $user, $pass, $db);
$out = gzopen("$dest/db-$date.sql.gz", 'w9');
$tables = $mysqli->query('SHOW TABLES')->fetch_all();
foreach ($tables as $row) {
    $t = $row[0];
    $create = $mysqli->query("SHOW CREATE TABLE `$t`")->fetch_row()[1];
    gzwrite($out, "DROP TABLE IF EXISTS `$t`;n$create;n");
    $rows = $mysqli->query("SELECT * FROM `$t`");
    while ($r = $rows->fetch_assoc()) {
        $values = array_map(fn($v) => $v === null ? 'NULL' : "'" . $mysqli->real_escape_string($v) . "'", $r);
        gzwrite($out, "INSERT INTO `$t` VALUES (" . implode(',', $values) . ");n");
    }
}
gzclose($out);

Этот код медленнее mysqldump, но работает на любом хостинге, где есть PHP и MySQL.

После создания скрипта дёргаете его раз в сутки внешним сервисом. Бесплатные варианты в 2026 году: cron-job.org, EasyCron, Make.com на минимальном плане. Любой из них раз в день делает GET на https://your-secret-domain.example/backups/run.php?k=V3rySecr3tT0kenChange1tEv3ryW33k.

Важно: этот файл должен лежать так, чтобы он был доступен по HTTP, но архивы складывались вне webroot. То есть у нас два пути: скрипт в public_html/_secret_path/run.php, а архивы в /home/user/backups/. Доступ к самому скрипту защищён токеном, имя папки тоже не угадаешь.

Стратегия 3-2-1 для маленького сайта

Профессиональный стандарт хранения бэкапов называется 3-2-1: три копии данных, на двух разных носителях, одна копия вне основной инфраструктуры. Для маленького сайта он переводится так.

  • Копия 1: живые файлы и база на хостинге.
  • Копия 2: ежедневный архив в /home/<user>/backups/ или в снапшоте хостера.
  • Копия 3: еженедельный архив в S3-совместимом хранилище в другом дата-центре.

Если хочется ещё надёжнее, добавляете офлайн-копию: раз в месяц скачиваете архив на свой ноутбук или внешний диск. Для микробизнеса этого хватит на любой сценарий, кроме одновременной кражи компьютера и пожара в дата-центре, что статистически маловероятно.

Не забудьте про шифрование. Дамп базы с паролями пользователей, хешами, IP-адресами и реальными именами клиентов это серьёзный ПДн. По 152-ФЗ его лучше шифровать перед выгрузкой за пределы своего хостинга. Простейший способ: gpg --symmetric --cipher-algo AES256 db-2026-04-30.sql.gz. Проверяйте, что ключ не лежит рядом с архивами.

Ноутбук с прогресс-баром резервного копирования

Что делать раз в месяц, чтобы бэкап не оказался пустым

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

  1. Берёте свежий архив, разворачиваете в локальную папку: tar tzf files-2026-04-30.tar.gz | head показывает структуру.
  2. Импортируете базу в локальный MySQL под названием restore_test.
  3. Прогоняете mysql restore_test -e "SELECT COUNT(*) FROM wp_posts WHERE post_status = 'publish'". Если число близко к фактическому количеству статей, дамп жив.
  4. Открываете архив файлов, проверяете, что в wp-content/uploads/2026/04/ есть свежие картинки.
  5. Если есть Docker, поднимаете локальный WordPress на образ wordpress:latest, монтируете в него wp-content и базу, заходите в wp-admin. Если зашли и видите свои посты, бэкап рабочий.

Это короткая процедура, и она ловит все типичные проблемы заранее: повреждённый архив из-за переполненного диска, недокачанный SQL, забытая директория в tar, проблемы с правами на чтение. Любая из них всплывает в боевой момент, когда восстанавливать надо за два часа.

Сколько хранить и как часто делать

Минимум для маленького сайта без интернет-магазина:

  • Ежедневно за 14 дней. Покрывает быстрые откаты после неудачных правок.
  • Еженедельно за 8 недель. Спасает от заражений, которые активировались с задержкой.
  • Ежемесячно за 12 месяцев. Архивный слой для редких сценариев и для соответствия 152-ФЗ по доказательствам.

Для интернет-магазина и сайтов с большим количеством заявок добавляете промежуточный слой: каждые 6 часов за последние 3 дня. На случай, когда заказы потеряны, и нужно вытащить именно сегодняшние.

Объём для типичного корпоративного сайта на WordPress без тяжёлых медиа:

  • База: 30-150 МБ в gzip.
  • Файлы: 200-800 МБ в gzip, в зависимости от количества картинок.
  • Год хранения по схеме выше: около 8-15 ГБ суммарно.

В Yandex Object Storage 15 ГБ обойдутся примерно в 100-150 рублей в месяц. На фоне стоимости разработки и переделки сайта это смешные деньги.

Когда стоит позвать подрядчика

Сделать первый раз пайплайн бэкапов это работа на 2-4 часа: настроить скрипт, проверить cron, настроить S3, прогнать тестовое восстановление. Потом он живёт сам и почти не требует внимания. Если эти 4 часа жалко или нет уверенности в результате, я обычно ставлю клиентам бэкап-конвейер за один заход и оставляю инструкцию.

Стоимость такой постановки на типичном сайте до 2 ГБ в моём случае попадает в обычную часовую ставку, без надбавок. Она же входит в любой из тарифов абонентского обслуживания на /#pricing. Если хочется только разово запустить инфраструктуру и дальше сами, напишите через /#contact, сделаю и отдам инструкцию. Дополнительно по теме: разделы /blog/category/security/ и /blog/category/support/ с инцидентами и миграциями.

Частые вопросы

Что должно быть в резервной копии

Папка с загрузками, тема, плагины и дамп базы данных. Ядро можно не включать: его проще скачать заново. Главное, чтобы файлы и база были сняты в один момент.

Как делать бэкапы без платных плагинов

Заданием по расписанию на хостинге: скрипт архивирует файлы, снимает дамп и отправляет всё во внешнее хранилище. Там, где есть консольный доступ, это несколько строк.

Куда класть копии

Не в папку сайта. Копия внутри загрузок пропадёт вместе с сайтом при заражении или блокировке. Внешнее хранилище стоит 50-150 рублей в месяц.

Как часто и сколько хранить

Ежедневно для сайта с заявками, раз в неделю для статичного. Хранить 14-30 дней плюс отдельные копии перед крупными изменениями.

Передайте техническую часть в надёжные руки.

Слежу за хостингом, бэкапами и обновлениями. Когда что-то пойдёт не так – звоните мне, не своему программисту, не в спортзал и не маме.

Короткие вопросы по теме

Все вопросы по теме "Безопасность сайта"

Заявка

Обсудим задачу

Напишите имя и телефон, выберите удобный канал. Перезвоню или напишу в течение часа в рабочее время.

Куда удобнее ответить?