Renovate на сервере: частые ошибки и решения
Renovate обещает простую вещь: зависимости проекта обновляются сами, вы только мержите pull request-ы. На практикеself-hosted Renovate на своём сервере регулярно упирается в лимиты API, зависает на onboarding-PR, путается в приватных registry или молча перестаёт создавать PR вообще. Разберём десяток конкретных ошибок, с которыми сталкиваешься при запуске Renovate на VPS, и как их закрыть без танцев с бубном.
Содержание
- Почему self-hosted Renovate, а не GitHub App
- Ошибка: PR не создаются, хотя логи говорят "processed"
- Ошибка: превышен rate limit GitHub/GitLab API
- Ошибка: Renovate не видит приватный npm/Docker registry
- Ошибка: PR зависают в конфликте или не проходят CI
- Ошибка: Renovate падает или зависает на большом монорепо
- Ошибка: расписание Renovate не срабатывает вовремя (или срабатывает слишком часто)
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество 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 не появляется. Причины почти всегда одни и те же:
- Нет
onboardingPR, а конфиг не подтверждён. 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 в логах и обрыв обработки на середине списка репозиториев.
Решения:
- Использовать GraphQL API там, где возможно — Renovate по умолчанию уже старается это делать, но убедитесь, что
platformнастроен правильно. - Развести токены. Если один бот-аккаунт обслуживает 50+ репозиториев, создайте отдельный GitHub App вместо personal access token — у GitHub App лимит считается отдельно и обычно выше.
- Ограничить частоту прогонов. Не гоняйте Renovate каждые 15 минут cron-ом на все репозитории разом — используйте
scheduleв конфиге, чтобы разнести проверки по времени:
{
"schedule": ["after 2am and before 5am every weekday"],
"timezone": "Europe/Moscow"
}
- Кэшировать между запусками. Флаг
--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 минут.
Что помогает:
- Увеличить память Node.js. По умолчанию Renovate может упереться в лимит heap на больших монорепо:
NODE_OPTIONS="--max-old-space-size=4096" renovate ...
Если запускаете в Docker — убедитесь, что у контейнера действительно есть эта память, а не только у процесса внутри (docker run --memory=4g).
- Ограничить область сканирования.
ignorePathsисключает вложенныеnode_modules, тестовые фикстуры и примеры, которые Renovate иначе тоже пытается парсить:
{
"ignorePaths": [
"**/node_modules/**",
"**/test/fixtures/**",
"**/examples/**"
]
}
- Group-обновления по workspace. Вместо сотни отдельных PR на каждый пакет монорепо — сгруппировать через
groupNameиmatchFileNames, чтобы один PR обновлял связанные зависимости разом.
- Инкрементальный клон. Флаг
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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →