[1.3.5] - 2026-10-13
Added
- Scope eligible retention versions with include_tags (#1080) — optional glob patterns restrict cleanup to matching version/tag names. Nonmatching and explicitly excluded names are preserved and do not consume the keep_last budget; omitted or empty inclusion lists retain existing behavior.
Changed
- Curation files name registries as NORA does (#1092) — a blocklist rule or an allowlist entry may name its registry in any case or by an alias NORA takes elsewhere (
PyPI,maven2,rubygems); such entries used to match nothing. A registry name NORA does not know now fails the load, and so does an allowlist entry for every registry (*). In enforce mode a curation file NORA cannot load stops it with exit code 78, the configuration error the packaged systemd units do not restart into — it used to end in a panic, which they restarted every 5 seconds — and a reload keeps the previous rules; in audit mode the file is logged and skipped. Before upgrading a node that runs curation in enforce mode, check its curation files for registry names NORA does not know; rules that named a registry in another case or by an alias start to apply after the upgrade.
Fixed
- A configured rate limit is applied exactly (#1082) — the
[rate_limit]*_rpssettings were converted to whole milliseconds per request, so any rate above 1000/s was applied as 1000/s and rates between 500 and 1000/s were rounded up (600 → 1000). The interval is now exact for every rate, and the defaults are unchanged. An instance configured with a rate between 500 and 1000/s now enforces it as written. - The npm package page lists every stored tarball (#1083) — the page built its version list from the cached packument only, so a package whose tarballs were cached without one (a lockfile install, or the default settings) showed no versions, and a newer tarball the packument did not name was hidden. Stored tarballs the packument does not name are now listed as cached versions.
- CPAN counts and lists distributions (#1084) — the CPAN index counted every file under
cpan/authors/id/(archives, their.meta/.readmeandCHECKSUMS) grouped by shard letter, so two distributions showed as 7 on the dashboard and 1 in/api/ui/statsandnora_artifacts_total. It now counts distribution archives, one package per author's distribution (A/AU/AUTHOR/Dist-Name), and the CPAN list returns those names. - Crates with capitals in their name download through the cargo proxy (#1085) — the download URL sent upstream lowercased the crate name, and static.crates.io refuses that path for a crate published with capitals (
Inflector), so the client got 404. The upstream URL now keeps the published name; the cache key stays lowercase. - A pull of a locally pushed Docker image counts against that image (#1086) — with an upstream configured, pulls of a pushed image were recorded under the upstream's namespace: the image's own metadata stayed at 0 pulls, and a stray namespaced metadata file hid its push date from curation's release-age check. Pull statistics now go beside the copy that was served. Stray
docker/<namespace>/<image>/manifests/*.meta.jsonfiles left by earlier releases for pushed images can be deleted. - pub packages with capitals in their name are served (#1092) — NORA answered 400 to a pub package name with a capital letter, while pub.dev holds a few such packages (
Pong,RAL,Flutter_Nectar) anddart pub getasks for them as written. Names now follow pub.dev's own rule,[a-zA-Z_][a-zA-Z0-9_]*.
Security
- Curation and internal namespaces decide on the artifact a request resolves to (GHSA-j734-gqxg-24r5) — a request could name an artifact otherwise than curation checked it. A path with an empty segment (
//, a leading or trailing/) reached the same stored object as the path without it, past curation, internal namespaces and integrity pins; storage keys and package names now refuse empty segments, and*in a pattern or an OIDC scope no longer matches an empty one. Names and versions are compared in the form each registry resolves them — PEP 503 names and PEP 440 versions for PyPI, lowercase ids and normalized versions for NuGet, crates.io canonical names for Cargo, lowercase names for Terraform,semver.cleanversions for npm, canonical versions for Go, pub_semver's form for pub — and a pattern's body takes that form in every pattern syntax, so a rule, an allowlist entry or an internal namespace holds however it spells the package or the version. File names are read as their clients read them: PyPI files as pip and setuptools do, CPAN archives as CPAN::DistnameInfo does (any extension case,.tar.Zincluded), and a RubyGems file every way RubyGems can build it, curation weighing each reading for the gem and its gemspec alike until the compact index tells which gem the file is. A Maven metadata path counts for every artifact it can belong to. Terraform module downloads and archives, a provider's files (archive, checksums, signature) and its platforms in the network mirror pass curation and namespace isolation, and an internal provider or module is answered from the cache only. For an internal name no request goes upstream, release-date lookups included.
Install
# x86_64
curl -LO https://github.com/getnora-io/nora/releases/download/v1.3.5/nora-linux-amd64
chmod +x nora-linux-amd64
sudo mv nora-linux-amd64 /usr/local/bin/nora
# ARM64 (Apple Silicon, Graviton, Ampere)
curl -LO https://github.com/getnora-io/nora/releases/download/v1.3.5/nora-linux-arm64
chmod +x nora-linux-arm64
sudo mv nora-linux-arm64 /usr/local/bin/noraDocker
docker pull getnora/nora:1.3.5| Variant | Image | Platforms |
|---|---|---|
| Alpine (default) | getnora/nora:1.3.5
| amd64, arm64 |
| RED OS | getnora/nora:1.3.5-redos
| amd64 |
| Astra Linux SE | getnora/nora:1.3.5-astra
| amd64 |
| GHCR | ghcr.io/getnora-io/nora:1.3.5
| amd64, arm64 |
DEB / RPM
# Debian / Ubuntu / Astra Linux (amd64)
curl -LO https://github.com/getnora-io/nora/releases/download/v1.3.5/nora-amd64.deb
sudo dpkg -i nora-amd64.deb
# RHEL / Fedora / RED OS (amd64)
curl -LO https://github.com/getnora-io/nora/releases/download/v1.3.5/nora-amd64.rpm
sudo rpm -i nora-amd64.rpmChangelog
See CHANGELOG.md