Upcoming release

Breaking Changes

  • more deprecated features

    This release cycle features a new batch of deprecated (anti-)features. You can opt in into the old behavior with --extra-deprecated-features or any equivalent configuration option.

    • cr-line-endings: Current handling of CR (\r) or CRLF (\r\n) line endings in Nix is inconsistent and broken, and will lead to unexpected evaluation results with certain strings. Given that fixing the semantics might silently alter the evaluation result of derivations, the only option at the moment is to disallow them alltogether. More proper support for CRLF is planned to be added back again in the future. Until then, all files must use \n exclusively.
    • nul-bytes: Currently the Nix grammar allows NUL bytes (\0) in strings, and thus indirectly also in identifiers. Unfortunately, several core parts of the code base still work with NUL-terminated strings and cannot easily be migrated. Also note that it is still possible to introduce NUL bytes and thus problematic behavior via other means, those are tracked separately.

    Many thanks to piegames and eldritch horrors for this.

  • Builders are always started in a fresh cgroup namespace cl/1996

    If you haven't enabled the experimental cgroups feature, Nix previously launched builder processes in new namespaces but did not create new cgroup namespaces. As a result, derivations could access and observe the parent cgroup namespace.

    Although this update introduces a breaking change, it ensures that all derivations now start in a fresh cgroup namespace by default. This reduces potential impurities observable within the sandbox, improving the likelihood of reproducible builds across different environments.

    Many thanks to Raito Bezarius for this.

  • nix-instantiate --parse outputs json fj#487 nix#11124 nix#4726 nix#3077 cl/2190

    nix-instantiate --parse does not print out the AST in a Nix-like format anymore. Instead, it now prints a JSON representation of the internal expression tree. Tooling should not rely on the stdout of nix-instantiate --parse.

    We've done our best to ensure that the new behavior is as compatible with the old one as possible. If you depend on the old behavior in ways that are not covered anymore or are otherwise negatively affected by this change, then please reach out so that we can find a sustainable solution together.

    Many thanks to piegames and eldritch horrors for this.

Features

  • lix foo now invokes lix-foo from PATH cl/2119

    Lix introduces the ability to extend the Nix command line by adding custom binaries to the PATH, similar to how Git integrates with other tools. This feature allows developers and end users to enhance their workflow by integrating additional functionalities directly into the Nix CLI.

    Examples

    For example, a user can create a custom deployment tool, lix-deploy-tool, and place it in their PATH. This allows them to execute lix deploy-tool directly from the command line, streamlining the process of deploying applications without needing to switch contexts or use separate commands.

    Limitations

    For now, autocompletion is supported to discover new custom commands, but the documentation will not render them. Argument autocompletion of the custom command is not supported either.

    This is also locked behind a new experimental feature called lix-custom-sub-commands to enable developing all the required features.

    Only the top-level lix command can be extended, this is an artificial limitation for the time being until we flesh out this feature.

    Outline

    In the future, this feature may pave the way for moving the Flake subcommand line to its own standalone binary, allowing for a more focused approach to managing Nix Flakes while letting the community explore alternatives to dependency management.

    Many thanks to Raito Bezarius for this.

  • nix-env --install now accepts a --priority flag cl/2607

    nix-env --install now has an optional --priority flag.

    Previously, it was only possible to specify a priority by adding a meta.priority attribute to a derivation. meta attributes only exist during eval, so that wouldn't work for installing a store path. It was also possible to change a priority after initial installation using nix-env --set-flag, however if there is already a conflict that needs to be resolved via priorities, this will not work.

    Now, a priority can be set at install time using --priority, which allows for cleanly overriding the priority at install time.

    Example

    $ nix-build
    $ nix-env --install --priority 100 ./result
    

    Many thanks to Andrew Hamon for this.

Improvements

  • Crashs land in syslog now cl/2640

    When Lix crashes with unexpected exceptions and in some other conditions, it prints bug reporting instructions. Previously, these only landed in stderr and not in syslog. However, on larger Lix installations, it may be the case that Lix crashes in the client without the logs landing in the system logs, which impeded diagnosis.

    Now, such crashes always land in syslog too.

    Many thanks to jade for this.

  • Deletion of specific paths no longer fails fast cl/2778

    nix-store --delete and nix store delete now continue deleting paths even if some of the given paths are still live. An error is only thrown once deletion of all the given paths has been attempted. Previously, if some paths were deletable and others weren't, the deletable ones would be deleted iff they preceded the live ones in lexical sort order.

    The error message for still-live paths no longer reports the paths that could not be deleted, because there could potentially be many of these.

    Many thanks to lheckemann for this.

  • --skip-live for path deletion cl/2778

    nix-store --delete and nix store delete now support a --skip-live option and a --delete-closure option.

    This makes custom garbage-collection logic a lot easier to implement and experiment with:

    • Paths known to be large can be thrown at nix store delete without having to manually filter out those that are still reachable from a root, e.g. nix store delete /nix/store/*mbrola-voices*

    • The --delete-closure option allows extending this to paths that are not large themselves but do have a large closure size, e.g. nix store delete /nix/store/*nixos-system-gamingpc*.

    • Other heuristics like atime-based deletion can be applied more easily, because nix store delete once again takes over the task of working out which paths can't be deleted.

    Many thanks to lheckemann for this.

  • Show all missing and unexpected arguments in errorneous function calls cl/2477

    When calling a function that expects an attribute set, lix will now show all missing and unexpected arguments. e.g. with ({ a, b, c } : a + b + c) { a = 1; d = 1; } lix will now show the error:

    [...]
    error: function 'anonymous lambda' called without required arguments 'b' and 'c' and with unexpected argument 'd'
    [...]
    

    Previously lix would just show b. Furthermore lix will now only suggest arguments that aren't yet used. e.g. with ({ a?1, b?1, c?1 } : a + b + c) { a = 1; d = 1; e = 1; } lix will now show the error:

    [...]
    error: function 'anonymous lambda' called with unexpected arguments 'd' and 'e'
           at «string»:1:2:
                1| ({ a?1, b?1, c?1 } : a + b + c) { a = 1; d = 1; e = 1; }
                 |  ^
           Did you mean one of b or c?
    

    Previously lix would also suggest a. Suggestions are unfortunately still currently just for the first missing argument.

    Many thanks to Zitrone for this.

  • REPL improvements cl/2319 cl/2320

    The REPL has seen various minor improvements:

    • Better error messages overall
    • The :env command to print currently available variables now also works outside of debug mode
    • Adding variables to the REPL now prints a small message on success

    Many thanks to piegames for this.

  • Allow specifying ports for remote ssh[-ng] stores cl/2432

    You can now specify which port should be used for a remote ssh store (e.g. for remote/distributed builds) through a uri parameter. E.g., when a remote builder foo is listening on port 1234 instead of the default, it can be specified like this ssh://foo?port=1234.

    Many thanks to seppel3210 for this.

Fixes

  • Avoid unnecessarily killing processes for the build user's UID nix#9142 fj#667

    We no longer kill all processes under the build user's UID before and after builds on Linux with sandboxes enabled.

    This avoids unrelated processes being killed. This might happen for instance, if the user is running Lix inside a container, wherein the build users use the same UIDs as the daemon's.

    Many thanks to teofilc for this.

  • Forbid impure path accesses in pure evaluation mode again cl/2708

    Lix 2.92.0 mistakenly started allowing the access to ancestors of allowed paths in pure evaluation mode. This made it possible to bypass the purity restrictions, for example by copying arbitrary files to the store:

    builtins.path {
      path = "/";
      filter = …;
    }
    

    Restore the previous behaviour of prohibiting such impure accesses.

    Many thanks to alois31 for this.

  • Fix curl error A value or data field grew larger than allowed cl/2780

    2.92 started using curl-provided HTTP decompression code, but it as discovered that curl has a bug that effectively breaks its decompression code on HTTP/2 transfers. We have partially rolled back our changes and no longer use builtin decompression methods provided by curl, but have kept the refusal of bzip2 and xz content encodings introduced with 2.92 since they are not in the HTTP spec.

    Many thanks to eldritch horrors for this.

  • Fetch peer PID for daemon connections on macOS fj#640 cl/2453

    nix-daemon will now fetch the peer PID for connections on macOS, to match behavior with Linux. Besides showing up in the log output line, If nix-daemon is given an argument (such as --daemon) that argument will be overwritten with the peer PID for the forked process that handles the connection, which can be used for debugging purposes.

    Many thanks to lilyball for this.

  • Test group membership better on macOS gh#5885 cl/2566

    nix-daemon will now test group membership better on macOS for trusted-users and allowed-users. It not only fetches the peer gid (which fixes @staff) but it also asks opendirectory for group membership checks instead of just using the group database, which means nested groups (like @_developer) and groups with synthesized membership (like @localaccounts) will work.

    Many thanks to lilyball for this.

  • nix store delete no longer builds paths cl/2782

    nix store delete no longer realises the installables specified. Previously, nix store delete nixpkgs#hello would download hello only to immediately delete it again. Now, it exits with an error if given an installable that isn't in the store.

    Many thanks to lheckemann for this.

  • Fix nix-store --delete on paths with remaining referrers cl/2783

    Nix 2.5 introduced a regression whereby nix-store --delete and nix store delete started to fail when trying to delete a path that was still referenced by other paths, even if the referrers were not reachable from any GC roots. The old behaviour, where attempting to delete a store path would also delete its referrer closure, is now restored.

    Many thanks to lheckemann for this.

  • Add a straightforward way to detect if in a Nix3 Shell nix#6677 nix#3862 cl/2090

    Running nix shell or nix develop will now set IN_NIX_SHELL to either pure or impure, depending on whether --ignore-environment is passed. nix develop will always be an impure environment.

    Many thanks to Ersei Saggi for this.

  • fix usage of builtins.filterSource and builtins.path with the filter argument when using chroot stores nix#11503

    The semantics of builtins.filterSource (and the filter argument for builtins.path) have been adjusted regarding how paths inside the Nix store are handled.

    Previously, when evaluating whether a path should be included, the filtering function received the physical path if the source was inside the chroot store.

    Now, it receives the logical path instead.

    This ensures consistency in path handling and avoids potential misinterpretations of paths within the evaluator, which led to various fallouts mentioned in https://github.com/NixOS/nixpkgs/pull/369694.

    Many thanks to lily, alois31, and eldritch horrors for this.

  • Fix --help formatting fj#622 cl/2776

    The help printed when invoking nix or nix-store and subcommands with --help previously contained garbled terminal escapes. These have been removed.

    Many thanks to lheckemann for this.

  • Flakes follow --eval-system where it makes sense fj#673 fj#692 gh#11359 cl/2657

    Most flake commands now follow --eval-system when choosing attributes to build/evaluate/etc.

    The exceptions are commands that actually run something on the local machine:

    • nix develop
    • nix run
    • nix upgrade-nix
    • nix fmt
    • nix bundle

    This is not a principled approach to cross compilation or anything, flakes still impede rather than support cross compilation, but this unbreaks many remote build use cases.

    Many thanks to jade for this.

  • Show error when item from NIX_PATH cannot be downloaded

    For e.g. nix-instantiate -I https://example.com/404, you'd only get a warning if the download failed, such as

    warning: Nix search path entry 'https://example.com/404' cannot be downloaded, ignoring
    

    Now, the full error that caused the download failure is displayed with a note that the search path entry is ignored, e.g.

    warning:
         … while downloading https://example.com/404 to satisfy NIX_PATH lookup, ignoring search path entry
    
         warning: unable to download 'https://example.com/404': HTTP error 404 ()
    
         response body: […]
    

    Many thanks to ma27 for this.

  • Fix handling of lastModified in tarball inputs cl/2792

    Previous versions of Lix would fail with the following error, if a tarball flake input redirect to a URL that contains a lastModified field:

    error: input attribute 'lastModified' is not an integer
    

    This is now fixed.

    Many thanks to xanderio and Julian Stecklina for this.

  • Fix --debugger --ignore-try cl/2440

    When in debug mode (e.g. from using the --debugger flag), enabling ignore-try once again properly disables debug REPLs within builtins.tryEval calls. Previously, a debug REPL would be started as if ignore-try was disabled, but that REPL wouldn't actually be in debug mode, and upon exiting the REPL the evaluating process would segfault.

    Many thanks to Dusk Banks for this.

  • Fix interference of the multiline progress bar with output cl/2774

    In some situations, the progress indicator of the multiline progress bar would interfere with persistent output. This would result in progress bar headers being visible in place of the desired text, for example the outputs shown after a :b command in the repl. The underlying ordering issue has been fixed, so that the undesired interference does not happen any more.

    Many thanks to alois31 for this.

  • Paralellise nix store sign using a thread pool fj#399 cl/2606

    nix store sign with a large collection of provided paths (such as when using with --all) has historically signed these paths serially. Taking extreme amounts of time when preforming operations such as fixing binary caches. This has been changed. Now these signatures are performed using a thread pool like nix store copy-sigs.

    Many thanks to Lunaphied for this.