DB Backup (dbbackdump) для Cotonti
Современный плагин резервного копирования и восстановления базы данных для CMS Cotonti. Работает в один процесс, поддерживает два движка (нативный mysqldump и чистый PHP), умеет корректно обрабатывать большие базы данных, показывает прогресс в реальном времени и не роняет сайт при дампах объёмом десятки гигабайт.
📑 Оглавление
- 1. Общие сведения
- 2. Принципы работы
- 3. Правила использования
- 4. Пошаговое руководство по установке
- 5. Пошаговое руководство по безопасности
- 5.1. Шаг 1: выбор места для хранения бэкапов
- 5.2. Шаг 2: защита директории бэкапов
- 5.3. Шаг 3: права на файлы
- 5.4. Шаг 4: защита AJAX-эндпоинта
- 5.5. Шаг 5: XK-токены и CSRF
- 5.6. Шаг 6: отдельный пользователь MySQL
- 5.7. Шаг 7: безопасность mysqldump
- 5.8. Шаг 8: HTTPS и заголовки
- 5.9. Шаг 9: регулярный аудит
- 5.10. Шаг 10: резервное копирование резервных копий
- 6. Пошаговое руководство по использованию
- 7. Возможные проблемы и их решения
- 7.1. Плагин не создаёт директорию для бэкапов
- 7.2. mysqldump не найден
- 7.3. Таймаут и обрыв соединения
- 7.4. Большие базы данных
- 7.5. Ошибка 500 при дампе
- 7.6. Не восстанавливаются таблицы
- 7.7. Memory limit exceeded
- 7.8. Кракозябры вместо кириллицы
- 7.9. Прерванный дамп остался висеть
- 7.10. Прогресс-бар не двигается
- 8. Логи и диагностика
- 9. FAQ — часто задаваемые вопросы
- 10. Обновление плагина
- 11. Удаление плагина
- 12. Дорожная карта
- 13. История изменений
- 14. Участие в разработке
- 15. Лицензия
- 16. Контакты и поддержка
1. Общие сведения
1.1. Что такое dbbackdump
dbbackdump — это плагин для CMS Cotonti, который предоставляет администратору сайта возможность создавать, скачивать, восстанавливать и удалять резервные копии базы данных MySQL прямо из административной панели, без необходимости заходить на сервер по SSH, использовать phpMyAdmin или сторонние утилиты.
Плагин разработан как «современная замена» устаревших решений для бэкапа БД, которые:
- грузят всю базу в память → падают на больших БД;
- не показывают прогресс → админ не понимает, работает ли операция;
- не дают отменить операцию → приходится ждать таймаута;
- не поддерживают потоковое восстановление → съедают всю память при restore;
- не умеют работать с
mysqldump→ медленно и неполно.
dbbackdump решает все эти проблемы.
1.2. Ключевые возможности
- Два движка дампа:
- native — использует системный
mysqldumpчерезproc_open()и сразу сжимает поток в gzip; - pure-PHP — если
mysqldumpнедоступен, дампит таблицы курсором по PRIMARY KEY батчами по 1000 строк;
- native — использует системный
- Потоковое восстановление — gzip читается порциями по 512 КБ, SQL-запросы разбираются «на лету» без загрузки всего дампа в память;
- Прогресс в реальном времени — через AJAX опрос состояния
.job.json; - Отмена операции — кнопка «Отменить» прерывает dump/restore на середине;
- Ротация бэкапов — автоматическое удаление старых копий по настройке
keep_backups; - Защита файлов —
.htaccess+index.phpсоздаются автоматически в папке бэкапов; - Безопасность — авторизация Cotonti + проверка XK-токена на каждом AJAX-запросе;
- Логирование — все ошибки пишутся в
.logвнутри папки бэкапов с усечённым SQL-хвостом.
1.3. Системные требования
| Компонент | Минимальная версия | Рекомендуемая |
|---|---|---|
| PHP | 8.5 | 8.5+ |
| MySQL | 8.0 | 8.4+ |
| MariaDB | 10.6 | 11.4+ |
| Cotonti | Verona 1.0.0 | Verona 1.0.0+ |
| Расширения PHP | pdo_mysql, zlib | + proc_open, exec |
Обязательные расширения PHP:
pdo_mysql— обязательно, иначе Cotonti не работает;zlib— обязательно, без него не будет gzip-сжатия;mbstring— для обрезки длинных SQL-ошибок в логе;json— встроен в PHP ≥ 8.0.
Опциональные расширения / функции:
proc_open— нужен для native-режимаmysqldump;exec— нужен для проверки версииmysqldump;ignore_user_abort— нужен для продолжения работы после закрытия вкладки.
Если proc_open/exec запрещены хостингом, плагин автоматически переключается на pure-PHP движок.
Важно: плагин использует класс Pdo\Mysql (новый API PHP 8.5). На PHP 8.4 и ниже работать не будет.
1.4. Совместимость
Плагин протестирован на:
- Cotonti Verona 1.0.0+;
- MySQL 8.0, 8.4;
- MariaDB 10.6 — 11.4;
- PHP 8.5;
- Apache 2.4, Nginx (с php-fpm), LiteSpeed.
1.5. Лицензия
BSD 3-Clause. Полный текст — в файле License.txt.
2. Принципы работы
2.1. Общая архитектура
Плагин состоит из четырёх основных частей:
- Админ-страница (
dbbackdump.admin.php+ шаблон) — UI, кнопки, таблица бэкапов. - AJAX-эндпоинт (
dbbackdump.ajax.php) — обработчик всех асинхронных запросов. - Библиотека функций (
inc/dbbackdump.functions.php) — вся логика. - Файл состояния (
.job.jsonв папке бэкапов) — «мост» между длительным процессом и AJAX-опросом.
Ключевая идея: всё работает в одном PHP-процессе. Плагин не использует cron, очереди, форки или фоновые воркеры. Запуск дампа/восстановления происходит прямо внутри AJAX-запроса start_dump/start_restore, а прогресс пишется в файл .job.json, который параллельно читается другими AJAX-запросами status.
Это даёт:
- простоту установки — не нужно настраивать cron или демоны;
- переносимость — работает на любом шаред-хостинге с PHP;
- прозрачность — легко отлаживать, все действия видны в логе.
2.2. Структура плагина
plugins/dbbackdump/
├── dbbackdump.setup.php # регистрация плагина и его конфигурации
├── dbbackdump.admin.php # контроллер админ-страницы
├── dbbackdump.ajax.php # AJAX-эндпоинт
├── inc/
│ └── dbbackdump.functions.php # ядро плагина
├── lang/
│ ├── dbbackdump.ru.lang.php # русская локализация
│ └── dbbackdump.en.lang.php # английская локализация
├── tpl/
│ └── dbbackdump.admin.tpl # шаблон админ-страницы
└── README.md # этот файл
2.3. Два движка резервного копирования
2.3.1. Native — mysqldump
Используется если:
- включена опция
prefer_mysqldump; - в
mysqldump_pathуказан существующий бинарь; - функция
exec()разрешена на хостинге.
Алгоритм:
- Запускается
mysqldumpчерезproc_open()с флагами--single-transaction --quick --routines --triggers --hex-blob --default-character-set=utf8mb4. - Пароль передаётся через переменную окружения
MYSQL_PWD— это исключает попадание пароля вps aux. - stdout процесса читается порциями по 128 КБ.
- Каждая порция немедленно пишется в gzip-файл.
- stderr читается отдельно, после завершения процесса, и при ненулевом exit-code выбрасывается исключение.
Плюсы: скорость, поддержка routines, triggers, events, корректное экранирование.
Минусы: нужен exec и proc_open; нужен mysqldump на сервере; версия клиента должна быть ≥ версии сервера.
2.3.2. Pure-PHP — cursor по PRIMARY KEY
Используется если mysqldump недоступен.
Алгоритм:
- Получаем список таблиц через
SHOW TABLES. - Для каждой таблицы:
- пишем
DROP TABLE IF EXISTS; - пишем результат
SHOW CREATE TABLE; - определяем PRIMARY KEY (
SHOW KEYS FROM ... WHERE Key_name='PRIMARY'); - читаем строки батчами по 1000 с сортировкой по PK;
- для следующего батча используем
WHERE pk > last_value— это защищает от «сдвига окна» при параллельной записи; - пишем
INSERT INTO ... VALUES (...), (...), ...;
- пишем
- Если у таблицы нет PRIMARY KEY — читаем всё за один
SELECT, но это опасно на больших таблицах.
Плюсы: работает везде, где есть PHP; не нужен mysqldump.
Минусы: медленнее; не сохраняет triggers, events, routines; хуже для таблиц без PRIMARY KEY; для полнотекстовых таблиц с тяжёлыми данными может тормозить.
2.4. Формат файла бэкапа
Файл — это обычный gzip-сжатый SQL-дамп, совместимый с:
mysql < backup.sql;gunzip < backup.sql.gz | mysql dbname;- phpMyAdmin (импорт);
- Adminer;
- любым другим SQL-клиентом.
Заголовок дампа:
-- Cotonti DB Backup (pure-PHP cursor)
-- 2026-10-16T12:34:56+00:00
-- DB: my_database
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS=0;
SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
SET time_zone='+00:00';
Далее — таблицы, и в конце:
SET FOREIGN_KEY_CHECKS=1;
Имя файла: backup_YYYY-MM-DD_HH-II-SS.sql.gz.
2.5. Процесс создания бэкапа
- Админ жмёт кнопку «Создать бэкап».
- JS отправляет AJAX-запрос
a=start_dumpс XK-токеном. dbbackdump_start_dump():- проверяет, не идёт ли уже другой процесс (читает
.job.json); - ставит
ignore_user_abort(true),set_time_limit(0),memory_limit=1024M; - генерирует имя файла и открывает gzip;
- пишет начальное состояние в
.job.json(status=running); - выбирает движок (mysqldump или pure-PHP);
- выполняет дамп;
- по завершении вызывает
dbbackdump_rotate()— удаляет старые копии; - пишет состояние
doneв.job.json.
- проверяет, не идёт ли уже другой процесс (читает
- Параллельно JS раз в 1200 мс дёргает
a=statusи обновляет прогресс-бар. - По завершении JS перезагружает страницу.
2.6. Процесс восстановления
Восстановление — самая сложная часть, потому что нужно:
- не загружать весь
.sql.gzв память; - корректно разбирать SQL с учётом кавычек, экранирования, многострочных строк и
;внутриINSERT; - показывать прогресс по мере чтения файла;
- уметь прерваться по нажатию «Отменить».
Алгоритм dbbackdump_run_restore():
- Устанавливает
FOREIGN_KEY_CHECKS=0,NAMES utf8mb4,SQL_MODE. - Открывает
.sql.gzчерезfopen('compress.zlib://...'). - Читает порциями по 512 КБ в буфер.
- Сканирует буфер посимвольно, отслеживая:
$inStr— внутри одинарной кавычки;$inBt— внутри бэктика (имя таблицы/колонки);$escape— после\;''— как экранированную кавычку внутри строки.
- Как только встречается
;вне строки и вне бэктика — весь текст до него считается запросом и выполняется черезCot::$db->query($sql). - Выполненный префикс удаляется из буфера (
substr($buffer, $i+1)), позиция$iсбрасывается в 0. - Важный момент:
$iне сбрасывается при чтении нового чанка — только после успешного выполнения запроса. Иначе кавычки в уже пройденной части буфера пересчитываются второй раз,$inStrзалипает,;перестаёт распознаваться и INSERT'ы молча пропускаются. - Каждые 50 выполненных запросов:
- обновляется
.job.json(прогресс поftell($fh) / filesize($path)); - проверяется, не нажал ли админ «Отменить».
- обновляется
- По завершении —
FOREIGN_KEY_CHECKS=1.
2.7. Система состояний (.job.json)
Файл .job.json в папке бэкапов — это «мост» между длительным процессом и AJAX-опросом. Структура:
{
"status": "running",
"type": "dump",
"file": "backup_2026-10-16_12-34-56.sql.gz",
"percent": 42,
"message": "Table x92374_pages (12/35)",
"started": 1760618096,
"finished": null,
"error": null
}
Возможные значения status:
| Статус | Что значит |
|---|---|
running |
Операция выполняется прямо сейчас |
done |
Успешно завершено |
error |
Ошибка, в поле error — текст |
cancelled |
Прервано пользователем |
| (отсутствует) | Файла нет → плагин считает, что ничего не идёт |
2.8. AJAX API
Все запросы идут на index.php?r=dbbackdump&a=<action>&x=<XK>.
| Action | Метод | Параметры | Возвращает |
|---|---|---|---|
start_dump |
GET | — | {status, percent, message} |
start_restore |
GET | name=<файл> |
{status, percent, message} |
status |
GET | — | {status, percent, message, file, error} |
cancel |
GET | — | {ok: true} |
download |
GET | name=<файл> |
бинарный gzip |
Все ответы (кроме download) — JSON вида:
{ "ok": true, "data": { ... } }
или
{ "ok": false, "error": "текст ошибки" }
2.9. Логирование
Файл .log в папке бэкапов. Формат:
2026-10-16T12:34:56+00:00 DUMP OK backup_2026-10-16_12-34-56.sql.gz
2026-10-16T12:35:10+00:00 RESTORE OK backup_2026-10-16_12-34-56.sql.gz
2026-10-16T12:36:22+00:00 SQL error: SQLSTATE[42S02]: Base table or view not found | SQL head: DROP TABLE IF EXISTS `foo`
Правило: если что-то пошло не так при восстановлении — первым делом смотрите .log.
2.10. Ротация бэкапов
После каждого успешного дампа вызывается dbbackdump_rotate(). Она читает конфиг keep_backups (по умолчанию 14) и удаляет все копии, начиная с 15-й по счёту (сортировка — по дате изменения, новые вверху).
Если keep_backups = 0 — ротация выключена, копии накапливаются.
3. Правила использования
3.1. Права доступа
Доступ к плагину имеют только администраторы Cotonti с правом plug.dbbackdump.A. Это проверяется в:
dbbackdump.admin.php— для страницы настроек;dbbackdump.ajax.php— для всех AJAX-действий.
Не-администратор получит HTTP 403.
3.2. Ограничения
- Один процесс одновременно. Нельзя запустить два дампа параллельно — второй запрос вернёт текущий статус первого.
- Только MySQL / MariaDB. PostgreSQL, SQLite и др. не поддерживаются.
- Только
.sql.gzв папке бэкапов. Файлы с другим расширением не видны в списке и не удаляются. - Только встроенный gzip. Формат
.zip,.bz2,.xzне поддерживается. - Нет автоматического расписания. Плагин не делает бэкапы по cron — это осознанное решение, чтобы не плодить забытые задачи. Если нужно — настраивайте внешний cron и дёргайте AJAX или CLI-скрипт.
3.3. Рекомендации по эксплуатации
- Держите
keep_backupsв разумных пределах. 14 копий — оптимально для большинства сайтов. - Храните внешнюю копию: раз в неделю скачивайте свежий бэкап и складывайте его на отдельный носитель / в облако / на другой сервер.
- Перед обновлением Cotonti, установкой новых плагинов или крупными изменениями — всегда делайте бэкап.
- Восстанавливайте БД только в момент минимальной нагрузки (ночью), особенно если у вас много посетителей.
- Периодически проверяйте
.log— там могут быть «тихие» ошибки SQL. - Не отключайте встроенный
.htaccessи не удаляйтеindex.phpиз папки бэкапов.
3.4. Что категорически нельзя делать
- ❌ Удалять
.htaccessиindex.phpиз папки бэкапов. - ❌ Размещать папку бэкапов внутри
public_htmlбез защиты (deny from all). - ❌ Указывать
backup_dirс правами777— только755(или750,770в зависимости от конфигурации). - ❌ Запускать восстановление поверх работающего сайта — сначала включите режим обслуживания.
- ❌ Использовать root MySQL для плагина — используйте отдельного пользователя с правами только на нужную БД.
- ❌ Прерывать дамп через
killall php-fpmили перезагрузку сервера — можно получить битый.sql.gz(правда, плагин удалит его при рестарте, но лучше не доводить). - ❌ Хранить бэкапы только на том же диске, где и БД — умрёт диск, умрут и данные, и бэкапы.
4. Пошаговое руководство по установке
4.1. Способ 1: через админку Cotonti
- Скачайте архив плагина с GitHub:
dbbackdump-cotonti-x.y.z.zip. - Войдите в админку Cotonti под администратором.
- Перейдите в Расширения → Управление плагинами (
/admin.php?m=extensions). - Нажмите «Установить новый плагин» или «Upload plugin».
- Выберите скачанный
.zipи подтвердите установку. - Плагин появится в списке. Если он не активирован автоматически — нажмите «Установить».
- Перейдите в Инструменты → DB Backup (
/admin.php?m=other&p=dbbackdump).
4.2. Способ 2: вручную через FTP/SFTP
- Скачайте плагин с GitHub.
- Распакуйте архив локально.
- Загрузите папку
dbbackdump/в/plugins/вашего Cotonti-сайта. - Убедитесь, что структура такая:
/plugins/dbbackdump/dbbackdump.setup.php /plugins/dbbackdump/dbbackdump.admin.php /plugins/dbbackdump/dbbackdump.ajax.php /plugins/dbbackdump/inc/dbbackdump.functions.php /plugins/dbbackdump/lang/dbbackdump.ru.lang.php /plugins/dbbackdump/lang/dbbackdump.en.lang.php /plugins/dbbackdump/tpl/dbbackdump.admin.tpl - Войдите в админку Cotonti.
- Перейдите в Расширения → Управление плагинами.
- Найдите
dbbackdumpв списке и нажмите «Установить». - Убедитесь, что плагин активен.
- Перейдите в Инструменты → DB Backup.
4.3. Настройка прав доступа
Плагин создаёт папку для бэкапов автоматически. По умолчанию это datas/dbbackdump относительно корня сайта. Права:
# через SSH
chmod 755 /path/to/site/datas/dbbackdump
chown www-data:www-data /path/to/site/datas/dbbackdump # пользователь веб-сервера
Если хостинг без SSH — используйте файловый менеджер в панели управления и выставьте права 755.
Если папка не создаётся автоматически — создайте её вручную и выставьте 755.
4.4. Конфигурирование плагина
Перейдите в Расширения → Управление плагинами → dbbackdump → Настройки. Доступны 4 параметра:
| Параметр | Значение по умолчанию | Описание |
|---|---|---|
backup_dir |
datas/dbbackdump |
Папка для бэкапов (относительно корня сайта или абсолютный путь) |
keep_backups |
14 |
Сколько последних копий оставлять (0 = без ограничения) |
prefer_mysqldump |
1 |
Использовать mysqldump, если доступен |
mysqldump_path |
/usr/bin/mysqldump |
Абсолютный путь к mysqldump |
Пример безопасной конфигурации:
backup_dir = /var/backups/cotonti/dbbackdump (вне public_html!)
keep_backups = 14
prefer_mysqldump = 1
mysqldump_path = /usr/bin/mysqldump
Если папка вне public_html — скачивание через браузер не будет работать, но сам дамп/restore будет. Тогда скачивание делайте через SSH/rsync.
4.5. Проверка работоспособности
- Откройте Инструменты → DB Backup.
- Убедитесь, что в шапке отображается:
- Движок:
mysqldump (native)— если mysqldump доступен; - Движок:
pure-PHP (cursor)— если нет.
- Движок:
- Нажмите «Создать бэкап».
- Дождитесь завершения — прогресс-бар должен дойти до 100%.
- Проверьте папку
datas/dbbackdump/— там должен быть файлbackup_*.sql.gzи файл.log. - Скачайте бэкап и откройте его архиватором — внутри должен быть читаемый SQL.
- Удалите тестовый бэкап (или оставьте как первый рабочий).
Готово. Плагин установлен и работает.
5. Пошаговое руководство по безопасности
Безопасность резервных копий — это критическая часть. Дамп содержит всю базу: логины, пароли (в виде хешей), email, личные сообщения, IP-адреса. Утечка дампа = полный компромисс сайта.
Ниже — 10 шагов, которые нужно пройти после установки.
5.1. Шаг 1: выбор места для хранения бэкапов
Плохой вариант:
/var/www/site/public_html/datas/dbbackdump/
Если сервер вдруг отдаст файл по прямой ссылке (а он отдаст, если не сработает .htaccess), дамп скачает любой, кто знает URL.
Хороший вариант:
/var/backups/cotonti/dbbackdump/
или любая директория вне корня сайта. В настройках плагина укажите абсолютный путь:
backup_dir = /var/backups/cotonti/dbbackdump
Внимание: data/, datas/, storage/ и подобные директории часто уже находятся вне public_html — это уже хорошо. Проверьте это на своём хостинге.
5.2. Шаг 2: защита директории бэкапов
Если папка всё-таки внутри public_html — плагин автоматически создаст два файла:
.htaccess(для Apache):Require all denied Deny from all Options -Indexesindex.php— заглушка для директорий безindex:<?php http_response_code(403);
Проверьте оба файла после первого запуска плагина. Если их нет — создайте вручную.
Для Nginx: .htaccess не работает. Добавьте в конфиг сервера:
location ^~ /datas/dbbackdump/ {
deny all;
return 403;
}
Для LiteSpeed .htaccess работает, но проверьте, что AllowOverride All включён для вашего vhost.
5.3. Шаг 3: права на файлы
chmod 755 /var/backups/cotonti/dbbackdump
chmod 640 /var/backups/cotonti/dbbackdump/*.sql.gz
chmod 640 /var/backups/cotonti/dbbackdump/.log
chmod 640 /var/backups/cotonti/dbbackdump/.job.json
Никогда не выставляйте 777 — это открывает папку для записи любому пользователю системы.
5.4. Шаг 4: защита AJAX-эндпоинта
AJAX-эндпоинт (index.php?r=dbbackdump) уже защищён:
- проверкой авторизации (
cot_auth('plug', 'dbbackdump', 'A')); - проверкой XK-токена (
cot_check_xg()).
Что можно усилить:
- Добавить HTTP Basic Auth на
/index.php?r=dbbackdumpчерез.htaccess(двойная защита). - Ограничить доступ по IP в
.htaccess:<If "%{QUERY_STRING} =~ /r=dbbackdump/"> Require ip 203.0.113.42 Require ip 198.51.100.0/24 </If> - Вести лог всех запросов к AJAX-эндпоинту.
5.5. Шаг 5: XK-токены и CSRF
Cotonti использует XK-токены (аналог CSRF-токенов) для всех действий, изменяющих состояние. Плагин проверяет токен на каждом AJAX-запросе через cot_check_xg().
Что это даёт: даже если злоумышленник обманом заставит админа открыть вредоносную страницу, браузер не сможет выполнить запрос без правильного XK.
Что можно улучшить:
- Убедитесь, что
Cot::$sys['xk']не утекает в JS-консоль / сторонние скрипты. - Не отключайте
cot_check_xg()ни при каких обстоятельствах. - Если вы используете CDN или сторонние виджеты — проверьте, что они не читают
data-xkатрибут.
5.6. Шаг 6: отдельный пользователь MySQL
Не используйте root MySQL для сайта. Создайте отдельного пользователя:
CREATE USER 'cotonti_backup'@'localhost' IDENTIFIED BY 'strong_password_here';
GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON `your_db`.* TO 'cotonti_backup'@'localhost';
-- Для восстановления также нужны:
GRANT INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX, REFERENCES ON `your_db`.* TO 'cotonti_backup'@'localhost';
FLUSH PRIVILEGES;
Пропишите этого пользователя в конфиге Cotonti (datas/config.php → $cfg['mysqluser'], $cfg['mysqlpassword']).
Преимущество: если пароль утечёт через дамп/лог, злоумышленник не получит root-доступ.
5.7. Шаг 7: безопасность mysqldump
Плагин передаёт пароль MySQL через переменную окружения MYSQL_PWD, а не через командную строку. Это значит, что пароль не виден в ps aux.
Проверьте, что на сервере:
mysqldumpне имеет suid-бита (ls -l $(which mysqldump)— не должно бытьsв правах);proc_openиexecразрешены вdisable_functions(если нет — используется pure-PHP);- версия
mysqldump≥ версии MySQL-сервера (иначе возможны проблемы с совместимостью).
5.8. Шаг 8: HTTPS и заголовки
Плагин работает по тому же протоколу, что и админка. Обязательно используйте HTTPS:
- без HTTPS XK-токен и содержимое дампа могут быть перехвачены;
- куки админа передаются в открытом виде (если не установлен флаг
Secure).
Убедитесь, что:
- на сервере стоит валидный TLS-сертификат (Let's Encrypt);
- HTTP редиректит на HTTPS;
- куки сессии имеют флаги
Secure,HttpOnly,SameSite=Lax(илиStrict).
5.9. Шаг 9: регулярный аудит
Раз в месяц:
- Проверьте
.logна ошибки и подозрительные записи. - Проверьте список бэкапов — нет ли лишних файлов.
- Проверьте
.htaccess— не изменён ли. - Проверьте права на папку — не
777ли. - Проверьте, что ротация работает (старые файлы удаляются).
- Сделайте тестовое восстановление на отдельной копии сайта (staging).
5.10. Шаг 10: резервное копирование резервных копий
Золотое правило: 3-2-1.
- 3 копии данных;
- 2 разных носителя;
- 1 копия вне офиса (вне сервера).
Минимум: раз в неделю скачивайте свежий бэкап и складывайте:
- на локальный компьютер;
- в облако (Яндекс.Диск, Google Drive, Dropbox, S3);
- на резервный сервер.
Автоматизировать можно через cron:
# Каждый день в 04:00 забирать все свежие дампы
0 4 * * * rsync -avz --remove-source-files user@site:/var/backups/cotonti/dbbackdump/ /home/backup/cotonti/
6. Пошаговое руководство по использованию
6.1. Создание резервной копии
- Откройте Инструменты → DB Backup.
- Убедитесь, что ни один процесс не идёт (прогресс-бар скрыт).
- Нажмите «Создать бэкап».
- Появится прогресс-бар и кнопка «Отменить».
- Дождитесь завершения — статус станет
done, прогресс 100%, страница перезагрузится. - Новый бэкап появится в таблице сверху.
Сколько это длится? Зависит от размера БД и выбранного движка:
| Размер БД | mysqldump | pure-PHP |
|---|---|---|
| 10 МБ | 1-2 сек | 3-5 сек |
| 100 МБ | 5-15 сек | 30-60 сек |
| 1 ГБ | 1-2 мин | 5-15 мин |
| 10 ГБ | 10-20 мин | 1-3 часа |
6.2. Скачивание бэкапа
- Найдите нужный файл в таблице.
- Нажмите «Скачать» — файл начнёт скачиваться.
- Файл отдаётся как
application/gzipс заголовкомContent-Disposition: attachment.
Внимание: скачивание идёт через AJAX-эндпоинт, то есть через PHP. Это значит:
- если у вас лимит
max_execution_time = 30и файл скачивается дольше — процесс может быть убит; - для больших файлов (>1 ГБ) лучше использовать SFTP/rsync.
6.3. Восстановление из бэкапа
⚠️ Восстановление полностью перезаписывает текущую БД. Все данные, появившиеся после создания бэкапа, будут потеряны.
- Включите режим обслуживания. В Cotonti это делается через админку (Настройки → Основные → Режим обслуживания) или вручную.
- Убедитесь, что у вас есть актуальный бэкап (сделан только что) — на случай, если восстановление пойдёт не так.
- Откройте Инструменты → DB Backup.
- Найдите в таблице нужный бэкап.
- Нажмите «Восстановить».
- Подтвердите действие в диалоге.
- Дождитесь завершения прогресса — статус станет
done. - Проверьте
.logна ошибки SQL. - Зайдите на сайт, проверьте ключевые страницы.
- Выключите режим обслуживания.
Если восстановление упало на середине: часть таблиц уже перезаписана, часть нет. Единственный способ гарантированно починить — снова запустить восстановление из того же бэкапа. Не пытайтесь «доделать руками» — почти всегда получите несогласованные данные.
6.4. Удаление бэкапа
- Найдите файл в таблице.
- Нажмите «Удалить».
- Подтвердите действие.
- Страница перезагрузится, файл исчезнет из списка.
Внимание: удаление необратимо. Файл физически стирается с диска.
6.5. Отмена операции
- Если операция выполняется — доступна кнопка «Отменить».
- Нажмите её.
- Плагин установит статус
cancelledв.job.json. - Процесс дампа/restore увидит это при следующей проверке (каждые 50 запросов при restore, раз в таблицу при dump) и прервётся.
- Файл бэкапа (при dump) будет удалён.
Внимание: отмена — это не мгновенный процесс. При restore может пройти несколько секунд, пока текущий батч запросов не завершится. При dump на больших таблицах — тоже.
7. Возможные проблемы и их решения
7.1. Плагин не создаёт директорию для бэкапов
Симптом: ошибка «Cannot create /path/to/datas/dbbackdump».
Причины и решения:
-
Нет прав на родительскую директорию.
chmod 755 /path/to/datasИли укажите
backup_dirв существующую директорию, куда есть права на запись. -
Директория вне открытых путей
open_basedir.
Проверьтеphpinfo()→open_basedir. Если путь не входит — укажитеbackup_dirвнутри разрешённой зоны. -
Диск заполнен.
df -hОсвободите место или перенесите папку.
-
SELinux / AppArmor блокирует запись.
sudo restorecon -Rv /var/backups/cotonti/Или настройте политику.
7.2. mysqldump не найден
Симптом: в шапке отображается pure-PHP (cursor), хотя prefer_mysqldump = 1.
Причины и решения:
-
Неверный путь к
mysqldump.which mysqldump # /usr/bin/mysqldumpПропишите этот путь в настройках.
-
exec()вdisable_functions.
Проверьтеphpinfo()→disable_functions. Еслиexecилиproc_openтам есть — используйте pure-PHP (просто отключитеprefer_mysqldump). -
mysqldumpне установлен.sudo apt install mysql-client # Debian/Ubuntu sudo yum install mysql # CentOS/RHEL -
Нет прав на выполнение.
ls -l $(which mysqldump) # должно быть -rwxr-xr-x
7.3. Таймаут и обрыв соединения
Симптом: процесс начинается, но через 30-60 секунд падает с ошибкой 504 Gateway Timeout или 500.
Причины и решения:
-
max_execution_time.
Плагин вызываетset_time_limit(0), но на некоторых хостингах это запрещено. Проверьте:php -i | grep max_execution_timeЕсли стоит
30и не переопределяется — обратитесь в поддержку хостинга. -
Nginx
fastcgi_read_timeout.fastcgi_read_timeout 3600s; fastcgi_send_timeout 3600s;Перезагрузите nginx:
sudo systemctl reload nginx. -
Apache
TimeOut.TimeOut 3600Или через
.htaccess:<IfModule mod_reqtimeout.c> RequestReadTimeout header=0 body=0 </IfModule> -
Cloudflare / CDN.
Cloudflare по умолчанию режет запросы >100 секунд. Включите «Bypass Cache» для URLindex.php?r=dbbackdump*или отключите проксирование для админки. -
Балансировщик нагрузки.
Если сайт за LB — увеличьтеidle timeoutдо 1 часа.
7.4. Большие базы данных
Симптом: дамп большой БД (>5 ГБ) падает, gzip-файл битый.
Решения:
- Используйте mysqldump. Pure-PHP для 10+ ГБ — это часы работы. С mysqldump — минуты.
- Разбейте таблицы. Если есть гигантские таблицы (логи, кеш) — исключите их из дампа или дампите отдельно.
- Увеличьте
memory_limit.memory_limit = 2048M - Проверьте
tmpdir. При работе с большими таблицами MySQL может писать во временные файлы. Убедитесь, что места хватает:df -h /tmp
7.5. Ошибка 500 при дампе
Симптом: AJAX-запрос падает с HTTP 500, ничего не пишется в .log.
Причины и решения:
-
Фатальная ошибка PHP. Смотрите
error_logPHP:tail -f /var/log/php/error.logИли в панели хостинга.
-
Превышен
memory_limit. Увеличьте до 512-1024 МБ. -
proc_openне разрешён. Отключитеprefer_mysqldump. -
Ошибка парсинга SQL в pure-PHP. Проверьте, что версия PHP ≥ 8.5.
7.6. Не восстанавливаются таблицы
Симптом: прогресс доходит до 100%, но данные не появились. В .log — ничего.
Причина: это была классическая проблема со сбросом $i в старых версиях плагина. Если у вас версия < 3.0.1 — обновитесь.
Проверка: в логе должно быть RESTORE OK. Если его нет — процесс упал молча, ищите причину в error_log PHP.
Если версия ≥ 3.0.1 и всё равно не работает:
- Проверьте, что SQL-дамп валиден. Распакуйте gzip и посмотрите глазами:
gunzip -c backup_*.sql.gz | head -100 - Проверьте, что в дампе есть нужные таблицы:
gunzip -c backup_*.sql.gz | grep -c "^INSERT INTO" - Проверьте
.logна конкретные ошибки SQL. Если естьSQL error— плагин «проглотил» проблемный запрос. Найдите его поSQL head:и разберитесь вручную.
7.7. Memory limit exceeded
Симптом: Allowed memory size of XXX bytes exhausted.
Решения:
- Увеличьте
memory_limitдо 1024 МБ. - Плагин уже ставит
ini_set('memory_limit', '1024M'), но если хостинг блокируетini_set— не поможет. Тогда используйте pure-PHP (не mysqldump) или разбейте БД.
7.8. Кракозябры вместо кириллицы
Симптом: после восстановления вместо русских букв — ???? или Привет.
Причины и решения:
-
Дамп в другой кодировке. Проверьте заголовок дампа:
gunzip -c backup_*.sql.gz | head -5Должно быть
SET NAMES utf8mb4;. -
База не в
utf8mb4. Проверьте:SHOW CREATE DATABASE my_db;Если кодировка не
utf8mb4— плагин не виноват, проблема в исходной БД. -
Соединение не в
utf8mb4. Проверьтеdatas/config.php→$cfg['mysqlcharset'].
7.9. Прерванный дамп остался висеть
Симптом: .job.json содержит status=running, но никакой процесс не идёт. Кнопки «Создать бэкап» — disabled.
Решение: удалите .job.json вручную:
rm /path/to/backups/.job.json
Внимание: перед удалением убедитесь, что процесс точно не идёт (ps aux | grep php). Иначе вы удалите «мост» между процессом и UI, но процесс продолжит работу.
7.10. Прогресс-бар не двигается
Симптом: прогресс-бар застыл на 0% или на N%, не двигается.
Причины и решения:
setIntervalв JS остановился. Проверьте консоль браузера на ошибки.- AJAX-запрос
statusвозвращает 403 или 500. Проверьте Network в DevTools. - XK-токен истёк. Перезагрузите страницу.
- Файл
.job.jsonне пишется. Проверьте права на папку бэкапов (755) и на сам файл (640). - Долгая таблица. На больших таблицах прогресс может стоять минутами. Просто подождите.
8. Логи и диагностика
8.1. Где смотреть
| Что | Где |
|---|---|
| Лог плагина | datas/dbbackdump/.log |
| Текущее состояние | datas/dbbackdump/.job.json |
| PHP-ошибки | /var/log/php/error.log, error_log сайта |
| Ошибки MySQL | /var/log/mysql/error.log |
| Ошибки Apache | /var/log/apache2/error.log |
| Ошибки Nginx | /var/log/nginx/error.log |
8.2. Что смотреть в первую очередь
.job.json— какой статус..log— есть лиSQL error,DUMP FAIL,RESTORE FAIL.- DevTools → Network — какие AJAX-запросы идут, что возвращают.
- DevTools → Console — есть ли JS-ошибки.
error_logPHP — есть ли fatal errors.
8.3. Включение подробного логирования
Cotonti умеет логировать SQL-запросы в режиме разработки. В datas/config.php:
$cfg['debug_mode'] = true;
$cfg['devmode'] = true;
После этого все запросы плагина (включая restore) будут видны в дебаг-панели Cotonti с временем выполнения и stack trace.
Внимание: не оставляйте эти флаги включёнными на production.
9. FAQ — часто задаваемые вопросы
Общее
Q: Плагин делает бэкап по расписанию?
A: Нет. Расписание — это задача cron, а не плагина. Настройте внешний cron, который будет дёргать AJAX-эндпоинт start_dump с валидным XK.
Q: Плагин умеет бэкапить файлы (картинки, вложения)?
A: Нет. Только БД. Для файлов используйте tar/rsync.
Q: Плагин работает с PostgreSQL?
A: Нет. Только MySQL и MariaDB.
Q: Плагин работает на Cotonti Verona?
A: Да, начиная с версии 3.0.0. Плагин рассчитан на Cotonti Verona 1.0.x (PHP 8.5).
Q: Что делать, если хостинг запрещает proc_open?
A: Плагин автоматически переключится на pure-PHP движок. Просто убедитесь, что prefer_mysqldump не мешает.
Q: Можно ли восстановить отдельную таблицу?
A: Штатно — нет. Но можно распаковать .sql.gz и вырезать нужный INSERT INTO, затем выполнить вручную через phpMyAdmin.
Безопасность
Q: Дампы доступны из браузера по прямой ссылке?
A: Нет, если .htaccess или конфиг Nginx корректны. Проверьте вручную.
Q: Что если .htaccess не работает (Nginx)?
A: Добавьте location ^~ /путь/к/бэкапам/ { deny all; } в конфиг Nginx.
Q: Пароль MySQL попадает в логи?
A: Нет, плагин передаёт пароль через MYSQL_PWD, а не через аргументы командной строки.
Q: Нужен ли HTTPS?
A: Обязательно. Без HTTPS XK-токен и содержимое дампа могут быть перехвачены.
Q: Можно ли давать доступ к плагину не-админам?
A: Нет. Только админы с правом plug.dbbackdump.A.
Использование
Q: Сколько времени занимает создание бэкапа?
A: Зависит от размера БД и движка. См. таблицу в разделе 6.1.
Q: Можно ли запустить два дампа одновременно?
A: Нет. Второй запрос вернёт статус первого.
Q: Что делать, если дамп упал на середине?
A: Проверьте .log и error_log PHP. Обычно это memory_limit, max_execution_time или ошибка SQL.
Q: Что делать, если restore упал на середине?
A: Запустите снова. Не пытайтесь «доделать руками».
Q: Как отменить операцию?
A: Кнопка «Отменить» в UI. Отмена срабатывает не мгновенно.
Q: Где хранятся бэкапы?
A: В папке, указанной в backup_dir. По умолчанию datas/dbbackdump.
Q: Как изменить папку бэкапов?
A: В настройках плагина.
Q: Как изменить количество хранимых копий?
A: Параметр keep_backups.
Q: Как отключить ротацию?
A: Поставить keep_backups = 0.
Проблемы
Q: Плагин не видит старые бэкапы.
A: Проверьте расширение файла — только .sql.gz. Проверьте права на чтение.
Q: Прогресс-бар не двигается.
A: Проверьте Network в DevTools. Возможно, истёк XK-токен — перезагрузите страницу.
Q: Ошибка «Call to undefined method CotDB::exec()».
A: Это баг старых версий плагина. Обновитесь до 3.0.1+. В новых версиях везде используется CotDB::query().
Q: Восстановление прошло, но данные не появились.
A: Проверьте .log на SQL error. Скорее всего, один из запросов упал. Найдите по SQL head: и разберитесь вручную.
Q: Кракозябры после восстановления.
A: Проверьте кодировку БД и соединения (utf8mb4).
Q: Долго восстанавливается большая таблица.
A: Нормально. Pure-PHP восстановление 10+ ГБ может занимать часы. Используйте mysqldump для дампа и mysql < backup.sql через SSH для восстановления.
10. Обновление плагина
- Сделайте бэкап БД штатным способом.
- Скачайте новую версию с GitHub.
- В админке Cotonti → Расширения → dbbackdump → «Обновить».
- Если обновление через админку недоступно — распакуйте поверх старой папки, сохранив
datas/dbbackdump/с бэкапами. - Проверьте настройки плагина — иногда добавляются новые параметры.
- Сделайте тестовый дамп для проверки.
11. Удаление плагина
- Сделайте финальный бэкап БД.
- Скачайте все нужные бэкапы из папки
datas/dbbackdump/— при удалении плагина они не удаляются, но лучше перестраховаться. - В админке Cotonti → Расширения → dbbackdump → «Удалить».
- Удалите папку
/plugins/dbbackdump/вручную, если она осталась. - Удалите папку
datas/dbbackdump/вручную, если она не нужна.
12. Дорожная карта
- [ ] CLI-режим для запуска из cron без HTTP.
- [ ] Хранение бэкапов в S3-совместимых хранилищах.
- [ ] Шифрование дампов на лету (age, gpg).
- [ ] Поддержка PostgreSQL.
- [ ] Выборочное восстановление отдельных таблиц.
- [ ] Дифференциальные дампы.
- [ ] Веб-интерфейс для просмотра
.log. - [ ] Уведомления по email после завершения дампа.
13. История изменений
v3.0.1 (2026-10-16)
- Исправлен баг с парсером SQL в
dbbackdump_run_restore(): сброс$iвнутри циклаfreadприводил к молчаливому пропуску INSERT'ов. - Улучшено логирование ошибок SQL — теперь пишется
SQL head(первые 300 символов проблемного запроса). - Верстка админки переведена на Bootstrap 5.3.
- Все хардкодные русские строки вынесены в
.lang.php. - Исправлены устаревшие требования: PHP 8.5, Cotonti Verona 1.0.x.
v3.0.0 (2026-10-01)
- Полностью переписан с нуля.
- Два движка: mysqldump и pure-PHP cursor.
- Потоковое восстановление без загрузки в память.
- Прогресс в реальном времени через AJAX.
- Отмена операций.
- Автоматическая защита папки бэкапов.
14. Участие в разработке
Pull-request'ы приветствуются. Перед отправкой:
- Форкните репозиторий.
- Создайте ветку
feature/your-featureилиfix/your-bug. - Следуйте PSR-12.
- Добавьте тесты, если возможно.
- Обновите
README.mdиCHANGELOG. - Отправьте PR с описанием: что, зачем, как проверить.
15. Лицензия
BSD 3-Clause. См. License.txt.
16. Контакты и поддержка
- GitHub Issues: github.com/webitproff/dbbackdump-cotonti/issues
- Cotonti Forum: abuyfile.com/ru/forums/cotonti/custom/plugs
- Author: webitproff