Прокси в npm: proxy и https-proxy, приоритет .npmrc и ошибки установки

Как настроить прокси в npm: proxy и https-proxy, конфликты .npmrc и окружения, проверка скачивания пакета, исправление маршрута и TLS без отключения проверки.

На этой странице

Когда 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.

Начните в проекте, где возникает ошибка:

sh
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 шлюза определяет протокол соединения с самим шлюзом. Не вписывайте настоящие секреты литералами в команды, которые попадут в историю оболочки, и не оставляйте их в общих логах. Подстановка из переменной окружения не прячет раскрытый аргумент: его можно увидеть в локальном списке процессов.

Запустите все три проверки в одном новом каталоге вне существующих проектов. Реестр, утверждённый конфиг и прокси оставьте одними и теми же, а кеш для каждой проверки указывайте новый:

sh
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=10000

ping опрашивает реестр; view читает метаданные, включая URL архива. Ни одна из этих команд не скачивает и не проверяет архив пакета. npm ping, npm view.

Для третьей проверки оставайтесь в том же диагностическом каталоге и используйте те же входные значения:

sh
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-реестра. Если нужен один шлюз, проверьте оба ключа и задайте им одно значение. Код запросов к реестру в зафиксированной версии.

Когда временная проверка сработала, сохраните в нужный файл значения без учётных данных; в примере они условные:

sh
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 поверх проекта BA; содержимое провереноПроверьте переменные конфигурации в окружении процесса
Команда задаёт B для обоих ключей поверх окружения с AB; содержимое провереноСравнивайте одинаковые ключи на одном уровне
Только обычная HTTP_PROXY=A, показаны значения nullA; содержимое провереноВывод npm config не полностью отражает маршрут
Обычная NO_PROXY=127.0.0.1 плюс пользовательский прокси A, noproxy показан пустымНапрямую; содержимое провереноОбычная переменная обхода может продолжать действовать
B пропускает ping и метаданные, но отклоняет архивping и view проходят; install падает с E502, пакета нетПроверяйте запрос архива отдельно
Пользовательский https-proxy=A, в проекте и в команде proxy=BA; содержимое провереноПриоритет команды для одного ключа не отменяет другой

В восьми установках содержимое пакета совпало с ожидаемым. Девятая была намеренным сбоем, и пакет не установился; все девять случаев соответствовали своим критериям приёмки. Запасной путь через обычные переменные окружения реализован в HTTP-агенте npm той версии, что мы тестировали. Наблюдение про обход касается только точного совпадения с IPv4-адресом loopback; на подстановочные знаки, CIDR и другие клиенты оно не распространяется. Агент npm в зафиксированной версии.

Как убрать прокси в npm: удаляйте из нужного файла

Проверьте .npmrc проекта, а также пути к пользовательскому и глобальному конфигу, которые npm вывел выше. Если нужно удалить пользовательские настройки из примера:

sh
npm config delete proxy https-proxy --location=user

Запись в проекте при этом всё ещё может взять верх. Настройки проекта удаляйте, только если действительно этого хотите, и запускайте команду из каталога проекта:

sh
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):

sh
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/ГБ: посмотрите цены.

Источники и дополнительное чтение

Технические материалы, использованные при подготовке руководства. Сверяйтесь с документацией вашей версии и с поддерживаемой конфигурацией вашего провайдера.