MAATRIX / Блог / Бэкап и восстановление Jenkins

Бэкап и восстановление Jenkins

MAATRIX

Jenkins годами копит конфигурацию: сотни job'ов, credentials, плагины, историю сборок — и всё это живёт в одной папке на диске сервера. Пока сервер жив, об этом не думаешь. А когда диск сыпется или кто-то случайно снёс контейнер, выясняется, что бэкапа либо нет, либо он бесполезен, потому что не включает secrets и credentials.xml теряют смысл без ключей шифрования. Разберём, что реально нужно бэкапить, как автоматизировать процесс и как поднять Jenkins на новом сервере за 20 минут, а не за два дня ручного восстановления job'ов.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что на самом деле лежит в JENKINS_HOME

Весь Jenkins — это одна директория, обычно /var/lib/jenkins (пакетная установка) или volume jenkins_home в Docker-контейнере. Важно понимать, что внутри неравноценно по значимости:

  • config.xml — глобальные настройки инстанса
  • jobs/*/config.xml — конфигурация каждого job'а (пайплайны, триггеры, параметры)
  • jobs/*/builds/ — история сборок, логи, артефакты — самое тяжёлое и наименее критичное
  • credentials.xml — зашифрованные учётки (SSH-ключи, токены, пароли)
  • secrets/master.key и secrets/hudson.util.Secret — ключи, которыми зашифрован credentials.xml
  • plugins/*.hpi / *.jpi — установленные плагины
  • nodes/ — конфигурация агентов сборки
  • users/ — локальные учётки, если не используется внешний SSO

Ключевой момент, который упускают чаще всего: secrets/master.key и secrets/hudson.util.Secret обязаны переезжать вместе с credentials.xml. Без них Jenkins на новом сервере поднимется, увидит credentials.xml, но расшифровать пароли и токены не сможет — придётся вбивать всё заново руками. Это не баг, а осознанное поведение: Jenkins не хранит секреты в открытом виде даже в бэкапе.

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

sudo du -sh /var/lib/jenkins/*

Обычно 80-95% объёма — это jobs/*/builds/, то есть логи и артефакты прошлых сборок. Для дисциплинированного бэкапа их стоит либо исключать, либо ограничивать retention отдельно (Discard Old Builds в настройках job'а или через политику storage).

Ручной бэкап: tar с исключениями

Самый надёжный способ — простой архив, без магии плагинов. Перед архивацией Jenkins лучше остановить или хотя бы перевести в quiet-режим, чтобы не поймать сборку в момент записи конфигов:

# graceful — дождаться завершения текущих job'ов
curl -X POST http://localhost:8080/quietDown --user admin:TOKEN

sudo systemctl stop jenkins

tar czf /backup/jenkins-$(date +%F).tar.gz \
  --exclude='workspace' \
  --exclude='*/builds/*/archive' \
  --exclude='caches' \
  --exclude='*.log' \
  -C /var/lib/jenkins .

sudo systemctl start jenkins

--exclude='workspace' убирает рабочие копии кода — их Jenkins восстановит сам при следующей сборке. caches — это кэши Maven/Gradle/npm внутри Jenkins, тоже не критично для бэкапа конфигурации, хотя их потеря замедлит первую сборку после восстановления.

Если Jenkins в Docker (что на VPS чаще всего и есть), архивировать нужно volume, а не файлы контейнера:

docker run --rm \
  -v jenkins_home:/data \
  -v /backup:/backup \
  alpine tar czf /backup/jenkins-$(date +%F).tar.gz -C /data \
  --exclude='workspace' --exclude='caches' .

Контейнер при этом можно не останавливать — tar через отдельный alpine-контейнер читает volume напрямую, без блокировки процесса Jenkins. Риск в том, что при активной записи в момент снятия архива можно поймать файл в промежуточном состоянии — для конфигов это почти никогда не критично, но для полной консистентности лучше на секунду поставить job'ы на паузу через quietDown.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

ThinBackup: плагин для регулярных снапшотов

Ручной tar хорош для разовой миграции, но для регулярного бэкапа удобнее плагин ThinBackup — он умеет делать инкрементальные снапшоты прямо из веб-интерфейса и по расписанию, без внешнего cron.

Установка: *Manage Jenkins → Plugins → Available* → найти thinBackup → установить, перезапустить Jenkins.

Настройка: *Manage Jenkins → ThinBackup → Settings*:

ПараметрЗначениеСмысл
Backup directory/var/backups/jenkins-thinКуда складывать снапшоты (вне JENKINS_HOME)
Full backup schedule0 2 * * 0Полный бэкап раз в неделю, ночью
Diff backup schedule0 3 * * 1-6Инкрементальный бэкап в остальные дни
Max number of backup sets8Сколько полных циклов хранить
Clean up diff backupsвключеноНе копить дифы бесконечно
Backup build resultsвыключеноЛоги сборок не бэкапим — они самые тяжёлые
Backup user contentsвключеноЛичные настройки пользователей

ThinBackup по умолчанию включает secrets/ в бэкап — это правильно, но именно поэтому папка с бэкапами должна иметь ограниченные права доступа (chmod 700) и не должна лежать в публично доступном месте на диске.

Ограничение ThinBackup: он не умеет сам заливать архивы во внешнее хранилище — это по-прежнему задача cron + rclone/rsync, о которой ниже. Плагин решает только «как красиво и регулярно снять снапшот», а не «куда его унести с этого сервера».

Автоматизация и офсайт-копия

Бэкап, который лежит на том же диске, что и сам Jenkins, бесполезен при отказе диска или компрометации сервера. Минимальная схема — cron-скрипт, который снимает архив и сразу же уносит его на другую машину или в S3-совместимое хранилище.

#!/bin/bash
# /usr/local/bin/jenkins-backup.sh
set -euo pipefail

DEST=/backup
DATE=$(date +%F)
FILE="jenkins-${DATE}.tar.gz"

curl -sf -X POST http://localhost:8080/quietDown --user "admin:${JENKINS_TOKEN}"
sleep 5

tar czf "${DEST}/${FILE}" \
  --exclude='workspace' --exclude='caches' \
  -C /var/lib/jenkins .

curl -sf -X POST http://localhost:8080/cancelQuietDown --user "admin:${JENKINS_TOKEN}"

# унести на другой сервер или в S3/MinIO
rclone copy "${DEST}/${FILE}" remote:jenkins-backups/

# оставить только последние 14 локальных архивов
find "${DEST}" -name 'jenkins-*.tar.gz' -mtime +14 -delete
0 3 * * * /usr/local/bin/jenkins-backup.sh >> /var/log/jenkins-backup.log 2>&1

Если под офсайт-хранилище удобнее свой S3-совместимый сервер, а не облако третьей стороны — это отдельный VPS с MinIO, настройка описана в статье про бэкап и восстановление MinIO. Для самой заливки через rclone конфигурация remote — тот же принцип, что для любого S3 endpoint.

Отдельно стоит настроить мониторинг, что бэкап-скрипт реально отработал, а не молча упал третью неделю подряд — например через healthchecks.io с пингом в конце скрипта (curl -fsS https://hc-ping.com/<uuid> > /dev/null).

Восстановление на новом сервере

Здесь и проверяется, был ли бэкап настоящим или «для галочки». Порядок действий:

  1. Поднять чистый Jenkins той же мажорной версии (расхождение LTS-версий иногда ломает формат конфигов плагинов):
sudo apt update
sudo apt install -y fontconfig openjdk-17-jre jenkins
sudo systemctl stop jenkins
  1. Полностью очистить свежесозданный JENKINS_HOME и развернуть архив на его место:
sudo rm -rf /var/lib/jenkins/*
sudo tar xzf jenkins-2026-08-24.tar.gz -C /var/lib/jenkins
sudo chown -R jenkins:jenkins /var/lib/jenkins
  1. Запустить и проверить логи на предмет проблем с плагинами:
sudo systemctl start jenkins
sudo journalctl -u jenkins -f
  1. Зайти в веб-интерфейс, убедиться, что job'ы на месте, credentials расшифровались (значит secrets/ перенесены верно), агенты (nodes) переподключились.

Частая ошибка на этом шаге — версия Java на новом сервере не совпадает с той, под которую собраны плагины. Jenkins LTS с 2025 года требует Java 17 или новее; если ставили сервер «с нуля» по старому мануалу, проверьте версию заранее: java -version.

Если новый сервер стоит в другом регионе или у другого провайдера, а старый Jenkins ещё жив — проще временно запустить оба и переключить DNS/reverse-proxy на новый только после того, как убедились, что все job'ы отрабатывают. Для CI/CD-раннеров это особенно важно: агенты, зарегистрированные на старый URL, нужно переподключить к новому вручную через *Manage Nodes*.

Что делать с credentials, если secrets/ потеряны

Иногда бэкап неполный: конфиги job'ов есть, а secrets/master.key — нет (например, если кто-то бэкапил только jobs/, не понимая структуру JENKINS_HOME). В этом случае credentials.xml восстановить нельзя — Jenkins покажет ошибку Failed to load для этого раздела или просто создаст его заново пустым.

Единственный рабочий путь в такой ситуации:

  • Удалить нерасшифровываемый credentials.xml (Jenkins создаст новый, пустой)
  • Пересоздать все credentials вручную через *Manage Jenkins → Credentials* — SSH-ключи, токены Git-провайдеров, пароли Docker-registry
  • Пройтись по job'ам и пересвязать credentials ID, если старые ID использовались напрямую в Jenkinsfile (credentialsId: 'old-id') — новые credentials лучше создавать с теми же ID, тогда Jenkinsfile трогать не придётся

Это ровно тот сценарий, который дороже всего по времени и ради которого стоит один раз настроить автоматический бэкап с офсайт-копией, а не полагаться на «снимем вручную перед большим обновлением». Для самого Jenkins-сервера как раздела инфраструктуры полезно ещё посмотреть на общий подход к настройке VPS под разработчика и CI/CD — там же логика ресурсов, которая пригодится, если Jenkins делит сервер с GitLab Runner или приватным Docker-registry.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

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

Нужно ли останавливать Jenkins на время бэкапа?

Для полной консистентности — да, systemctl stop jenkins на пару минут безопаснее всего. Если простой недопустим, используйте quietDown (новые сборки не стартуют, текущие доигрывают) или бэкапьте Docker volume отдельным контейнером — это не блокирует запись, но при очень активной записи конфигов теоретически можно поймать неполный файл.

Можно ли бэкапить только jobs/, без всей JENKINS_HOME?

Можно, но тогда потеряются плагины, глобальные настройки и, главное, secrets/ — без них credentials.xml бесполезен. Минимум для полноценного восстановления: jobs/*/config.xml, credentials.xml, secrets/, config.xml, список плагинов.

Сколько места нужно под бэкапы Jenkins?

Зависит от истории сборок — если исключить builds/ и workspace, конфигурация обычно занимает 50-500 МБ даже при сотнях job'ов. С логами сборок счёт может пойти на десятки гигабайт, поэтому их либо не бэкапят вовсе, либо ограничивают retention.

ThinBackup или обычный tar + cron — что лучше?

ThinBackup удобнее для быстрого «снял снапшот из интерфейса» и инкрементальных бэкапов без внешних скриптов. Tar + cron + rclone гибче: проще интегрировать с офсайт-хранилищем и мониторингом. На практике многие используют оба — ThinBackup для быстрого отката локально, внешний скрипт для настоящей офсайт-копии.

Что делать, если версия Jenkins на новом сервере новее, чем была в бэкапе?

Обычно апгрейд конфигов проходит автоматически при первом старте — Jenkins мигрирует формат. Но безопаснее сначала поднять ту же версию, что была, дать плагинам обновиться штатно через интерфейс, и только потом обновлять сам Jenkins.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →