MAATRIX / Блог / Renovate на сервере: частые ошибки и решения

Renovate на сервере: частые ошибки и решения

MAATRIX

Renovate обещает простую вещь: зависимости проекта обновляются сами, вы только мержите pull request-ы. На практикеself-hosted Renovate на своём сервере регулярно упирается в лимиты API, зависает на onboarding-PR, путается в приватных registry или молча перестаёт создавать PR вообще. Разберём десяток конкретных ошибок, с которыми сталкиваешься при запуске Renovate на VPS, и как их закрыть без танцев с бубном.

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

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

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

Почему self-hosted Renovate, а не GitHub App

GitHub App-версия Renovate (Mend) бесплатна и работает из коробки, но у неё есть потолок: лимиты на количество репозиториев в бесплатном тарифе, задержки в очереди на общих раннерах, невозможность держать secrets и приватные registry внутри своей сети. Self-hosted Renovate на собственном сервере снимает эти ограничения — вы сами задаёте расписание, сами храните токены, сами решаете, сколько PR открывать одновременно.

Обратная сторона — вы теперь отвечаете за инфраструктуру: cron, логи, обновления самого Renovate, диск под кэш. Типичная связка — Docker-контейнер с renovate CLI, запускаемый по cron или как systemd timer, плюс отдельный GitLab/Gitea/Forgejo или self-hosted GitHub Enterprise, если репозитории не на публичном GitHub.

Минимальные требования для сервера под Renovate: 2 vCPU, 4 ГБ RAM хватает на несколько десятков репозиториев с умеренной активностью — если репозиториев сотни или в них большие lock-файлы (например, package-lock.json на тысячи строк), закладывайте больше RAM под Node.js процессы. Диск — от 20 ГБ, кэш renovate (клоны репозиториев, npm-кэш) быстро съедает место, если не чистить.

Ошибка: PR не создаются, хотя логи говорят "processed"

Самая частая жалоба — Renovate отрабатывает без ошибок, пишет в логе INFO: Repository started и INFO: Repository finished, но ни одного PR не появляется. Причины почти всегда одни и те же:

  • Нет onboarding PR, а конфиг не подтверждён. Renovate по умолчанию сначала открывает PR "Configure Renovate" и ждёт его мержа — обычные PR с обновлениями не создаются, пока onboarding не закрыт. Проверьте dependencyDashboard: true в конфиге — Dashboard-issue покажет реальную причину.
  • enabled: false где-то в цепочке конфигов. Renovate читает конфиг каскадно: global config → renovate.json в репозитории → пресеты. Если хоть один уровень выключает пакет через packageRules, PR не будет.
  • Rate limiting или prConcurrentLimit: 0. По умолчанию лимит на конкурентные PR — 10, но если кто-то в конфиге явно поставил 0, Renovate тихо ничего не создаёт.
  • Все обновления уже "ignored" через ignoreDeps или packageRules с enabled: false.

Быстрая диагностика — запустить с подробным логом:

LOG_LEVEL=debug renovate --platform=github --token=$RENOVATE_TOKEN my-org/my-repo 2>&1 | tee renovate-debug.log
grep -i "skipping\|disabled\|ignored" renovate-debug.log

Строки вида packageFiles with no updates или Skipping branch creation укажут точную причину для конкретного пакета.

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

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

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

Ошибка: превышен rate limit GitHub/GitLab API

При десятках репозиториев Renovate легко упирается в лимит API (для GitHub REST API это 5000 запросов в час на токен). Симптом — ошибки 403 rate limit exceeded в логах и обрыв обработки на середине списка репозиториев.

Решения:

  1. Использовать GraphQL API там, где возможно — Renovate по умолчанию уже старается это делать, но убедитесь, что platform настроен правильно.
  2. Развести токены. Если один бот-аккаунт обслуживает 50+ репозиториев, создайте отдельный GitHub App вместо personal access token — у GitHub App лимит считается отдельно и обычно выше.
  3. Ограничить частоту прогонов. Не гоняйте Renovate каждые 15 минут cron-ом на все репозитории разом — используйте schedule в конфиге, чтобы разнести проверки по времени:
{
  "schedule": ["after 2am and before 5am every weekday"],
  "timezone": "Europe/Moscow"
}
  1. Кэшировать между запусками. Флаг --repository-cache=enabled (или переменная RENOVATE_REPOSITORY_CACHE=enabled) сохраняет состояние репозитория между прогонами и резко снижает число запросов к API на повторных проходах.

Ошибка: Renovate не видит приватный npm/Docker registry

Если зависимости тянутся из приватного registry (Verdaccio, Nexus, GitLab Package Registry, приватный Docker Hub), Renovate по умолчанию не знает про эти источники и либо падает с 401, либо просто не находит новых версий.

Настройка через hostRules в config.js (глобальный конфиг self-hosted инстанса) или в renovate.json репозитория:

{
  "hostRules": [
    {
      "matchHost": "npm.internal.example.com",
      "hostType": "npm",
      "token": "{{ secrets.NPM_TOKEN }}"
    },
    {
      "matchHost": "registry.internal.example.com",
      "hostType": "docker",
      "username": "renovate",
      "password": "{{ secrets.DOCKER_PASSWORD }}"
    }
  ]
}

Ключевые грабли здесь:

  • Секреты нельзя хранить прямо в renovate.json репозитория — это публичный файл в git. Для self-hosted инстанса секреты задаются через переменные окружения контейнера, а в renovate.json только ссылка {{ secrets.NAME }}.
  • matchHost должен точно совпадать с хостом в lock-файле, включая порт, если он нестандартный.
  • Для scoped npm-пакетов (@myorg/pkg) дополнительно нужна секция packageRules с matchPackagePrefixes: ["@myorg/"], иначе Renovate может пытаться резолвить их через публичный registry.npmjs.org и падать с 404.

Если приватный registry работает через самоподписанный TLS-сертификат — добавьте NODE_EXTRA_CA_CERTS=/path/to/ca.crt в переменные окружения контейнера Renovate, иначе будет SELF_SIGNED_CERT_IN_CHAIN.

Ошибка: PR зависают в конфликте или не проходят CI

Renovate открывает PR корректно, но они годами висят "красными", потому что либо конфликтуют с main, либо валят CI. Здесь помогает не борьба с симптомом, а настройка поведения:

  • rebaseWhen: "conflicted" (значение по умолчанию в новых версиях) — Renovate ребейзит PR только при конфликте, экономя ресурсы CI. Если нужно жёстче — "behind-base-branch" перебазирует при каждом отставании от main.
  • automerge для мелких обновлений. Патч-версии и devDependencies — кандидаты на автомерж без участия человека:
{
  "packageRules": [
    {
      "matchUpdateTypes": ["patch", "pin", "digest"],
      "matchDepTypes": ["devDependencies"],
      "automerge": true
    }
  ]
}
  • minimumReleaseAge (раньше называлось stabilityDays) — не создавать PR на версию раньше, чем через N дней после релиза. Спасает от обновления на пакет, в котором на следующий день нашли критический баг:
{ "minimumReleaseAge": "3 days" }
  • Если CI сам по себе флаки — это не проблема Renovate, но она усугубляет её количеством PR. Ограничьте prConcurrentLimit: 5 и prHourlyLimit: 2, чтобы не заваливать очередь раннеров одновременно.

Если у вас self-hosted GitLab CI/CD раннер, который и без Renovate периодически подвисает или падает под нагрузкой — это отдельная тема, разобранная в статье про частые ошибки GitLab CI Runner.

Ошибка: Renovate падает или зависает на большом монорепо

На монорепозиториях с десятками package.json (Lerna, Nx, Turborepo, pnpm workspaces) Renovate иногда либо падает по OOM, либо обрабатывает репозиторий по 20-30 минут.

Что помогает:

  1. Увеличить память Node.js. По умолчанию Renovate может упереться в лимит heap на больших монорепо:
NODE_OPTIONS="--max-old-space-size=4096" renovate ...

Если запускаете в Docker — убедитесь, что у контейнера действительно есть эта память, а не только у процесса внутри (docker run --memory=4g).

  1. Ограничить область сканирования. ignorePaths исключает вложенные node_modules, тестовые фикстуры и примеры, которые Renovate иначе тоже пытается парсить:
{
  "ignorePaths": [
    "**/node_modules/**",
    "**/test/fixtures/**",
    "**/examples/**"
  ]
}
  1. Group-обновления по workspace. Вместо сотни отдельных PR на каждый пакет монорепо — сгруппировать через groupName и matchFileNames, чтобы один PR обновлял связанные зависимости разом.
  1. Инкрементальный клон. Флаг gitNoVerify и cloneSubmodules: false (если сабмодули не нужны для анализа зависимостей) ускоряют клонирование крупных репозиториев.

Если сервер регулярно упирается в память именно из-за таких batch-задач — возможно, дело не в конфигурации Renovate, а в том, что VPS изначально недосайзен под нагрузку CI/CD. Ориентир по ресурсам для такого профиля описан в статье сколько ресурсов нужно VPS для разработчика и CI/CD.

Ошибка: расписание Renovate не срабатывает вовремя (или срабатывает слишком часто)

Self-hosted Renovate обычно запускают через cron или systemd timer, и здесь легко ошибиться с таймзоной или синтаксисом.

Пример systemd timer, который многие делают неправильно (забывают Persistent=true, из-за чего пропущенный из-за перезагрузки сервера запуск просто теряется):

# /etc/systemd/system/renovate.timer
[Unit]
Description=Renovate scheduled run

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target
# /etc/systemd/system/renovate.service
[Unit]
Description=Renovate bot run

[Service]
Type=oneshot
EnvironmentFile=/etc/renovate/renovate.env
ExecStart=/usr/bin/docker run --rm \
  --env-file /etc/renovate/renovate.env \
  -v /var/cache/renovate:/tmp/renovate/cache \
  renovate/renovate:latest

Активация:

systemctl daemon-reload
systemctl enable --now renovate.timer
systemctl list-timers renovate.timer

Отдельно стоит развести два понятия расписания: когда запускается сам процесс Renovate (systemd timer/cron на сервере) и schedule внутри renovate.json (когда Renovate разрешено создавать/обновлять PR для конкретного репозитория). Если они не согласованы — например, cron гоняет Renovate каждый час, а в конфиге schedule разрешает работу только ночью — вы просто впустую тратите ресурсы на 23 холостых прогона в сутки, которые ничего не делают, кроме API-запросов на проверку.

Если базовые cron-задачи на сервере у вас и так периодически ведут себя странно (не тот часовой пояс, задвоенные запуски, тихие падения без уведомления) — это частая и решаемая проблема, разобранная в статье про частые ошибки cron-задач на сервере.

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

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

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

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

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

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

Renovate и Dependabot — в чём разница для self-hosted сценария?

Dependabot глубже интегрирован в GitHub и почти не настраивается для self-hosted запуска вне GitHub Actions. Renovate изначально проектировался как платформонезависимый инструмент — одинаково работает с GitHub, GitLab, Gitea, Forgejo, Bitbucket, и его self-hosted версия полноценна, а не урезана.

Нужен ли Renovate отдельный сервер или можно на том же, где крутится CI/CD?

Можно на том же — Renovate не требователен к ресурсам сама по себе, основную нагрузку создают git-клоны и парсинг lock-файлов. Если CI/CD и так нагружает сервер, лучше вынести Renovate в отдельный контейнер с лимитом памяти, чтобы он не конкурировал за ресурсы с самими сборками.

Как обновить сам Renovate, если он запускается через Docker?

Обычно тег latest в docker-образе уже означает автообновление при следующем docker pull — но для предсказуемости лучше пиновать конкретную мажорную версию (renovate/renovate:39) и обновлять её осознанно, проверяя changelog на breaking changes в самом Renovate.

Можно ли ограничить Renovate только определёнными типами обновлений (например, только security-патчи)?

Да, через vulnerabilityAlerts (использует данные о CVE из GitHub Advisory Database или OSV) в сочетании с packageRules, где matchUpdateTypes для всего остального выставлен на enabled: false. Это частый выбор для консервативных production-проектов.

Почему Renovate не подхватывает изменения в конфиге сразу после коммита?

Если используется repository-cache, изменения конфига обычно подхватываются сразу при следующем прогоне (Renovate читает renovate.json заново каждый раз), но кэш зависимостей и extends-пресетов может жить дольше — при отладке конфига временно отключайте кэш флагом --repository-cache=disabled или переменной RENOVATE_REPOSITORY_CACHE=disabled.

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

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

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