Когда npm ходит в реестр через прокси, проверьте оба ключа — proxy и https-proxy, выберите один утверждённый шлюз и убедитесь, что скачивается сам пакет, а не только отвечает реестр. Успешный npm ping ещё не доказывает, что установка сработает. На нашем стенде ping и метаданные пакета проходили, а запрос архива пакета (tarball) падал.
Наблюдения в этом руководстве сделаны на npm 11.19.1, Node 26.10.0 и macOS 15.7.4 и записаны 12 октября 2026 года. Девять случаев маршрутизации и четыре проверки редактирования конфигурации соответствовали заявленным критериям приёмки. Стенды используют HTTP-реестр и пересылающие прокси на loopback; HTTPS, сертификаты, аутентификацию на прокси и коммерческие сервисы они не проверяют.
Если npm install undici проходит, а ваш код на Node.js 26 потом падает с invalid onError method, дело в несовпадении версий undici, а не в настройках npm: см. fetch failed: invalid onError method в Node.js 26.
Не путайте шлюз с реестром
registry указывает сервис, который отдаёт метаданные пакетов. proxy и https-proxy задают сетевой шлюз, через который npm до этого сервиса добирается. «npm proxy repository» в Nexus — это менеджер репозиториев с кешем, доступный клиентам как реестр npm; это другой слой, не прямой (forward) HTTP-прокси. Задавайте URL реестра вашей организации и шлюз как отдельные параметры. Настройка npm в Sonatype, конфигурация npm.
Начните в проекте, где возникает ошибка:
node --version
npm --version
npm config get registry
npm config get proxy https-proxy noproxy
npm config get userconfig globalconfigСмотрите этот вывод только у себя: в URL прокси могут быть учётные данные. URL реестра ничего не говорит о сетевом маршруте. Значения null у прокси — тоже: на стенде с одной лишь обычной переменной HTTP_PROXY npm всё равно шёл через прокси, хотя для обоих ключей показывал null.
Проверьте npm через прокси: реестр, метаданные и архив
Посмотрев конфигурацию проблемного проекта, задайте явно четыре значения: NPM_PROXY_URL и NPM_REGISTRY_URL — утверждённые шлюз и реестр, NPM_PACKAGE — пакет без scope, закреплённый как NAME@VERSION, и NPM_USERCONFIG — абсолютный путь к утверждённому npmrc. Путь userconfig из вывода выше — отправная точка; убедитесь, что в выбранном файле есть всё нужное для аутентификации в реестре. Копировать токены в диагностический каталог не нужно.
Для приватного или scoped-пакета в утверждённой конфигурации должны остаться нужный реестр и привязанная к нему аутентификация. Запись @scope:registry — отдельная настройка: не рассчитывайте, что основной --registry её перекроет. Проверьте URL архива в метаданных и реестр, к которому npm обратился на самом деле. В базовых командах ниже взят пакет без scope, чтобы проверить только шлюз. scope и аутентификация в npmrc.
Для HTTPS-реестра можно использовать HTTP-шлюз: схема в URL шлюза определяет протокол соединения с самим шлюзом. Не вписывайте настоящие секреты литералами в команды, которые попадут в историю оболочки, и не оставляйте их в общих логах. Подстановка из переменной окружения не прячет раскрытый аргумент: его можно увидеть в локальном списке процессов.
Запустите все три проверки в одном новом каталоге вне существующих проектов. Реестр, утверждённый конфиг и прокси оставьте одними и теми же, а кеш для каждой проверки указывайте новый:
npm_proxy_check_dir="$(mktemp -d)"
cd "$npm_proxy_check_dir" || exit 1
npm ping --proxy="$NPM_PROXY_URL" --https-proxy="$NPM_PROXY_URL" \
--registry="$NPM_REGISTRY_URL" --userconfig="$NPM_USERCONFIG" \
--cache="$npm_proxy_check_dir/cache-ping" \
--fetch-retries=0 --fetch-timeout=10000
npm view "$NPM_PACKAGE" version dist.tarball --json \
--proxy="$NPM_PROXY_URL" --https-proxy="$NPM_PROXY_URL" \
--registry="$NPM_REGISTRY_URL" --userconfig="$NPM_USERCONFIG" \
--cache="$npm_proxy_check_dir/cache-view" \
--fetch-retries=0 --fetch-timeout=10000ping опрашивает реестр; view читает метаданные, включая URL архива. Ни одна из этих команд не скачивает и не проверяет архив пакета. npm ping, npm view.
Для третьей проверки оставайтесь в том же диагностическом каталоге и используйте те же входные значения:
npm install "$NPM_PACKAGE" --ignore-scripts --no-audit --no-fund \
--no-package-lock --save=false \
--proxy="$NPM_PROXY_URL" --https-proxy="$NPM_PROXY_URL" \
--registry="$NPM_REGISTRY_URL" --userconfig="$NPM_USERCONFIG" \
--cache="$npm_proxy_check_dir/cache-install" \
--fetch-retries=0 --fetch-timeout=10000Проверьте, что у установленного пакета ожидаемые имя, версия и содержимое. Наш стенд сверяет точные файлы пакета, а не довольствуется ответом HTTP 200 или успешными метаданными. Новый кеш установки не даёт архиву, закешированному раньше, незаметно пройти эту проверку. Если доступны логи запросов шлюза, сверьтесь и с ними: корректный пакет сам по себе не доказывает, каким маршрутом он пришёл. Сохраните диагностический вывод для разбора, а временный каталог по окончании удалите.
В этой установке install-скрипты пакетов отключены. Она проверяет получение пакета из реестра, а не все зависимости и не полную установку проекта. fetch-timeout и отключённые повторы ограничивают отдельные запросы, но не задают десятисекундный лимит на всю установку. npm install, параметры загрузки в npm.
Конфликты настроек: что проверить до npm config set proxy
Для одного и того же ключа документированный приоритет в npm такой: параметры командной строки, затем переменные окружения npm_config_*, затем конфиг проекта, пользовательский и глобальный. .npmrc проекта может и дальше перекрывать новую пользовательскую настройку. В режиме глобальной установки конфиг проекта не читается. Иерархия конфигурации npm в зафиксированной версии, файлы npmrc.
Конфликты между разными ключами эта иерархия не решает. В нашем тесте на npm 11.19.1 пользовательский https-proxy=A оставался в силе, несмотря на --proxy=B в команде. Когда npm собрал итоговую конфигурацию, в ней остались оба значения, а код запросов к реестру выбрал httpsProxy || proxy — даже для нашего HTTP-реестра. Если нужен один шлюз, проверьте оба ключа и задайте им одно значение. Код запросов к реестру в зафиксированной версии.
Когда временная проверка сработала, сохраните в нужный файл значения без учётных данных; в примере они условные:
npm config set proxy=http://proxy.example:8080 \
https-proxy=http://proxy.example:8080 --location=userЕсли нужен уровень проекта, запустите команду с --location=project в каталоге этого проекта. Не храните учётные данные в .npmrc, который попадает в коммиты. npmrc поддерживает подстановку переменных окружения в значения, но при просмотре конфигурации может показываться уже раскрытое значение. У токенов реестра к тому же своя привязка к реестру, и учётными данными прокси они не являются. Аутентификация и подстановки в npmrc.
Что показал наш стенд маршрутизации
Стенд маршрутизации поднимает фиктивный реестр и прокси A и B, отдаёт настоящий сгенерированный архив пакета и записывает каждый реальный запрос. В результатах есть точные аргументы команд, конфигурация и итог проверки содержимого.
| Заданный конфликт | Маршрут / результат | Что это даёт для диагностики |
|---|---|---|
| Нет ни настроек прокси, ни переменных прокси в окружении | Напрямую; содержимое проверено | Базовый случай |
| Пользовательский npmrc задаёт A для обоих ключей | A; содержимое проверено | На этом стенде пользовательский конфиг работает |
| Проект B поверх пользовательского A, оба ключа | B; содержимое проверено | Проверьте файл проекта |
npm_config_proxy и npm_config_https_proxy со значением A поверх проекта B | A; содержимое проверено | Проверьте переменные конфигурации в окружении процесса |
| Команда задаёт B для обоих ключей поверх окружения с A | B; содержимое проверено | Сравнивайте одинаковые ключи на одном уровне |
Только обычная HTTP_PROXY=A, показаны значения null | A; содержимое проверено | Вывод npm config не полностью отражает маршрут |
Обычная NO_PROXY=127.0.0.1 плюс пользовательский прокси A, noproxy показан пустым | Напрямую; содержимое проверено | Обычная переменная обхода может продолжать действовать |
| B пропускает ping и метаданные, но отклоняет архив | ping и view проходят; install падает с E502, пакета нет | Проверяйте запрос архива отдельно |
Пользовательский https-proxy=A, в проекте и в команде proxy=B | A; содержимое проверено | Приоритет команды для одного ключа не отменяет другой |
В восьми установках содержимое пакета совпало с ожидаемым. Девятая была намеренным сбоем, и пакет не установился; все девять случаев соответствовали своим критериям приёмки. Запасной путь через обычные переменные окружения реализован в HTTP-агенте npm той версии, что мы тестировали. Наблюдение про обход касается только точного совпадения с IPv4-адресом loopback; на подстановочные знаки, CIDR и другие клиенты оно не распространяется. Агент npm в зафиксированной версии.
Как убрать прокси в npm: удаляйте из нужного файла
Проверьте .npmrc проекта, а также пути к пользовательскому и глобальному конфигу, которые npm вывел выше. Если нужно удалить пользовательские настройки из примера:
npm config delete proxy https-proxy --location=userЗапись в проекте при этом всё ещё может взять верх. Настройки проекта удаляйте, только если действительно этого хотите, и запускайте команду из каталога проекта:
npm config delete proxy https-proxy --location=projectНаши четыре отдельные проверки редактирования конфигурации показывают: удаление пользовательских ключей не затронуло значения проекта, а последующее удаление ключей проекта убрало действующую пару в этой изолированной конфигурации. В документации npm сказано, что удаление убирает ключи из всех файлов, но код зафиксированной версии npm 11.19.1 удаляет их только из выбранного расположения — так вышло и в нашем эксперименте. Указывайте уровень явно и проверяйте результат. Реализация удаления в зафиксированной версии, документация npm config.
Проверьте также npm_config_proxy, npm_config_https_proxy, HTTP_PROXY, HTTPS_PROXY и переменные обхода в окружении того процесса, который на самом деле запускается. Удаление записей из файлов не удаляет значения из окружения. Руководство по переменным окружения объясняет, как разные клиенты по-разному обрабатывают унаследованные настройки.
Разберите оставшиеся ошибки
| На каком этапе сбой | Что проверить дальше |
|---|---|
| Нет соединения со шлюзом | Хост и порт, выбранный конфиг и настройки обхода в процессе |
| Реестр доступен, архив не скачивается | Хост и путь в dist.tarball, политика шлюза и запрос архива; учитывайте кеш |
| 407 от прокси | Аутентификация на шлюзе; см. руководство по 407 |
| Ошибка аутентификации в реестре | Токен, реестр и scope; не смешивайте это с учётными данными шлюза |
| Ошибка проверки сертификата | Доверие к утверждённому CA и имя хоста для того соединения, которое на самом деле падает |
| Не скачивается Git-зависимость или падает загрузка в install-скрипте | Для загрузок Git по HTTP(S) см. настройку прокси в Git; клиент каждого install-скрипта проверяйте отдельно. Настройки реестра npm эти маршруты не задают |
Чтобы npm доверял корпоративному CA, в документации описаны cafile и strict-ssl. Утверждённый набор CA получите у администратора и оставьте strict-ssl включённым. HTTP-стенды не проверяют ни одно исправление для HTTPS или корпоративного CA. Настройка сертификатов в npm.
Как повторить оба эксперимента
Скачайте оба скрипта и README в один каталог и запустите (нужны установленные Node и npm):
node npm-proxy-lab.mjs ./local-results.json
node npm-config-edit-check.mjs ./local-config-results.jsonСкрипт проверки конфигурации и его результаты дополняют данные о маршрутизации. Скрипты используют явно заданные временные пути к пользовательскому и глобальному конфигу и временные кеши, не трогают вашу пользовательскую конфигурацию и не выходят в сеть за пределы loopback. Прогон шёл на npm 11.19.1 / Node 26.10.0; актуальная документация v11 показывает более новую версию, поэтому запустите стенд заново, прежде чем переносить выводы на другой выпуск. Дополнительные npm-пакеты для запуска этих стендов не нужны. HTTPS/CONNECT, учётные данные прокси, аутентификация в приватном реестре, Git-зависимости, существующие lock-файлы и загрузки в lifecycle-скриптах в эксперимент не входят.
ipvolt продаёт мобильные прокси и резидентные прокси от $0.60/ГБ: посмотрите цены.
Источники и дополнительное чтение
Технические материалы, использованные при подготовке руководства. Сверяйтесь с документацией вашей версии и с поддерживаемой конфигурацией вашего провайдера.