Перейти к содержимому

Руководство по обновлению

1.4.3 читает хранилище 1.4.2 как есть, и на локальном диске, и в S3, а 1.4.2 читает то, что сохранила 1.4.3. 1.4.3 закрывает уязвимости из GHSA-54qr-w49h-mgfq.

OIDC-провайдер в [[auth.oidc.providers]] без audience на 1.4.3 останавливает запуск (код выхода 78: systemd-юниты из пакетов после него сервис не перезапускают) с ошибкой, называющей провайдера; перезагрузку по SIGHUP, которая его добавляет, NORA отклоняет. Задайте каждому включённому провайдеру audience, который запрашивают задания CI (core.getIDToken('nora'), в GitLab id_tokens: … aud:), или any_audience = true, если назвать aud нельзя: тогда принимается любой aud, с предупреждением при каждом запуске.

ИзменениеВлияниеЧто сделать
OIDC-провайдер без audienceОтклоняется при запуске и при перезагрузке (см. выше)Задать audience или any_audience = true
nora import для PyPI и NuGetИмпортируются как hosted: индекс, версии и даты строятся из того, что хранит NORA, upstream об имени не спрашивается. Импортированный проект PyPI отдаёт только импортированные или загруженные в него файлыЗапустить импорт ещё раз: репозиторий PyPI или NuGet, который 1.4.2 и старше отметили завершённым, обходится заново. Файл, загруженный под именем импортированного проекта версией 1.4.2 и старше, загрузить снова
/health503 с failing_task, когда фоновая задача паникует раз за разом или цикл обслуживания не завершает ни одного прохода за server.maintenance_stall_secs (300 с). Паника обработчика отвечает 500, сервер продолжает работать; паника записи аудита завершает процесс с кодом 70Kubernetes перезапускает по liveness-пробе. Под Docker без Swarm или под systemd 503 сам ничего не перезапускает: добавьте autoheal или таймер с nora healthcheck || systemctl restart nora
/ready503, когда хранилище не ответило к сроку прохода обслуживания, без перезапускаНичего
Пределы соединений: server.header_read_timeout (30 с), server.keep_alive_timeout (120 с), server.max_connections (4096)Соединения без заголовков запроса и простаивающие закрываются; HTTP/2 закрывается с GOAWAYДержите keep_alive_timeout больше idle-таймаута reverse proxy перед NORA (90 с и меньше — предупреждение при старте), а max_connections — больше числа keep-alive соединений, которые этот прокси держит открытыми
Сроки токеновНе больше 3650 дней на любом пути выпуска; токен, выпущенный OIDC-идентичностью, живёт не дольше max_token_lifetime_secs провайдера и остатка своего JWT. В ответе есть expires_in_secsНичего
Блокировка по паролюСчитается по имени пользователя на адресе; адрес по-прежнему блокируется для всех имён после неверных паролей к десяти учётным записямНичего
Адрес клиента при NORA_HOST=:: (дефолт образа)IPv4-клиент читается как IPv4, поэтому его видят trusted_proxies и ограничение частотыНичего
Tarball npmЗагружается только для версии из пакумента upstream, по его ссылке. Редирект на другой origin выполняется без учётных данных upstream; метаданные записи proxies, привязанной к scope, берутся только с её originНичего
Попадания в кэшДороже по CPU: p95 большого пакумента npm вроде react около 16 мс (было около 10 мс)Ничего

Остановите 1.4.3 и запустите 1.4.2 на том же хранилище. 1.4.2 не знает server.header_read_timeout, server.keep_alive_timeout, server.max_connections, server.maintenance_stall_secs и any_audience: она предупреждает и игнорирует их, но с NORA_CONFIG_STRICT=true не стартует (код выхода 78). Перед откатом уберите их из config.toml или задайте ключи [server] переменными окружения (NORA_HEADER_READ_TIMEOUT и остальные) — их 1.4.2 не читает.

1.4.0 читает хранилище 1.3.6 как есть, и на локальном диске, и в S3. Она добавляет свои ключи, которые 1.3.6 не читает: записи написаний Cargo в cargo/_names/, индекс upstream Cargo под отдельным ключом и копии upstream npm в npm/<name>/upstream/. 1.4.0 закрывает уязвимости из GHSA-5pr2-xx8w-79jc и GHSA-pg2g-wvgf-cxpp.

Некоторые конфигурации, с которыми 1.3.6 стартует, на 1.4.0 останавливают запуск; сообщение называет ключ:

  • min_release_age для rpm, deb или cpan — у этих загрузок нет ни проверки имени, ни даты релиза, которую можно выдержать;
  • min_release_age отдельного proxy-реестра без карантина этого реестра (curation.<registry>.quarantine или глобального curation.quarantine);
  • глобальный min_release_age без карантина, когда набор включённых реестров монтирует proxy-реестры с выключенными собственными флагами, или монтирует Hugging Face через all,hf;
  • curation.require_integrity без curation.allowlist_path;
  • любые настройки [curation.hf] и переменные NORA_CURATION_HF_* — модели Hugging Face удерживаются по репозиторию и коммиту в allowlist и blocklist.
ИзменениеВлияниеЧто сделать
Cargo: крейт, опубликованный в NORA, отдаётся только из своих записейUpstream о нём не спрашивается; скачивание версии, которой у него нет, — 404, ничего не запрашивается и не сохраняетсяПервый cargo publish поверх индекса, который старый релиз оставил без записей по версиям, отклоняется с 409 и именем ключа: удалите ключ, если это кэш upstream, или задайте NORA_CARGO_IMPORT_EMBEDDED=<имя>, если это ваш крейт
Cargo: - и _ — одно имя крейта, как на crates.ioДругое написание опубликованного крейта — 404 (с опубликованным написанием в ответе), у upstream не запрашивается; публикация — 409Ничего. Первый запуск до приёма запросов записывает написания для крейтов, опубликованных до 1.4.0 (один листинг опубликованных записей)
Cargo: копии неизвестных версий, которые старый релиз сохранил рядом с опубликованным крейтомДля имён с - или _ не отдаются; по-прежнему видны в UI и учитываются keep_lastУдалите вручную (#1163)
Retention и GC CargoЗаписи индекса по версиям и .crate крейтов с именами из одной-двух букв больше не удаляютсяНичего
Docker: запушенный тегОтвечает только запушенный манифест, в том числе после pull через прокси; курация датирует его по pushТег, запушенный до 1.4.0 поверх уже проксированного, остаётся за проксированной копией, пока его не запушат снова
Docker: манифест по дайджестуОтвет upstream с другим дайджестом считается сбоем upstream; push по дайджесту с другими байтами — 400 DIGEST_INVALIDНичего
Docker: теги, оканчивающиеся на .meta или .stats400 на всех маршрутах манифестовПереименуйте такие теги
Docker: удаление, которое не может прочитать метаданные манифеста500, ничего не удаляется (было 202)Ничего
Docker: отказ курацииdocker pull и skopeo печатают denied: blocked by policy: …Ничего
npm: пакет, опубликованный в NORAPackument, манифесты версий и dist-tags отдаются из его ключей, upstream не спрашиваетсяПубликация поверх packument неизвестного происхождения у пакета без опубликованных версий — 409 с именем ключа: удалите его, если это кэш, или задайте NORA_NPM_IMPORT_EMBEDDED=<имя>, если это ваш пакет
npm: npm search и другие пути метаданныхОтвечает upstream, без кэшаНичего
Пустая настройка upstream у gems, NuGet, Conan, Terraform, Ansible, CPANФормат отвечает только из хранилища (было: публичный upstream по умолчанию)Ничего, если вы имели в виду «без upstream»
PyPI: учётные данные upstreamУходят только этому upstream, а не хостам файлов, на которые он ссылаетсяНичего
curation.mode по умолчанию при включённых proxy-реестрахПредупреждение при каждом запуске и nora_config_deprecated{reason="curation_mode_implicit"} 1; 1.5.0 будет останавливать запускЗадайте curation.mode (NORA_CURATION_MODE): off, audit или enforce
Адрес клиента за обратным проксиБерётся справа в X-Forwarded-For, за доверенными проксиПроверьте NORA_AUTH_TRUSTED_PROXIES, если перед NORA больше одного прокси
Прокси Hugging Face HubНовое, включается явно (NORA_HF_ENABLED=true)Ничего

Остановите 1.4.0 и запустите 1.3.6 на том же хранилище. Опубликованные крейты Cargo, пакеты npm и образы Docker продолжают работать. 1.3.6 не читает записи написаний и копии upstream, которые 1.4.0 хранит под своими ключами, поэтому снова запрашивает эти пакеты у upstream. Packument неопубликованного пакета, который закэшировал старый релиз, 1.4.0 не перезаписывает, и 1.3.6 его находит.

1.3.4 читает хранилище 1.3.3 как есть, и на локальном диске, и в S3. Миграция не нужна.

ИзменениеВлияниеЧто сделать
npm: несколько upstream по scope (npm.proxies)Новое, включается явноНичего. См. npm
npm: недоступный upstream при первом запросе пакета502 вместо 404Ничего. Клиент сообщает об ошибке шлюза, а не об отсутствии пакета
npm audit при scope с владельцами или внутреннем пространстве имёнЗапрос, из которого NORA не может вырезать эти имена, получает 4xx с причиной, а не пересылаетсяИспользуйте npm 7+ (bulk-аудит) или yarn npm audit
Circuit breaker для Docker, PyPI, npmСвой breaker на каждый upstream; метка метрик registry="<формат>:<url>"Дашборды и алерты с registry="pypi" и т. п. переведите на registry=~"pypi(:.*)?"
circuit_breaker.overrides.dockerТеперь применяется (раньше игнорировался)Проверьте заданные значения
Неизвестные ключи в config.tomlЗаписываются в лог предупреждением с именамиПри желании задайте NORA_CONFIG_STRICT=true, чтобы такие ключи отклонялись
Запись в локальное хранилищеИдёт через .nora-staging/ в корне хранилища; перезапуск удаляет то, что оставил упавший экземплярНичего
ЛогиУчётные данные в URL (user:pass@) маскируютсяНичего

Остановите 1.3.4 и запустите 1.3.3 на том же хранилище. 1.3.3 отдаёт всё, что сохранила 1.3.4, а её retention и GC не видят записи, которые 1.3.4 хранит в .nora-origins/ и .nora-staging/.

v0.9 обратно совместима по всем возможностям и хранилищу. Единственное необходимое действие — обновить переименованные переменные окружения, если вы используете какие-либо из переименованных имён, перечисленных ниже.

ВозможностьВлияниеТребуемое действие
Изоляция пространств имён DockerВ структуру хранилища добавляется префикс пространства имёнНет — ленивая миграция выполняется автоматически
Circuit breakerНовая возможность, отключена по умолчаниюНет
TTL метаданных Docker + stale-while-errorНовая возможность, включается вручнуюНет
Потоковый read_timeoutНовая возможность, включается вручнуюНет
Горячая перезагрузка курирования по SIGHUPНовая возможностьНет
Бинарный файл linux/arm64Новая платформаНет

В v0.9 вводятся префиксы пространств имён для каждого вышестоящего источника в ключах хранилища Docker, чтобы изолировать данные из разных вышестоящих реестров.

Старая структура (v0.8):

docker/{name}/blobs/{digest}
docker/{name}/manifests/{ref}.json

Новая структура (v0.9):

docker/{namespace}/{name}/blobs/{digest}
docker/{namespace}/{name}/manifests/{ref}.json

Пространство имён определяется по URL вышестоящего источника (например, registry-1.docker.io превращается в docker.io) или задаётся явно через поле namespace в [[docker.upstreams]].

Миграция автоматическая и ленивая:

  • При обработке запроса NORA сначала проверяет путь с пространством имён.
  • Если он не найден, происходит откат к устаревшему плоскому пути.
  • Никакой фоновой миграции при запуске не выполняется.
  • Существующие закэшированные данные продолжают отдаваться без перебоев.
  1. Остановите работающий экземпляр NORA.
  2. Замените бинарный файл или обновите образ контейнера до v0.9.
  3. Запустите NORA с вашей существующей конфигурацией.
Окно терминала
# Binary upgrade
curl -fsSL https://github.com/getnora-io/nora/releases/latest/download/nora-linux-amd64 -o nora
chmod +x nora
./nora

Скрипты миграции данных не требуются.

Чтобы откатиться с v0.9 на v0.8:

  1. Остановите экземпляр v0.9.
  2. Замените бинарный файл или образ на v0.8.
  3. Запустите NORA.

В v0.9 добавлены следующие необязательные переменные (все отключены или неактивны по умолчанию):

ПеременнаяПо умолчаниюОписание
NORA_CB_ENABLEDfalseВключить circuit breaker
NORA_CB_THRESHOLD5Число сбоев до размыкания
NORA_CB_RESET_TIMEOUT30Секунд до пробного запроса
NORA_DOCKER_READ_TIMEOUT60Таймаут чтения одного фрагмента (секунды)
NORA_DOCKER_METADATA_TTL-1TTL кэша метаданных в секундах
NORA_DOCKER_SERVE_STALEtrueОтдавать закэшированные манифесты, когда вышестоящий источник недоступен

Полный справочник см. в Справочнике по конфигурации.

В v0.9 несколько имён переменных сокращены в соответствии с соглашением NORA_{SECTION}_{FIELD} (менее 30 символов):

Старое имяНовое имя
NORA_TF_ENABLEDNORA_TF_ENABLED
NORA_TF_PROXYNORA_TF_PROXY
NORA_TF_PROXY_TIMEOUTNORA_TF_PROXY_TIMEOUT
NORA_TF_METADATA_TTLNORA_TF_METADATA_TTL
NORA_TF_PROXY_TIMEOUT_DLNORA_TF_PROXY_TIMEOUT_DL
NORA_CONAN_PROXY_TIMEOUT_DLNORA_CONAN_PROXY_TIMEOUT_DL
NORA_CURATION_INTERNAL_NSNORA_CURATION_INTERNAL_NS

Старые имена больше не распознаются. Обновите свою конфигурацию, если вы используете какие-либо из них.