npm
NORA предоставляет полностью совместимый npm-реестр. Публикуйте приватные пакеты и прозрачно проксируйте публичные пакеты из официального реестра npm.
Настройка клиента
Заголовок раздела «Настройка клиента»Направьте npm (или yarn/pnpm) на NORA:
# npmnpm config set registry http://nora.example.com:4000/npm/
# yarnyarn config set registry http://nora.example.com:4000/npm/
# pnpmpnpm config set registry http://nora.example.com:4000/npm/Публикация пакета:
npm publish --registry http://nora.example.com:4000/npm/npm публикует только с токеном для реестра: при выключенной аутентификации подойдёт любое значение, при включённой — API-токен:
npm config set //nora.example.com:4000/npm/:_authToken=<token>Настройка .npmrc для конкретного проекта:
registry=http://nora.example.com:4000/npm/Проксирование upstream
Заголовок раздела «Проксирование upstream»Если пакет не найден локально, NORA загружает его из upstream-реестра. URL тарболов в метаданных перезаписываются для загрузки через NORA.
config.toml:
[npm]enabled = trueproxy = "https://registry.npmjs.org"proxy_timeout = 30metadata_ttl = 300 # секундыПеременные окружения:
| Переменная | Описание | По умолчанию |
|---|---|---|
NORA_NPM_ENABLED | Включить реестр npm | true |
NORA_NPM_PROXY | URL upstream-реестра | https://registry.npmjs.org |
NORA_NPM_PROXY_AUTH | Аутентификация upstream (user:pass) | — |
NORA_NPM_PROXY_TIMEOUT | Таймаут upstream в секундах | 30 |
NORA_NPM_METADATA_TTL | TTL кеша метаданных в секундах | 300 |
Опубликованные пакеты и upstream
Заголовок раздела «Опубликованные пакеты и upstream»С 1.4.0 пакет, опубликованный в NORA, владеет своим именем: его packument, манифесты версий и dist-tags (/<name>, /<name>/<version>, /<name>/<dist-tag>, -/package/<name>/dist-tags) отдаются из его ключей при любом metadata_ttl и никогда не обращаются к upstream. То, что upstream отдаёт для пакета, который в NORA не опубликован, кэшируется отдельно, в npm/<name>/upstream/. npm search и другие пути метаданных отвечает upstream, без кэша.
Несколько upstream по scope
Заголовок раздела «Несколько upstream по scope»Используйте proxies вместо proxy, если часть scope живёт в приватном реестре (GitLab, GitHub Packages, Verdaccio, реестр поставщика), а всё остальное берётся из публичного:
[npm]proxies = [ "https://registry.npmjs.org", { url = "https://npm.vendor.example", scopes = ["@vendor"], auth_bearer_env = "VENDOR_NPM_TOKEN" }, { url = "https://gitlab.example.com/api/v4/packages/npm", scopes = ["@team", "@infra"], auth = "deploy:secret" },]- Пакет из перечисленного scope (
@vendor/a) идёт только к записи, которой этот scope принадлежит: за метаданными, тарболами и при ревалидации. Если этот upstream недоступен, клиент получает502: другой upstream NORA не спрашивает. Так приватное имя не попадает в публичный реестр. - Все остальные пакеты идут к записи без
scopes. Такая запись может быть только одна. Если её нет, пакеты вне перечисленных scope отдаются только из локального хранилища. - У каждой записи свои учётные данные:
auth = "user:pass"(Basic) илиauth_bearer_env = "VAR"(Bearer-токен из этой переменной окружения, читается при старте; в конфиг и логи токен не попадает). Задаётся одно из двух. - Если задан
proxies, параметрыproxyиproxy_authне используются (наproxy_authпри старте будет предупреждение).
NORA не запускается (код выхода 78), если у записи URL без http:///https://, scope не вида @name, один scope принадлежит двум записям, заданы одновременно auth и auth_bearer_env или переменная из auth_bearer_env не задана либо содержит значение, недопустимое в HTTP-заголовке (например, с переводом строки в конце).
Происхождение кэша. Для каждого закэшированного объекта NORA записывает, какой upstream его отдал, и SHA-256 этих байтов. В scope с владельцем закэшированная копия отдаётся, только если её отдал владелец и байты не менялись, или если пакет опубликован в NORA. Копия, закэшированная раньше из другого upstream (например, публичный пакет с тем же именем, попавший в кэш до того, как у scope появилась своя запись), заново запрашивается у владельца и не отдаётся ни из кэша, ни как устаревшая копия. Записи хранятся в .nora-origins/ в корне хранилища; nora backup, nora restore и nora migrate их переносят, а nora gc удаляет записи, у которых нет объекта.
Своей базы уязвимостей у NORA нет. npm audit, yarn npm audit и pnpm audit пересылаются в upstream, который отдаёт пакеты без scope, и его ответ возвращается как есть.
Если у proxies есть scope с владельцами или в курации задано внутреннее пространство имён, NORA сначала удаляет эти имена из запроса. Это возможно только для формата npm 7+ (/-/npm/v1/security/advisories/bulk, обычный или gzip). Запрос, который проверить нельзя, отклоняется с кодом 4xx и JSON-полем error с причиной; ответа «уязвимостей нет» в этом случае не бывает:
| Запрос | Код |
|---|---|
npm 6 audits/quick или pnpm audits (всё дерево зависимостей) | 422 |
| Тело больше 8 МБ, сжатое или после распаковки | 413 |
| Кодирование, отличное от gzip | 415 |
| gzip, который не распаковывается, или тело не того JSON-формата | 422 |
Реестр без upstream для пакетов без scope отвечает на аудит 200 {}, и клиенты сообщают, что уязвимостей нет.
Возможности
Заголовок раздела «Возможности»| Функция | Статус | Примечание |
|---|---|---|
| Метаданные пакета (GET) | Полная | JSON со всеми версиями |
Scoped-пакеты (@scope/name) | Полная | URL-кодированный путь |
| Скачивание тарболов | Полная | Проверка SHA256 |
| Перезапись URL тарболов | Полная | Указывает на NORA, а не на upstream |
Публикация (npm publish) | Полная | Иммутабельные версии |
| Upstream-прокси | Полная | Настраиваемый TTL; несколько upstream по scope |
| Unpublish | — | Не реализовано |
Dist-теги (latest, next) | Частичная | Читаются из метаданных, без явного управления |
Поиск (/-/v1/search) | — | Не реализовано |
| Аудит безопасности | Прокси | Пересылается в upstream; имена scope с владельцами вырезаются, иначе запрос отклоняется |
Известные ограничения
Заголовок раздела «Известные ограничения»- Unpublish не поддерживается — опубликованные версии являются иммутабельными.
- Dist-теги считываются из upstream-метаданных, но не могут быть явно управляемы через NORA.
- Поиск пакетов не реализован. На аудит отвечает upstream: своей базы уязвимостей у NORA нет.
dist.tarball, указывающий на другой хост, а не на URL своего upstream, не перезаписывается: клиент скачивает тарбол с этого хоста напрямую.- Если upstream недоступен при первом запросе пакета, NORA отвечает
502(до 1.3.4 —404).