~/ ~/documents ~/harmful.txt github

Environment Variables are Impure

The builtins.getEnv nix function returns the value of an environment variable as type string:

IMPURE="foo"  nix-instantiate --eval -E 'builtins.getEnv "IMPURE"' # outputs "foo"
Environment variables are impure as their values are non-deterministic and always produce build artifacts that are considered non-reproducible when depended upon. Only use them when absolutely necessary.

Note that the value returned by builtins.getEnv will always be equal an empty string when evaluating in certain contexts, such as nix flakes as by design they are pure and reproducible, and thus do not have access to any state outside of the sandboxed environment.

It may sometimes be necessary to depend upon an environment variables value within a the context of a flake:

{
    inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";

    outputs = { self, nixpkgs }: {
        packages.impure = nixpkgs.legacyPackages.x86_64-linux.stdenNoCC.mkDerivation {
            name = "env-var-example";
            buildPhase = ''
                echo ${builtins.getEnv "IMPURE"} > $out
            '';
        };
    };
}

In such cases, pass the --impure flag to allow for impure evaluation of the expression:

IMPURE="foo" nix build .#impure && cat result # outputs ""
IMPURE="foo" nix build .#impure --impure && cat result # outputs "foo"

The explicit use --impure the flag is to be considered a safety mechanism to prevent accidental dependencies on non-deterministic environment variables values. Hence, providing flakes an advantage over tradition Nix expressions in this regard.