Release 2.33.0 (2025-12-09)
New features
-
New command
nix registry resolve#14595This command looks up a flake registry input name and returns the flakeref it resolves to.
For example, looking up Nixpkgs:
$ nix registry resolve nixpkgs github:NixOS/nixpkgs/nixpkgs-unstableUpstreamed from Determinate Nix 3.14.0.
-
nix flake clonesupports all input types #14581nix flake clonenow supports arbitrary input types. In particular, this allows you to clone tarball flakes, such as flakes on FlakeHub.Upstreamed from Determinate Nix 3.12.0.
Performance improvements
-
Git fetcher computes
revCounts using multiple threads #14462When using Git repositories with a long history, calculating the
revCountattribute can take a long time. Nix now computesrevCountusing multiple threads, making it much faster (e.g. 9.1s to 3.7s for Nixpkgs).Note that if you don't need
revCount, you can disable it altogether by setting the flake input attributeshallow = true.Upstreamed from Determinate Nix 3.12.2.
-
builtins.stringLengthnow runs in constant time #14442The internal representation of strings has been replaced with a size-prefixed Pascal style string. Previously Nix stored strings as a NUL-terminated array of bytes, necessitating a linear scan to calculate the length.
-
Uploads to
http://andhttps://binary cache stores now run in constant memory #14390Nix used to buffer the whole compressed NAR contents in memory. It now reads it in a streaming fashion.
-
Channel URLs migrated to channels.nixos.org subdomain #14517 #14518
Channel URLs have been updated from
https://nixos.org/channels/tohttps://channels.nixos.org/throughout Nix. This subdomain provides better reliability with IPv6 support and improved CDN distribution. The old domain apex (nixos.org/channels/) currently redirects to the new location but may be deprecated in the future. -
Fix
download buffer is full; consider increasing the 'download-buffer-size' settingwarning #11728 #14614The underlying issue that led to #11728 has been resolved by utilizing libcurl write pausing functionality to control backpressure when unpacking to slow destinations like the git-backed tarball cache. The default value of
download-buffer-sizeis now 1 MiB and it's no longer recommended to increase it, since the root cause has been fixed.This is expected to improve download performance on fast connections, since previously a single slow download consumer would stall the thread and prevent any other transfers from progressing.
Many thanks go out to the Lix project for the implementation that served as inspiration for this change and for triaging libcurl issues with pausing.
-
Significantly improve tarball unpacking performance #14689 #14696 #10683 #11098
Nix uses a content-addressed cache backed by libgit2 for deduplicating files fetched via
fetchTarballandgithub,tarballflake inputs. Its usage has been significantly optimised to reduce the amount of I/O operations that are performed. For a typical nixpkgs source tarball this results in 200 times fewer system calls on Linux. In combination with libcurl pausing this alleviates performance regressions stemming from the tarball cache. -
Already valid derivations are no longer copied to the store #14219
This results in a modest speedup when using the Nix daemon.
-
nix nar lsandnix nar catare significantly faster and no longer buffer the whole NAR in memory #14273 #14732
S3 improvements
-
Improved S3 binary cache support via HTTP #11748 #12403 #12671 #13084 #13752 #13823 #14026 #14120 #14131 #14135 #14144 #14170 #14190 #14198 #14206 #14209 #14222 #14223 #14330 #14333 #14335 #14336 #14337 #14350 #14356 #14357 #14374 #14375 #14376 #14377 #14391 #14393 #14420 #14421
S3 binary cache operations now happen via HTTP, leveraging
libcurl's native AWS SigV4 authentication instead of the AWS C++ SDK, providing significant improvements:- Reduced memory usage: Eliminates memory buffering issues that caused segfaults with large files
- Fixed upload reliability: Resolves AWS SDK chunking errors (
InvalidChunkSizeError) - Lighter dependencies: Uses lightweight
aws-crt-cppinstead of fullaws-cpp-sdk, reducing build complexity
The new implementation requires curl >= 7.75.0 and
aws-crt-cppfor credential management.All existing S3 URL formats and parameters remain supported, however the store settings for configuring multipart uploads have changed:
-
multipart-upload(default:false): Enable multipart uploads for large files. When enabled, files exceeding the multipart threshold will be uploaded in multiple parts. -
multipart-threshold(default:100 MiB): Minimum file size for using multipart uploads. Files smaller than this will use regular PUT requests. Only takes effect whenmultipart-uploadis enabled. -
multipart-chunk-size(default:5 MiB): Size of each part in multipart uploads. Must be at least 5 MiB (AWS S3 requirement). Larger chunk sizes reduce the number of requests but use more memory. -
buffer-size: Has been replaced bymultipart-chunk-sizeand is now an alias to it.
Note that this change also means Nix now supports S3 binary cache stores even if built without
aws-crt-cpp, but only for public buckets which do not require authentication. -
S3 URLs now support object versioning via
versionIdparameter #13955 #14274S3 URLs now support a
versionIdquery parameter to fetch specific versions of objects from S3 buckets with versioning enabled. This allows pinning to exact object versions for reproducibility and protection against unexpected changes:s3://bucket/key?region=us-east-1&versionId=abc123def456 -
S3 binary cache stores now support storage class configuration #7015 #14464
S3 binary cache stores now support configuring the storage class for uploaded objects via the
storage-classparameter. This allows users to optimize costs by selecting appropriate storage tiers based on access patterns.Example usage:
# Use Glacier storage for long-term archival nix copy --to 's3://my-bucket?storage-class=GLACIER' /nix/store/... # Use Intelligent Tiering for automatic cost optimization nix copy --to 's3://my-bucket?storage-class=INTELLIGENT_TIERING' /nix/store/...The storage class applies to both regular uploads and multipart uploads. When not specified, objects use the bucket's default storage class.
See the S3 storage classes documentation for available storage classes and their characteristics.
Store path info JSON format changes
The JSON format emitted by nix path-info --json has been updated to a new version with improved structure.
To maintain compatibility, nix path-info --json now requires a --json-format flag to specify the output format version.
Using --json without --json-format is deprecated and will become an error in a future release.
For now, it defaults to version 1 with a warning, for a smoother migration.
Version 1 (--json-format 1)
This is the legacy format, preserved for backwards compatibility:
- String-based hash values (e.g.,
"narHash": "sha256:FePFYIlM...") - String-based content addresses (e.g.,
"ca": "fixed:r:sha256:1abc...") - Full store paths for map keys and references (e.g.,
"/nix/store/abc...-foo") - Now includes
"storeDir"field at the top level
Version 2 (--json-format 2)
The new structured format follows the JSON guidelines with the following changes:
-
Nested structure with top-level metadata:
The output is now wrapped in an object with
version,storeDir, andinfofields:{ "version": 2, "storeDir": "/nix/store", "info": { ... } }The map from store path base names to store object info is nested under the
infofield. -
Store path base names instead of full paths:
Map keys and references use store path base names (e.g.,
"abc...-foo") instead of full absolute store paths. Combined withstoreDir, the full path can be reconstructed. -
Structured
cafield:Content address is now a structured JSON object instead of a string:
- Old:
"ca": "fixed:r:sha256:1abc..." - New:
"ca": {"method": "nar", "hash": "sha256-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="} - Still
nullvalues for input-addressed store objects
The
hashfield uses the SRI format like other hashes. - Old:
Additionally the following fields are added to both formats:
-
versionfield:All store path info JSON now includes
"version": <1|2>. Theversiontracks breaking changes, and adding fields to outputted JSON is not a breaking change. -
storeDirfield:Top-level
"storeDir"field contains the store directory path (e.g.,"/nix/store").
Derivation JSON format changes
The derivation JSON format has been updated from version 3 to version 4:
-
Nested structure with top-level metadata:
The output of
nix derivation showis now wrapped in an object withversionandderivationsfields:{ "version": 4, "derivations": { ... } }The map from derivation paths to derivation info is nested under the
derivationsfield.This matches the structure used for
nix path-info --json --json-format 2, and likewise brings this command into compliance with the JSON guidelines. -
Restructured inputs:
Inputs are now nested under an
inputsobject:- Old:
"inputSrcs": [...], "inputDrvs": {...} - New:
"inputs": {"srcs": [...], "drvs": {...}}
- Old:
-
Consistent content addresses:
Fixed content-addressed outputs now use structured JSON format. This is the same format as
cain store path info (after the new version).
Version 3 and earlier formats are not accepted when reading.
Affected command: nix derivation, namely its show and add sub-commands.
Miscellaneous changes
-
Git fetcher: Restore progress indication #14487
Nix used to feel "stuck" while it was cloning large repositories. Nix now shows Git's native progress indicator while fetching.
Upstreamed from Determinate Nix 3.13.0.
-
Interrupting REPL commands works more than once #13481
Previously, this only worked once per REPL session; further attempts would be ignored. This issue is now fixed, so REPL commands such as
:bor:pcan be canceled consistently. This is a cherry-pick of the change from the Lix project. -
NAR unpacking code has been rewritten to make use of dirfd-based
openatandopenat2system calls when available #14597 -
Dynamic size unit rendering #14423 #14364
Various commands and the progress bar now use dynamically determined size units instead of always using
MiB. For example, the progress bar now reports download status like:[1/196/197 copied (773.7 MiB/2.1 GiB), 172.4/421.5 MiB DL]Instead of:
[1/196/197 copied (773.7/2147.3 MiB), 172.4/421.5 MiB DL]
Contributors
This release was made possible by the following 33 contributors:
- Adam Dinwoodie (@me-and)
- jonhermansen (@jonhermansen)
- Arnout Engelen (@raboof)
- Jean-François Roche (@jfroche)
- tomberek (@tomberek)
- Eelco Dolstra (@edolstra)
- Marcel (@MarcelCoding)
- David McFarland (@corngood)
- Soumyadip Sarkar (@neuralsorcerer)
- Cole Helbling (@cole-h)
- John Ericson (@Ericson2314)
- Tristan Ross (@RossComputerGuy)
- Alex Auvolat (@Alexis211)
- edef (@edef1c)
- Sergei Zimmerman (@xokdvium)
- Vinayak Goyal (@vinayakankugoyal)
- Graham Dennis (@GrahamDennis)
- Aspen Smith (@glittershark)
- Jens Petersen (@juhp)
- Bernardo Meurer (@lovesegfault)
- Peter Bynum (@pkpbynum)
- Jörg Thalheim (@Mic92)
- Alex Decious (@adeci)
- Matthieu Coudron (@teto)
- Domen Kožar (@domenkozar)
- Taeer Bar-Yam (@Radvendii)
- Seth Flynn (@getchoo)
- Robert Hensing (@roberth)
- Vladimir Panteleev (@CyberShadow)
- bryango (@bryango)
- Henry (@cootshk)
- Martin Joerg (@mjoerg)
- Farid Zakaria (@fzakaria)