Changelog: security fixes, OpenTelemetry tracing, baked flakes, fiber-based parallel evaluation, and more

We at Determinate Systems are pleased to announce the release of Determinate Nix version 3.23.3, based on upstream Nix 2.35.3. This post covers everything that’s changed since 3.22.2 and covers Determinate Nix versions 3.22.3, 3.22.4, 3.22.5, 3.23.0, 3.23.1, 3.23.2, and 3.23.3, which means we have a lot to share with you:
- Determinate Nix 3.23.2 fixes four security vulnerabilities, including one that allowed local privilege escalation through the Nix daemon, so we strongly recommend upgrading.
- Determinate Nix can now export OpenTelemetry traces of evaluations, builds, substitutions, and more.
- The new experimental
nix flake bakecommand produces what we’re calling baked flakes, which are flakes whose outputs need (almost) no evaluation. - The garbage collector no longer races with processes that are still creating the store paths it’s deleting.
- Parallel evaluation now runs on fibers rather than blocking threads, and it now spends far less time waiting on the garbage collector’s global lock.
builtins.wasmcaches compiled modules, reads files and attribute sets more efficiently, and bounds-checks every guest memory access.- Evaluating through the Nix daemon is faster thanks to a smarter asynchronous path writer.
- You can now experimentally build Nix with Nix using a new Wasm-backed C++ build system.
- The flake eval cache now provides performance benefits earlier (on the second evaluation run instead of the third).
- Tarball unpacking is faster, while repeat Git fetches transfer far less data.
- Git inputs with submodules that were locked with Nix < 2.20 can once again evaluate.
- Nix now copies files with zero-copy block cloning on filesystems that support it.
- Purging the binary cache metadata cache no longer blocks concurrent
nix copyruns on busy builders. nix profile historyreports rebuilt packages and can show where each package came from.- With the
use-cgroupssetting enabled, build cgroups now expose memory and I/O statistics. - Nix handles interruptions and memory exhaustion far more gracefully, and 3.23.1 through 3.23.3 bring a round of bug fixes for issues reported through crash reporting.
- Determinate Nixd now logs the cause of HTTP 500 errors, records less information in its tracing spans, and tells you how to get Native Linux Builder working when it isn’t available.
And as always, we’ve included a batch of smaller improvements to round out the lineup.
Security fixes
Determinate Nix 3.23.2 fixes four security vulnerabilities that affect all earlier versions of Determinate Nix, on both Linux and macOS. We strongly recommend that you upgrade.
- Store path corruption through the Nix daemon (GHSA-jwvx-xq5j-gc56, high severity).
Users who could connect to the Nix daemon (those matched by
allowed-users) but weren’t trusted could pass the repair flag when adding a Nix Archive (NAR) to the store, which let them replace the contents of arbitrary store paths. With the daemon running as root, that’s a route to local privilege escalation. The daemon no longer accepts repair requests from untrusted clients. - macOS sandbox escape (GHSA-m4vq-qf6v-82pj, medium severity). With the Nix sandbox enabled on macOS (it’s off by default), a malicious derivation could exploit a logic error in how Nix splits up its Seatbelt sandbox policy to access every file on the host, not just its inputs and allowed impure host dependencies.
- Out-of-bounds memory access in
builtins.genList(GHSA-25vp-6h23-hj3g, medium severity). Huge arguments could overflow the list size calculation, so evaluating an untrusted expression could make Nix read, and depending on compiler optimizations write, outside the list’s allocation. - Build users could connect to the Nix daemon on macOS (GHSA-92x5-h528-wrmw, low severity).
On macOS, the daemon ignored the primary group of connecting clients, so it didn’t reject connections from members of
build-users-group, which exposed it to unsandboxed builders. This isn’t exploitable on its own, but it widens the impact of other daemon vulnerabilities. Linux isn’t affected.
OpenTelemetry tracing
Determinate Nix can now export OpenTelemetry (OTel) traces of evaluations, local and remote builds, cache substitutions, HTTP requests, and Nix daemon connections to any backend that accepts the OpenTelemetry Protocol (OTLP) over HTTP.
Traces follow operations like nix build across the Nix daemon, remote builders, and binary caches, and can join the traces your CI system already emits.
For more in-depth information on things like authentication, sampling, configuration, and trying it out locally, check out our announcement post and the OpenTelemetry for Determinate Nix documentation.
Relevant pull request
Baked flakes
Given a flake, the new experimental nix flake bake command produces what we’re calling a baked flake that includes the same flake outputs but with every derivation evaluated ahead of time.
The baked flake is essentially a flake.nix shim plus an outputs.json file listing each output’s pre-computed store paths and metadata, so commands like nix build and nix run do (almost) no evaluation at all.
To work properly, the outputs themselves must be available in a binary cache.
Here’s what baking the fh flake looks like:
nix flake bake https://flakehub.com/f/DeterminateSystems/fh/0 --dest-dir /tmp/fh-bakednix flake show /tmp/fh-bakednix run /tmp/fh-baked -- --versionUnder the hood, each baked output is a derivation with a new builtin builder, builtin:substitute, that’s never actually built.
Instead, it pulls in its output paths from a binary cache at build time.
That’s why we couldn’t use builtins.storePath or builtins.fetchClosure here: paths referenced that way become part of the closure of the .drv file itself, so Nix would substitute them at evaluation time rather than at build time.
Baked flakes require the baked-derivations experimental feature in both the client and the Nix daemon.
If you bake a large flake like Nixpkgs, we recommend passing --read-only to avoid writing hundreds of thousands of files to your store.
Relevant pull request
Garbage collector race fixes
In rare cases, the garbage collector could delete a store path while another process was still creating it.
The path stayed registered as valid in the Nix database but was missing on disk, and later garbage collections failed with errors like cannot delete path ... because it is in use by ....
The culprit was a handful of races in how Nix tracks temporary garbage collector (GC) roots, which protect the paths that a running process is still working on:
- Threads releasing each other’s lock. All of the threads in a process share one lock on the garbage collector, so one thread finishing up could release that lock while another, such as an evaluator thread, was still registering its temporary roots. A garbage collection could start in that window and miss those roots. Nix now holds the lock for the whole registration.
- Processes sharing a process ID. Nix deleted any existing temporary roots file for its own process ID (PID) on the assumption that it was stale, which is wrong when one process has several stores open or when processes in different PID namespaces share an ID. Nix now never overwrites an existing roots file, and only the garbage collector removes stale ones.
- Paths that come back to life mid-collection. If a path gains a temporary root or turns out to be in use while the garbage collector is deleting things, the collector now skips it rather than going on to delete its closure.
Relevant pull request
Parallel evaluation on fibers
Parallel evaluation now uses fibers rather than plain threads.
Previously, when a thread needed a value that another thread was in the middle of evaluating, it blocked until that value was done.
Now, the waiting work is suspended as a fiber, while its thread picks up any other fiber that’s ready to run.
Determinate Nix only starts eval-cores threads, keeps them busy, and reuses fiber stacks between tasks.
A new eval-max-fibers setting caps the number of live fibers per evaluation thread, since each one has its own stack.
It defaults to four fibers per thread, which keeps memory in check and is as fast in practice as having no limit, even on highly parallel workloads like nix search nixpkgs.
Set it lower if you need to keep your memory usage within tighter bounds.
Less lock contention in parallel evaluation
In our effort to make parallel evaluation ever more performant, we tackled the Boehm-Demers-Weiser garbage collector’s global allocation lock.
Profiling nix search nixpkgs --no-eval-cache showed that roughly 65% of all futex waits came from the garbage collector, most of them on that one lock.
Determinate Nix now avoids most of that waiting, which makes parallel evaluation faster: with 24 worker threads, nix search nixpkgs is roughly 10% faster.
builtins.fromJSON is faster now too, since it no longer waits on that lock at all.
builtins.wasm improvements
We’ve made a batch of improvements to builtins.wasm, which enables you to call WebAssembly (Wasm) modules from Nix expressions:
- A compilation cache.
Compiling a Wasm module used to take about 0.1 seconds in every Nix process that called it.
Determinate Nix now enables Wasmtime’s compilation cache, so each module is compiled once per machine and cached in
~/.cache/nix/wasmtime. - Cheaper file reads.
With the old
read_filehost function, a module had to guess how large a buffer it needed to provide, and for any file larger than the guess Nix read and copied it twice. The newread_file_v2reads each file exactly once into a buffer it allocates in the module’s memory. - Cheaper attribute set access.
Copying an attribute set into a module used to take one call per attribute, which made it quadratic in the attribute set’s size.
The new
get_attrsethost function returns all of the names and values in a single buffer.copy_attrsetandcopy_attrnamestill work but are now deprecated. - Bounds-checked memory access. Host functions now check every guest-supplied offset and length against the module’s memory, so a buggy or hostile module gets a clean “Wasm memory access out of bounds” error rather than reading or writing outside its memory.
- A fix for layered attribute sets.
Passing an attribute set produced by
//to a module that read it as an attribute set used to abort the evaluator, and now it works.
We also updated Wasmtime from 40.0.2 to 48.0.2.
Faster evaluation through the Nix daemon
When Determinate Nix evaluates derivations, its asynchronous path writer writes the resulting .drv files to the store in the background rather than making evaluation wait on each one.
It now asks the store which paths are already valid, in a single batch query, and skips writing those, which is the common case since most .drv files already exist.
It also now handles files created with builtins.toFile, which NixOS evaluations produce thousands of times over (one NixOS evaluation instantiated the same write-text-file.kaem file 5,279 times), and it skips any file that’s already queued.
Each of those writes used to cost a synchronous round trip to the Nix daemon.
Together, these changes cut nix flake show on a flake with three NixOS configurations, evaluated through the daemon, from 12.8 seconds to 8.5 seconds.
Building Nix with Nix
As an experiment, Nix can now be built with Nix itself as its C++ build system, in place of Meson and Ninja.
Every compilation unit is its own derivation, so you get incremental rebuilds, ccache-like sharing of build results, and substitution and remote building of individual compilation units, with no development shell or build directory to fall out of sync.
This works without import from derivation.
A dependency scanner written in Rust runs under builtins.wasm to compute each compilation unit’s #include closure at evaluation time, and tracks which configuration macros each unit uses, so a unit is only rebuilt when something it actually depends on changes.
A cold evaluation of the nix derivation takes about 1.2 seconds.
To try it out, run this from a checkout of Determinate Nix’s source (Linux only for now):
nix build ./packaging/nix-make#release.nixThe eval cache pays off on the second run
A bug caused the flake evaluation cache to be written incompletely on the first run, so you didn’t get the benefit of caching until the third run. That’s fixed now, and the second run is fast.
Relevant pull request
Faster tarball unpacking
When you fetch a tarball input, whether that’s nixpkgs.tar.gz from a mirror or a tarball+file:// archive on disk, Determinate Nix unpacks it into a bare Git repository under your cache directory (the tarball cache) so that later fetches of the same archive happen instantaneously.
Previously, writing that unpacked tree meant asking libgit2 to build a packfile, and libgit2’s pack builder does what Git does by default: it searches every object in the pack for other objects it could store as a delta against.
That search is the slowest part of building a pack, and for the tarball cache it doesn’t save much space.
Determinate Nix now tells libgit2 to skip delta discovery entirely for the tarball cache (pack.window=0, set through an in-memory configuration so your on-disk Git config is untouched).
It also turns off libgit2’s strict hash verification, which rehashed every object on every read, in line with how the Git CLI behaves and how Nix already trusts store paths without recomputing their NAR hash.
Running nix flake info against a local Nixpkgs tarball with a cold cache dropped from about 3.7 seconds to 2.3 seconds.
The same change prepares Determinate Nix for the upcoming libgit2 2.0 release, including repositories that use SHA-256 object IDs, and carries two small libgit2 patches so that the pack builder actually honors pack.window (and reads core.bigFileThreshold from the right key) rather than ignoring both.
Relevant pull request
Cheaper repeat fetches of Git repositories
Nix keeps a shared Git cache for the repositories it fetches, so that fetching a second revision of a repository only needs to transfer the objects the cache doesn’t already have.
That negotiation only works if Git can find the earlier rev in the cache, and for rev-pinned fetches (rev= in a flake input, or a builtins.fetchGit call with a specific commit) it couldn’t.
Rev-pinned fetches now record what they fetched under an internal ref, bucketed into 256 slots by the first two hex characters of the rev, so that unrelated revs mostly don’t evict each other’s tip the way a single shared ref would.
A second fetch of a different rev of a large repository dropped from about 89,000 objects transferred to about 9,000, and a sequence of six revs of the same repository left the cache about 63% smaller.
Ref-based fetches (ref=main and friends) are unchanged.
Relevant pull request
Submodule inputs locked with Nix < 2.20 evaluate again
Nix 2.20 changed how Git inputs are exported: it stopped applying Git’s text and eol filters, export-ignore, and export-subst, which changes the NAR hash of any repository that uses them.
To keep older lock files working, Nix hashes the tree both ways when a locked narHash doesn’t match the modern export and, if the legacy export matches, warns you to update the hash rather than failing.
For Git inputs with submodules = true, that fallback never worked.
Nix compared the two candidate hashes before mounting the submodules, while the locked hash covered the fully assembled tree, so neither candidate could ever match and you got a hard NAR hash mismatch error instead of the warning.
It was easy to miss because nix flake update <input> recomputes the hash rather than checking it, so the lock changed quietly for whoever touched the input next and failed for everyone else.
The same failure hit lock files written with nix-219-compat enabled, since that setting only ever governed the write path.
Determinate Nix now mounts submodules into both candidate trees before comparing hashes, and exports the submodules with the same semantics as their parent, so a Nix < 2.20 hash can actually be reproduced. The existing cache keys are unchanged, so nothing you’ve already fetched needs refetching. Thanks to @joshuaspence for tracking this down and contributing the fix, along with a regression test that covers both directions. This is their first contribution to Determinate Nix.
Relevant pull request
Zero-copy file copying
Nix now uses copy_file_range when it copies whole files out of the store, such as when it copies fixed-output derivation outputs.
On filesystems like ZFS and Btrfs, that lets the kernel clone blocks rather than read and write every byte through Nix.
Building a simple fixed-output derivation with a large output on a ZFS-backed store, the change eliminated 61,730 write calls, replacing them with a single copy_file_range.
System time dropped from 7.27 seconds to 3.80 seconds, and wall clock time from 14.47 seconds to 13.32 seconds.
On filesystems and platforms without copy_file_range support, Nix falls back to an ordinary copy automatically.
Relevant pull request
Cheap, non-blocking purges of the binary cache metadata cache
Nix caches the metadata it fetches from binary caches (.narinfo files) in a local SQLite database under ~/.cache/nix.
On busy builders that database can grow to millions of rows and several GiB.
Once a day, Nix purged expired entries with a full table scan that could hold the database’s write lock for over two minutes, blocking every concurrent nix copy.
And if something killed the purging process, the next one started the scan all over again.
Three changes fix this:
- An index.
The purge is now two index range searches rather than a table scan.
On a synthetic cache with 1.5 million rows and 3 GiB of data, the purge now reads under 100 MiB from disk rather than about 3 GiB.
To pick up the index, Nix starts a fresh
binary-cache-detsys-v4.sqlitedatabase rather than building the index in place on an existing multi-gigabyte one, which would itself hold the write lock for a full table read. - Small chunks. Nix purges 1,000 rows per transaction, so other processes wait a few hundred milliseconds at most, and a purge that gets killed keeps the progress it’s already made. The next process to open the cache picks up where it left off.
- One purger at a time. When several processes start at once, they all used to see the purge as due. Now only one of them purges, and the rest skip it: in testing, eight simultaneous processes produced one purge and seven sub-second skips.
Relevant pull request
Better nix profile history
nix profile history used to report “No changes” when a package was replaced by a different store path with the same version, which is what happens when a package is rebuilt because its source or one of its dependencies changed.
It now prints a changed line in that case.
The command also has a new --show-source flag that shows the locked flake reference of each package that was added, removed, upgraded, or changed:
nix profile history --show-sourceVersion 59 (2026-10-05) <- 58: github:NixOS/nixpkgs#legacyPackages.x86_64-linux.hello: 2.12.2 changed (github:NixOS/nixpkgs/6fd8c75 -> github:NixOS/nixpkgs/ffc5e35)Relevant pull request
Memory and I/O statistics for builds
With the use-cgroups setting enabled, Nix runs each build in its own Linux control group (cgroup).
Until now, those per-build cgroups only exposed CPU statistics.
The Nix daemon now enables the cpu, memory, io, and pids controllers in its own cgroup, which means that each build’s cgroup also exposes memory.peak, io.stat, and memory.events.
That can be handy if you run a CI system and want to measure how much memory and disk I/O each build uses.
The controllers need to be delegated to the daemon’s cgroup, for example with Delegate=yes in its systemd unit.
If some of them aren’t available, the daemon enables the ones that are and logs a warning rather than failing.
Thanks to @DerDennisOP for contributing this change to upstream Nix.
Relevant pull request
Better handling of interruptions and memory exhaustion
- Ctrl-C works reliably with crash reporting enabled.
With Sentry crash reporting enabled, Ctrl-C often killed Nix instantly, with no
error: interrupted by the usermessage and a hidden cursor left behind in your terminal. Sentry’s worker threads started before Nix blocked interrupt signals, so the kernel could deliver your Ctrl-C to one of them rather than to Nix’s signal handler. Nix now starts Sentry afterwards, so interrupts always reach the handler and Nix shuts down cleanly. - Interrupting garbage collection no longer takes down the daemon. If you interrupted a garbage collection while a client was connected to the GC roots server, the Nix daemon aborted. The daemon now logs the interruption and closes that client connection cleanly.
- A clear message when Nix runs out of memory.
Running out of memory used to produce an opaque
SIGABRT. Nix now prints a proper error message when an allocation fails and exits with status 12, so crash reporting no longer treats running out of memory as a crash.
Bug fixes
Thanks to crash reporting, we tracked down and fixed a batch of rare failures in 3.23.1 through 3.23.3, several of them in code that’s new in 3.23.0:
- Heap corruption in
builtins.fromJSON. A garbage collection in the middle of abuiltins.fromJSONcall could free a value that the parser was still using, which led to crashes, wrong evaluation results, and deadlocks, mostly with parallel evaluation. This was the root cause of a cluster of crash reports fromnix search,nix flake show, andnix flake checkgoing back to 3.22.3. In a stress test that ran many small parses on 16 evaluation cores across 16 concurrent processes, Nix failed 71 times in fewer than 100 runs before the fix and 0 times in 100 runs after it. - Crashes on exit. Nix and Nix daemon workers could crash on exit because static destructors ran while other threads were still using the objects they destroyed. Nix now releases resources like SQLite databases, temporary roots, and child processes up front and then exits without running those destructors.
- Reused connections to the GC roots server. If a client disconnected from the garbage collector roots server right after connecting, a later client that reused the same file descriptor could make the Nix daemon abort.
- Dynamic attribute errors with parallel evaluation.
With
eval-coresset above 1, a failing attribute selection likea.b.${name}could abort with an assertion failure while Nix built its error trace. - Substituting during evaluation without a daemon.
When a nested data stream (like decompressing a NAR fetched from a binary cache) ran inside the evaluator process, the garbage collector could scan the wrong stack and segfault.
This only affected setups without a Nix daemon, such as single-user installs and root in containers, running
nix flake checkwith import from derivation or substitutable inputs. - Concurrent
builtins.getFlakecalls. Multiple evaluation threads callingbuiltins.getFlakeon the same flake at the same time could segfault because of a data race. nix flake check --keep-going. A failing check could makenix flake check --keep-goingabort while it was reporting a cached evaluation error.- Killing the build hook. The Nix daemon could terminate when the build hook was killed while the worker was being interrupted. This also fixes an uninitialized kill timeout and a case where the timeout thread could signal every process the daemon was allowed to signal.
- SQLite on ZFS.
Nix’s workaround for SQLite’s shared memory file on ZFS reopened that file every time Nix opened a database, which could drop locks held by the same process’s other connections and lead to a
SIGBUSin the daemon. The workaround now only runs on the first open of each database. - Extremely long flake references.
Parsing an extremely long installable, like
nix path-info "$(cat paths)"with many store paths in a single argument, overflowed the stack. Nix now parses flake references with a regex engine that keeps its state on the heap. - Shell completion with a closed pipe.
Shell completion could abort with a
Broken pipeerror if standard output was already closed. nix store info --jsonwith an unreachable store. If connecting to the store failed and printing the result then failed too, for example because standard output was a closed pipe, Nix aborted. It now reports the connection error and exits with the same status as before.- URLs without a scheme.
Commands like
nix-prefetch-url fooaborted, and now they fail witherror: URL 'foo' doesn't have a scheme. - A build users group with group ID 0.
If
build-users-groupresolved to a group with group ID (GID) 0, or a build user had user ID (UID) 0, Nix aborted on an assertion when starting a build. That’s now a proper configuration error. - Garbage collector statistics with a closed standard error.
With
GC_PRINT_STATSset and standard error closed, Nix aborted at startup. - Quitting with
SIGQUITon macOS. Crash reporting no longer treats quitting Nix with Ctrl-\ (SIGQUIT) on macOS as a crash. - Stray
.cache/nixdirectories. With$HOMEset to an empty string, Nix created.cache/nixin the current directory on every run (owned by root, if Nix ran as root). Nix now ignores empty or relative values of$HOME,$XDG_*_HOME, and$NIX_*_HOMEand falls back to the defaults. If you set a$NIX_*_HOMEvariable to a relative path, note that Nix now ignores it.
3.23.1 also picks up fixes from the upstream Nix 2.35 maintenance branch: correct store timestamps in installer tarballs, x86_64-darwin as an extra platform on Apple silicon systems with Rosetta 2, and nix flake prefetch-inputs skipping relative path inputs.
Relevant pull requests
Determinate Nixd changes
These Determinate Nixd releases make the daemon’s logs more useful, its tracing leaner, and its error messages more helpful.
Determinate Nixd logs the cause of an HTTP 500. When a request handler in the daemon’s HTTP API failed, the error went into the response body and nowhere else, so the daemon log showed nothing about what went wrong. The daemon now logs the error with its full cause chain.
Determinate Nixd records less in its tracing spans.
The daemon no longer records a netrc login token or the contents of its certificate trust store as span fields, and it no longer opens a span for trivial operations such as integer arithmetic and formatting a value for display, which could re-enter the tracing subscriber from inside itself.
Determinate Nixd tells you how to get Native Linux Builder working.
When Native Linux Builder wasn’t available, Determinate Nixd told you to contact support.
Since the usual cause is that you’re not logged in to FlakeHub, it now tells you to run determinate-nixd login and points you to the troubleshooting guide.
Smaller improvements
- No more duplicated
nix buildoutput. Passing the same installable more than once tonix build --print-out-pathsprinted its output path n² times rather than n times, and the same blowup showed up in--jsonoutput and--out-linknumbering. You now get exactly one result per installable, in command-line order. The build itself was never duplicated, only the results. netrc-filereaches the daemon again. Thenetrc-filesetting was no longer forwarded to the Nix daemon, and now it is.dirworks innix-219-compatmode. Flake references with adirparameter, likegithub:NixOS/nix?dir=perl, failed to parse withnix-219-compatenabled. They now parse correctly, and a flake reference with an unknown parameter now produces an error that names the parameter.- An atomic schema file. Nix now updates the store’s schema file atomically, so a system crash in the middle of a write can’t leave it corrupted.
- Narrower
nix copychange for older daemons. In 3.22.2, we stopped registering temporary GC roots when talking to daemons that can’t register them in a batch. That change applied more broadly than intended, so Nix now skips those roots only while runningnix copy. - Building Determinate Nix in a hardened CI sandbox works again.
The Sentry crash reporting test in our functional test suite needs
ptraceto capture a crash dump, and on hosts where the Yama security module restricts it (ptrace_scope=2, as on Talos Linux) the test failed every time. It now skips itself when a crash dump can’t be captured, matching how Sentry’s own client library behaves. Thanks to @Reasonable-Solutions for the fix, their first contribution to Determinate Nix. - No more
fsyncat the start of every build. Nix used to flush the file that marks a build as active to disk before it started reading the builder’s output, which forced a full device cache flush on macOS and could take a long time on slow storage. That flush bought nothing, since Nix discards stale build files after a crash anyway, so the build now starts without it. Thanks to @Jesssullivan for the fix, their first contribution to Determinate Nix. - A visible wait on store path locks.
When another process is substituting or adding the same store path, Nix now shows
waiting for lock on '/nix/store/...'in its status line, rather than a download that looks stalled at 0 bytes. - Daemon activities in JSON logs.
Activities that the Nix daemon performs on your behalf, such as substitutions, now include their names and metadata in
--log-format internal-jsonandjson-log-pathoutput, just like local activities already did. This requires both the client and the daemon to be on 3.23.3 or later. - Bash completion after redirections.
Tab completion now works after a redirection, as in
nix nario list < /tmp/system-exp<TAB>. - Fewer temporary directories for SSH stores.
SSH stores now only create a temporary directory when they need one, for an SSH master’s control socket or a known hosts file, which most
ssh://stores don’t.
Relevant pull requests
How to get Determinate Nix
If you already have Determinate Nix installed, you can upgrade to 3.23.3 with one Determinate Nixd command:
sudo determinate-nixd upgradeIf you don’t yet have Determinate Nix installed, you can upgrade or migrate to Determinate Nix on macOS using our graphical installer:
Install Determinate Nix on macOS
With support for Apple Silicon (aarch64-darwin)
On Linux:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | \ sh -s -- install --determinateOn NixOS, we recommend using our dedicated NixOS module or our NixOS ISO (NixOS installer for x86_64, NixOS installer for ARM) with Determinate Nix pre-installed.
On GitHub Actions:
on: pull_request: workflow_dispatch: push: branches: - main
jobs: nix-ci: runs-on: ubuntu-latest # Include this block to log in to FlakeHub and access private flakes permissions: id-token: write contents: read steps: - uses: actions/checkout@main - uses: DeterminateSystems/flake-checker-action@main with: fail-mode: true - uses: DeterminateSystems/determinate-nix-action@v3 - uses: DeterminateSystems/flakehub-cache-action@v3 - run: nix flake checkIn Amazon Web Services:
data "aws_ami" "detsys_nixos" { most_recent = true owners = ["535002876703"] # Commercial # owners = ["579351485434"] # GovCloud # owners = ["129194717446"] # European Sovereign Cloud
filter { name = "name" values = ["determinate/nixos/epoch-1/*"] }
filter { name = "architecture" values = ["x86_64"] }}Written by
Graham is a Nix and Rust developer with a passion and focus on reliability in the lower levels of the stack. He is a co-founder of Determinate Systems, alongside Eelco Dolstra, as well as its Chief Technology Officer.
