Бэкап и восстановление SonarQube
SonarQube годами копит историю анализа кода: quality gate, тренды покрытия, настроенные профили правил под конкретный проект — восстановить это руками после сбоя диска или неудачного обновления невозможно. Хорошая новость в том, что весь ценный слепок состояния живёт всего в нескольких местах, и бэкапить SonarQube проще, чем кажется, если понимать, что действительно нужно сохранять, а что можно пересобрать за пару минут после восстановления.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Архитектура SonarQube и что действительно нужно бэкапить
У SonarQube три хранилища данных с принципиально разной ценностью:
- PostgreSQL — единственная база данных, которую поддерживает SonarQube начиная с 8-й ветки. Здесь лежит всё: проекты, история измерений, quality profiles и quality gates, пользователи и права, настройки webhook'ов, привязка к CI, лицензия (для Developer/Enterprise редакций). Это критичные данные — без них SonarQube превращается в чистую установку.
- Elasticsearch-индекс (каталог
data/es*внутри$SONARQUBE_HOME, у контейнерной установки — томsonarqube_data) — поисковый индекс по issues и hotspot'ам. Он полностью производный от содержимого БД: если индекс отсутствует или повреждён, SonarQube перестраивает его сам при следующем запуске. Включать в бэкап не обязательно — это просто лишний вес и время на упаковку. - Конфигурация и плагины —
conf/sonar.propertiesи каталогextensions/plugins(в Docker — томаsonarqube_extensions, у части инсталляций конфиг задаётся через переменные окружения и живёт в docker-compose.yml, а не в файле). Плагины (SonarC#, checkstyle-правила, кастомные quality profiles в виде XML) переустанавливать вручную после сбоя — отдельное неприятное занятие, особенно если версии плагинов подбирались под конкретную версию ядра.
Итог простой: обязательный бэкап — это дамп PostgreSQL плюс конфиг и плагины. Индекс Elasticsearch и логи в бэкап не идут.
Бэкап базы данных PostgreSQL
Для консистентного снимка используется pg_dump в custom-формате — он даёт сжатие «из коробки» и позволяет восстанавливать выборочно через pg_restore. Дамп снимает MVCC-снапшот на момент старта, поэтому останавливать SonarQube для самого дампа не обязательно — база продолжает принимать запросы во время выгрузки.
Если PostgreSQL работает в контейнере рядом с SonarQube (типичная docker-compose связка):
docker exec -t sonarqube-db pg_dump -U sonar -F c -d sonar \
-f /tmp/sonar_db.dump
docker cp sonarqube-db:/tmp/sonar_db.dump ./sonar_db_$(date +%F).dump
docker exec sonarqube-db rm /tmp/sonar_db.dump
Если PostgreSQL вынесен на отдельный сервер или установлен на хосте напрямую — смотрите отдельную статью про установку PostgreSQL на VPS, там же разбор pg_hba.conf и прав доступа, которые нередко мешают именно бэкапу под отдельным сервисным пользователем:
sudo -u postgres pg_dump -F c -d sonar -f /backup/sonar_db_$(date +%F).dump
Полезно завести отдельного read-only-по-факту пользователя sonar_backup только с правом CONNECT и pg_read_all_data — так дамп не зависит от смены пароля основной учётки приложения, и в логах видно, кто именно снимал бэкап.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверБэкап конфигурации и данных SonarQube
Для bare-metal установки ($SONARQUBE_HOME обычно /opt/sonarqube) конфиг и плагины архивируются напрямую:
tar -czf sonar_conf_$(date +%F).tar.gz -C /opt/sonarqube conf
tar -czf sonar_extensions_$(date +%F).tar.gz -C /opt/sonarqube extensions
Для контейнерной установки, где плагины и конфиг лежат в именованных томах, проще всего временно смонтировать том в служебный контейнер:
docker run --rm \
-v sonarqube_extensions:/data:ro \
-v "$(pwd)":/backup \
alpine tar czf /backup/sonar_extensions_$(date +%F).tar.gz -C /data .
Том с данными (sonarqube_data) в архив можно не включать вовсе — там как раз тот самый Elasticsearch-индекс, который перестраивается из базы. Если всё же хочется его сохранить (ускоряет старт после восстановления на той же версии), архивируйте только когда контейнер SonarQube остановлен — иначе Lucene-сегменты могут попасть в архив в процессе записи и получиться повреждённый индекс, который потом всё равно придётся снести и пересобрать.
Автоматизация: скрипт и cron
Собираем всё в один скрипт с ротацией и выгрузкой во внешнее хранилище — держать бэкапы только на том же диске, что и сам сервер, бессмысленно.
#!/bin/bash
set -euo pipefail
BACKUP_ROOT="/backup/sonarqube"
DATE=$(date +%F_%H-%M)
DEST="$BACKUP_ROOT/$DATE"
RETENTION_DAYS=14
DB_CONTAINER="sonarqube-db"
DB_NAME="sonar"
DB_USER="sonar"
mkdir -p "$DEST"
docker exec -t "$DB_CONTAINER" pg_dump -U "$DB_USER" -F c -d "$DB_NAME" \
> "$DEST/sonar_db.dump"
docker run --rm -v sonarqube_extensions:/data:ro -v "$DEST":/backup \
alpine tar czf /backup/sonar_extensions.tar.gz -C /data .
# конфиг задан через docker-compose.yml — храните его отдельно в git,
# сюда добавляйте только если конфиг реально лежит в volume/файле
find "$BACKUP_ROOT" -maxdepth 1 -type d -mtime +"$RETENTION_DAYS" -exec rm -rf {} \;
rclone copy "$DEST" remote:sonarqube-backups/"$DATE" --log-file="$DEST/rclone.log"
Ставим в cron с запуском в окно низкой нагрузки — для SonarQube это обычно ночь или выходные, когда CI не гоняет анализ веткой за веткой:
0 2 * * * /usr/local/bin/sonar-backup.sh >> /var/log/sonar-backup.log 2>&1
Если не хочется писать и поддерживать свой скрипт с нуля, можно взять за основу готовый подход из статьи про установку BorgBackup на VPS — дедупликация особенно заметна на дампах БД, которые день ото дня меняются несильно, а полный архив каждый раз занимал бы куда больше места.
Восстановление из бэкапа: пошагово
Порядок действий одинаков что при переезде на новый сервер, что при откате после сбоя:
- Остановите SonarQube, оставив PostgreSQL доступным для восстановления:
docker compose stop sonarqube
- Восстановите базу. Если восстанавливаете в новую пустую БД:
docker exec -i sonarqube-db pg_restore -U sonar -d sonar --clean --if-exists \
< sonar_db_2026-08-20.dump
Флаги --clean --if-exists дропают существующие объекты перед восстановлением, поэтому команда безопасна и для повторного прогона, и для случая, когда в целевой БД уже есть старые данные, которые нужно перезаписать.
- Восстановите плагины и конфиг:
docker run --rm -v sonarqube_extensions:/data -v "$(pwd)":/backup \
alpine sh -c "rm -rf /data/* && tar xzf /backup/sonar_extensions_2026-08-20.tar.gz -C /data"
- Удалите старый поисковый индекс, если он остался от предыдущей установки и не соответствует восстановленной БД:
docker run --rm -v sonarqube_data:/data alpine sh -c "rm -rf /data/es*"
Это обязательный шаг: несовпадение индекса и БД приводит к тому, что в UI показываются не те issues или проекты выглядят пустыми, хотя данные в базе на месте.
- Запустите SonarQube и следите за логами:
docker compose up -d sonarqube
docker compose logs -f sonarqube
Дождитесь строки SonarQube is operational — до неё идёт пересборка индекса, и на инсталляции с несколькими тысячами issues это может занять от пары минут до получаса; точное время зависит от объёма данных и ресурсов сервера, ориентируйтесь по факту, а не по чужим цифрам.
- Проверьте UI: зайдите под своей учёткой, откройте один-два проекта, убедитесь что quality gate и история измерений на месте.
Проверка бэкапов и типичные ошибки
Бэкап, который ни разу не разворачивали, — это файл, а не бэкап. Раз в квартал стоит разворачивать дамп на тестовом сервере с нуля и проверять, что SonarQube реально стартует и показывает данные; подробный разбор этой практики — в статье про восстановление базы данных из бэкапа.
Частые причины, почему восстановление идёт не по плану:
- Версия
pg_dumpновее версии сервера PostgreSQL.pg_dumpиз более новой версии клиента иногда пишет формат, который старыйpg_restoreне понимает. Держите версии клиента и сервера согласованными или снимайте дамп прямо внутри контейнера с той же версией PostgreSQL, что и сама база. - Восстановление дампа в SonarQube другой мажорной версии. SonarQube умеет мигрировать схему БД только вперёд, при первом старте после восстановления. Откатить дамп из новой версии в старую установку не получится — придётся сначала обновить SonarQube до нужной версии.
- Права на файлы после распаковки архива в volume. Образ SonarQube в Docker работает от непривилегированного пользователя (обычно uid 1000), а
tarвнутри служебного alpine-контейнера пишет от root. Если после восстановления SonarQube не может стартовать с ошибками доступа кextensions/plugins, поправьте владельца:
docker run --rm -v sonarqube_extensions:/data alpine chown -R 1000:1000 /data
- Активные соединения блокируют
pg_restore --clean. Перед восстановлением остановите не только SonarQube, но и всё, что может держать открытые коннекты к базе (например, отдельный сервис для отчётов), иначеDROPвнутри восстановления зависнет. - Бэкап без плагинов = проект без части quality profiles. Если в команде используются кастомные правила или плагины под конкретный язык, а в бэкап попала только БД — после восстановления SonarQube поднимется, но ссылки на правила из недостающих плагинов будут битыми. Проще держать список установленных плагинов в git рядом с docker-compose.yml, чем восстанавливать его по памяти.
Если SonarQube и CI-раннер живут на одном сервере, полезно заранее прикинуть ресурсы под оба процесса сразу — тема разобрана в статье про сервер для разработчика и CI/CD, а интеграцию самого анализа с пайплайном удобнее смотреть в связке с настройкой GitLab CI/CD на VPS.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Нужно ли включать в бэкап данные Elasticsearch (data/es*)?
Нет. Это производный поисковый индекс, SonarQube пересобирает его из PostgreSQL автоматически при старте, если файлов индекса нет или они не совпадают с БД. Экономит место и время на бэкап.
Как часто делать бэкап SonarQube?
Для большинства команд достаточно раз в сутки, в окно низкой нагрузки. Если через SonarQube ежедневно прогоняются десятки веток и потеря дня истории критична, снимайте дамп чаще — раз в 6–12 часов.
Можно ли бэкапить без остановки сервера?
Дамп PostgreSQL — можно, pg_dump берёт консистентный снапшот на лету. Том с плагинами лучше архивировать либо когда SonarQube остановлен, либо хотя бы не во время установки/обновления плагинов через UI.
После восстановления SonarQube показывает пустые проекты — что не так?
Почти всегда это рассинхронизация индекса и БД. Удалите каталог индекса (data/es*) и перезапустите сервис — SonarQube пересоберёт индекс из восстановленной базы с нуля.
Можно ли восстановить дамп с более новой версии SonarQube на более старую установку?
Нет, схема БД мигрирует только вперёд. Сначала обновите SonarQube до версии, из которой сделан дамп (или новее), затем восстанавливайте.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →