Release 2.33.0 (2025-12-09)

New features

  • New command nix registry resolve #14595

    This 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-unstable
    

    Upstreamed from Determinate Nix 3.14.0.

  • nix flake clone supports all input types #14581

    nix flake clone now 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 #14462

    When using Git repositories with a long history, calculating the revCount attribute can take a long time. Nix now computes revCount using 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 attribute shallow = true.

    Upstreamed from Determinate Nix 3.12.2.

  • builtins.stringLength now runs in constant time #14442

    The 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:// and https:// binary cache stores now run in constant memory #14390

    Nix 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/ to https://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' setting warning #11728 #14614

    The 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-size is 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 fetchTarball and github, tarball flake 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 ls and nix nar cat are 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-cpp instead of full aws-cpp-sdk, reducing build complexity

    The new implementation requires curl >= 7.75.0 and aws-crt-cpp for 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 when multipart-upload is 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 by multipart-chunk-size and 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 versionId parameter #13955 #14274

    S3 URLs now support a versionId query 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-class parameter. 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, and info fields:

    {
      "version": 2,
      "storeDir": "/nix/store",
      "info": { ... }
    }
    

    The map from store path base names to store object info is nested under the info field.

  • 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 with storeDir, the full path can be reconstructed.

  • Structured ca field:

    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 null values for input-addressed store objects

    The hash field uses the SRI format like other hashes.

Additionally the following fields are added to both formats:

  • version field:

    All store path info JSON now includes "version": <1|2>. The version tracks breaking changes, and adding fields to outputted JSON is not a breaking change.

  • storeDir field:

    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 show is now wrapped in an object with version and derivations fields:

    {
      "version": 4,
      "derivations": { ... }
    }
    

    The map from derivation paths to derivation info is nested under the derivations field.

    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 inputs object:

    • Old: "inputSrcs": [...], "inputDrvs": {...}
    • New: "inputs": {"srcs": [...], "drvs": {...}}
  • Consistent content addresses:

    Fixed content-addressed outputs now use structured JSON format. This is the same format as ca in 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 :b or :p can 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 openat and openat2 system 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: