Release 2.30.0 (2025-07-07)
Backward-incompatible changes and deprecations
-
build-dir
no longer defaults to$TMPDIR
The directory in which temporary build directories are created no longer defaults to
TMPDIR
or/tmp
, to avoid builders making their directories world-accessible. This behavior allowed escaping the build sandbox and can cause build impurities even when not used maliciously. We now default tobuilds
inNIX_STATE_DIR
(which is/nix/var/nix/builds
in the default configuration). -
Deprecate manually making structured attrs using the
__json
attribute #13220The proper way to create a derivation using structured attrs in the Nix language is by using
__structuredAttrs = true
withbuiltins.derivation
. However, by exploiting how structured attrs are implementated, it has also been possible to create them by setting the__json
environment variable to a serialized JSON string. This sneaky alternative method is now deprecated, and may be disallowed in future versions of Nix. -
Rename
nix profile install
tonix profile add
#13224The command
nix profile install
has been renamed tonix profile add
(though the former is still available as an alias). This is because the verb "add" is a better antonym for the verb "remove" (i.e.nix profile remove
). Nix also does not have install hooks or general behavior often associated with "installing".
Performance improvements
This release has a number performance improvements, in particular:
-
Reduce the size of value from 24 to 16 bytes #13407
This shaves off a very significant amount of memory used for evaluation (~20% percent reduction in maximum heap size and ~17% in total bytes).
Features
-
Add stack sampling evaluation profiler #13220
The Nix evaluator now supports stack sampling evaluation profiling via the
--eval-profiler flamegraph
setting. It outputs collapsed call stack information to the file specified by--eval-profile-file
(nix.profile
by default) in a format directly consumable byflamegraph.pl
and compatible tools like speedscope. Sampling frequency can be configured via--eval-profiler-frequency
(99 Hz by default).Unlike the existing
--trace-function-calls
, this profiler includes the name of the function being called when it's available. -
nix repl
prints which variables were loaded #11406Instead of
Added <n> variables
it now prints the first 10 variables that were added to the global scope. -
nix flake archive
: Add--no-check-sigs
option #13277This is useful when using
nix flake archive
with the destination set to a remote store. -
Emit warnings for IFDs with
trace-import-from-derivation
option #13279While we have the setting
allow-import-from-derivation
to deny import-from-derivation (IFD), sometimes users would like to observe IFDs during CI processes to gradually phase out the idiom. The new settingtrace-import-from-derivation
, when set, logs a simple warning to the console. -
json-log-path
setting #13003New setting
json-log-path
that sends a copy of all Nix log messages (in JSON format) to a file or Unix domain socket. -
Non-flake inputs now contain a
sourceInfo
attribute #13164 #13170Flakes have always had a
sourceInfo
attribute which describes the source of the flake. ThesourceInfo.outPath
is often identical to the flake'soutPath
. However, it can differ when the flake is located in a subdirectory of its source.Non-flake inputs (i.e. inputs with
flake = false
) can also be located at some path within a wider source. This usually happens when defining a relative path input within the same source as the parent flake, e.g.inputs.foo.url = ./some-file.nix
. Such relative inputs will now inherit their parent'ssourceInfo
.This also means it is now possible to use
?dir=subdir
on non-flake inputs.This iterates on the work done in 2.26 to improve relative path support (#10089), and resolves a regression introduced in 2.28 relating to nested relative path inputs (#13164).
Miscellaneous changes
-
builtins.sort
uses PeekSort #12623Previously it used libstdc++'s
std::stable_sort()
. However, that implementation is not reliable if the user-supplied comparison function is not a strict weak ordering. -
Revert incomplete closure mixed download and build feature #77 #12628 #13176
Since Nix 1.3 (commit
299141e
in 2013) Nix has attempted to mix together upstream fresh builds and downstream substitutions when remote substuters contain an "incomplete closure" (have some store objects, but not the store objects they reference). This feature is now removed.In the worst case, removing this feature could cause more building downstream, but it should not cause outright failures, since this is not happening for opaque store objects that we don't know how to build if we decide not to substitute. In practice, however, we doubt even more building is very likely to happen. Remote stores that are missing dependencies in arbitrary ways (e.g. corruption) don't seem to be very common.
On the contrary, when remote stores fail to implement the closure property, it is usually an intentional choice on the part of the remote store, because it wishes to serve as an "overlay" store over another store, such as
https://cache.nixos.org
. If an "incomplete closure" is encountered in that situation, the right fix is not to do some sort of "franken-building" as this feature implemented, but instead to make sure both substituters are enabled in the settings.(In the future, we should make it easier for remote stores to indicate this to clients, to catch settings that won't work in general before a missing dependency is actually encountered.)
Contributors
This release was made possible by the following 32 contributors:
- Cole Helbling (@cole-h)
- Eelco Dolstra (@edolstra)
- Egor Konovalov (@egorkonovalov)
- Farid Zakaria (@fzakaria)
- Graham Christensen (@grahamc)
- gustavderdrache (@gustavderdrache)
- Gwenn Le Bihan (@gwennlbh)
- h0nIg (@h0nIg)
- Jade Masker (@donottellmetonottellyou)
- jayeshv (@jayeshv)
- Jeremy Fleischman (@jfly)
- John Ericson (@Ericson2314)
- Jonas Chevalier (@zimbatm)
- Jörg Thalheim (@Mic92)
- kstrafe (@kstrafe)
- Luc Perkins (@lucperkins)
- Matt Sturgeon (@MattSturgeon)
- Nikita Krasnov (@synalice)
- Peder Bergebakken Sundt (@pbsds)
- pennae (@pennae)
- Philipp Otterbein
- Pol Dellaiera (@drupol)
- PopeRigby (@poperigby)
- Raito Bezarius
- Robert Hensing (@roberth)
- Samuli Thomasson (@SimSaladin)
- Sergei Zimmerman (@xokdvium)
- Seth Flynn (@getchoo)
- Stefan Boca (@stefanboca)
- tomberek (@tomberek)
- Tristan Ross (@RossComputerGuy)
- Valentin Gagarin (@fricklerhandwerk)
- Vladimír Čunát (@vcunat)
- Wolfgang Walther (@wolfgangwalther)