Skip to content

recursive-nix

Overview

The recursive-nix experimental feature allows derivation builders to invoke Nix during a build, so a build script can recursively build other derivations. That breaks the usual separation between evaluation (which produces .drv files) and realisation (which runs builders), and is useful for advanced packaging patterns where the set of sub-builds depends on intermediate build results.

Version stamp: As of the Nix 2.34.x stable reference manual (nix.dev/manual/nix/stable/ → 2.34; title 2.34.9), recursive-nix remains experimental (manual example and substitution restriction unchanged relative to the flag entry; local Nix 2.34.8). Behaviour and restrictions may change. Enable it explicitly (Feature Flags Overview); track stabilisation in Tracking Stabilization and the recursive-nix tracking issue. For a related but distinct capability (derivation outputs whose identity is not fully fixed at eval time), see dynamic-derivations.

Details

What the flag enables. With recursive-nix on, a builder may run nix-build, nix build, or similar inside the sandbox. The derivation should declare the need via requiredSystemFeatures = [ "recursive-nix" ] (optional but recommended—the 2.34 manual marks it as letting Nix know the build requires the feature / a builder that advertises it). The builder typically needs nix (and often NIX_PATH or flake inputs) in buildInputs.

Substitution restrictions. Recursive builders may not pull arbitrary store paths via substitution. For example, running nix-store -r on a path that is neither already in the derivation’s build inputs nor produced by an earlier recursive Nix call in the same build is disallowed. That prevents hidden dependencies and store-state-dependent builds that would break reproducibility. Paths already listed as inputs, or built earlier in the same recursive session, are permitted.

Background concepts. Static derivation structure and .drv files are in Derivation. How builders run inside sandboxes is in Builders and sandboxes. How substitution works—and why uncontrolled -r is risky—is in Substitutes and narinfo.

Examples

Enable in nix.conf (Nix 2.34.x; still experimental):

extra-experimental-features = recursive-nix

On multi-user installs, the daemon (and any remote builders) must advertise / allow the feature for scheduled builds; client-only flags are not enough for realisation.

Minimal recursive build (from the Nix 2.34 experimental-features manual; requires <nixpkgs> on NIX_PATH):

with import <nixpkgs> {};

runCommand "foo"
  {
    # Optional: let Nix know "foo" requires the experimental feature
    requiredSystemFeatures = [ "recursive-nix" ];
    buildInputs = [ nix jq ];
    NIX_PATH = "nixpkgs=${<nixpkgs>}";
  }
  ''
    hello=$(nix-build -E '(import <nixpkgs> {}).hello.overrideDerivation (args: { name = "recursive-hello"; })')

    mkdir -p $out/bin
    ln -s $hello/bin/hello $out/bin/hello
  ''

The inner nix-build is allowed because it goes through Nix’s recursive-build machinery. Calling nix-store -r /nix/store/…-hello-2.10 on a path not already in buildInputs or from a prior recursive call in this script would be rejected (manual’s concrete hash is illustrative).

References

See also