Nix-channel: forcing an update

Hi, I am not sure this is the right place, but I wanted to mention there is no documentation on how to force nix-channel to update all channels even when the channels have been recently updated. There is also no documentation on how long the channel cache lasts for before being updated, or that channels are cached in the first place (at least on the nix-channel documentation page).

One use case worth documenting for is perhaps you have a development branch channel that you want to consume. You add a commit to test how it would install/run on a NixOS system, then try to run sudo nix-channel --update. However, you have recently run that command, so the channel is not updated and sudo nixos-rebuild does nothing.

If that is not a use case for nix-channel, then maybe that should be documented as well, pointing to the proper tool.

Anyway the workaround I found was to run these commands:

sudo nix-channel --rollback # optionally add number of arbitrarily old enough generation
sudo nix-channel --update   # this now works

If there is a better way to dogfood nix packages in a non-flake nix system config I’d love to know. This is how I tested this package properly installed and run (as a new contributor), and also how I applied patches like this one to test before contributing them to upstream LegendsViewer-Next.

As an aside, is there a reason why channels are cached without checking that refs haven’t been updated? Is it a bandwidth reduction issue?

Hi @donttellmetonottellu, have you tried setting --tarball-ttl 0? I haven’t used nix-channel in a long time, so all documentation there amounts to manual testing and code archeology (writing extra tests for such cases is often not worth the effort, the framework is rather cumbersome to use).

Working with remote sources declaratively in stable Nix can be done e.g. with npins: Automatically managing remote sources with npins — nix.dev documentation

It’s a common misconception that it’s “flakes vs channels”. Flakes are about multiple things, source management is just one of them, and nix-channel with search paths is not the only way to do that in stable Nix:

https://nix.dev/reference/pinning-nixpkgs

The confusion for NixOS users stems more from the fact that nixos-rebuild obscures the evaluation entry point and thus strongly nudges you to inject source references at the call site or some other side channel rather than specifying them in the Nix expression that invokes your configuration. The flakes variant simply doesn’t do that, but that has nothing to do with flakes per se (except there’s no other way with flakes, because they are mandatory pure).

2 Likes

Thanks, this is what I needed. I had forgotten about that option.

That’s the problem, I don’t want it to be that pure. I want to be able to imperatively say fetch the latest updates for my system. I also don’t like encouraging a culture of I don’t update my system because updates may break my configuration, especially on stable (which is where I am). I thought that was one thing nix was supposed to solve!

/siderant

nix rebuild

I am not against using flakes. I think they are very useful for dev environments, or reproducible dev builds, etc. I just don’t want anything to do with my system configuration potentially relying on something that I forgot and now doesn’t get security (or any) updates, and eventually breaks due to the impure ways packages communicate with each other and the outside world (which nix will never solve). It is also extremely useful to have one command be the one true source of truth when it comes to the current input state of your system, rather than having to hunt through potentially dozens of flake.lock’s (or figure out how to unify them somehow). I already spent enough time figuring out a workflow for editing my system configuration (because by default that is very difficult to do and setup with version control). I don’t need flakes to complicate things further.

I'll go there anyway

Also, it seems that nix-channel (and nixos-rebuild --update-all) is the only way to get updates on your system like a regular Linux distribution. This is an essential feature of a self-respecting non-LFS Linux distribution, not “legacy code”. I would not use NixOS as my daily driver if I had no easy way to update my system with one command. Nix’s biggest problem is accessibility to new users, removing this in some future version or allowing it to bit rot will only close the door on any potential new users without esoteric use cases. Reproducible systems should be the standard, not a weird quirk. And NixOS will lose a race it is already ahead in against e.g. Ubuntu (Core) if they make simple things harder for new users. Updates always have been and always will be by-default imperative (or even non-interactive). Even if you built your system using only flakes (somehow), only the truly insane would use declarative programming by manually editing flake.lock’s: instead using nix flake update, which is both imperative and impure. A feature should not be progressed towards if it realistically has little real world use cases, and conversely a feature that is needed and common should be well documented and maintained. Otherwise what’s the point of NixOS other than as a reference distribution (like KDE Neon).

I think the nix definition of “pure” has strayed from the original definition of pure functions (according to Wikipedia):

  1. the function return values are identical for identical arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams, i.e., referential transparency), and
  2. the function has no side effects (no mutation of non-local variables, mutable reference arguments or input/output streams).

Of course, we must note that I/O streams in this case are part of the purity, due to the architecture of NixOS, and are not a required part of “purity” (or at least I’ll allow it, otherwise nix is fundamentally “impure”).

nixpkgs supported by blood and github

I don’t see channels as causing impurity or irreproducibility. You could control those “arguments” to get the same, reproducible result, although there is a lack of tooling to make that easy. It is true that they aren’t defined by “parameters” in the same sense that arguments to { ... }: are, but rather more similar to how modules work they are like library imports (mod rust_module; or import defaultExport from "module-name";, or using System;. The lack of such features hasn’t historically defined a “functional programming language”. It is assumed that if you update Haskell (or a Haskell library) you may get a different result in the same pure function, which may or may not be considered a bug depending on the project goals and semantic versioning. The claim of pure functional languages is not that the same code will do the same thing through all versions of the language, rather that on a specific version the code will do the same thing all the time. And even if it was insisted that the channels are non-local variables, they are not mutated. And the system is reproducible, given the same system channels.

nix language description

That is not to say that mitigating the effects of language updates is a bad thing, I recognize the effort to create a translational layer for nix that is used in derivatives, and think it is great that nix 2.1 does the same thing with the same inputs as nix 2.99 (hopefully). But the “standard library” (nixpkgs) is a whole different animal, and has no such guarantees.

general mills nix flakes

It would have been nice if flakes had leveraged the existing way that nix functions worked, instead of creating a new DSL to (learn and) work with that is incompatible with nix-channel. Then instead of being a hacky attribute set with inputs and outputs, a flake.nix could be fed inputs in the same way as a configuration.nix, and be a proper nix function instead (and have the ability to define imports), with the same predefined inputs determined by the flake.lock. Channels could be both defined by a flake.lock and by a system’s global channels. nix channel would be a new subcommand that would work with both system and flake channels. Instead of everyone using flake-utils, a nixpkgs argument would have built-in tools to enable system-specific configurations, and in general the standard library would be more complete for flake usage. Then we would have all the same features as core nix, in flakes. It would feel more nix-like, less people would be upset and confused, and everything would be rainbows and sunshine. LOL. Oh well. History is history.

nix-shell-env

Finally, there is no such thing as a pure development shell, which is what flakes are used for quite often (and what I use it for). You cannot guarantee that you won’t have an “it works on my system” problem if you ever allow that use case. Because of that, development flakes are no more pure than a shell.nix.

2 Likes

Not at all, and no one would ever make such a guarantee. Nix is meant to ensure that all the dependencies are specified correctly, but it’s not going to handle data migration or configuration migration for your NixOS system.

Software upstream of NixOS changes, we would never guarantee that your config from today will work 6 years from now unless you use the exact same nixpkgs revision in both cases. (And even then, some software sources might disappear making some packages unbuildable.)

nix flake update && sudo nixos-rebuild switch

(or boot and reboot, which’d be safer in some cases).

That’s the whole reason to not use channels. Although flakes get you the same inputs, and nixpkgs sort of half-tries with reproducible builds, claiming reproducible deployments on a desktop system would be nonsensical, unless it’s a highly controlled environment where all the data can be wiped (e.g. school workstations). So let’s be clear that in the kinds of use cases most of the casual users are talking about, NixOS will never have reproducible deployments, as there’s too much outside of NixOS’s control.

But you fundamentally can’t even approach reproducibility of any useful kind without declarative systems. That’s why nix-channel sucks.

Not at all, the input is declared with your config, that’s how lockfiles work in programming languages. If you’re looking for semver, that’d be the one thing nix is missing.

Yeah, “pure” devshells are stupid, the point of using flakes here would only be to ensure it’s the same nixpkgs revision used for both development and build/deployment.

1 Like

I appreciate your respectful response, as it is useful for learning a flake user’s perspective. I do have a few things to respond to.

On stable, changes should not be breaking. And plenty of distros make that guarantee, less security fixes, on stable releases. I only have to worry about breaking changes twice a year, which is great (and has been true for the 3 releases I’ve been through). Of course, the stability guarantee is not actually controlled directly by the language, but rather maintainer policies and testing. However the systems in place do a good job of rarely breaking things that don’t break themselves from not being updated. Apparently using stable makes you the weird one, though.

I was that guy that used Debian because he didn’t like being spammed with non-security updates.

I really wish there was a nixos-stable branch (not channel, that wouldn’t make sense), just so that it would be possible to get that stability guarantee on flake updates (less the twice-a-year releases) without having the issue of breaking nix flake update when the current stable is depreciated.

No, I agree, but that’s why I use stable. Nobody seems to appreciate the fact that stable is, well, stable! It solves the problem that pinning a specific version of nixos-unstable does, without locking you in a specific version and potentially being a security problem. Of course, stable is only maintained for ~7 months, but that is fine, assuming there is an easy way to update to the next stable (which there isn’t really). You can deal with breaking changes twice a year at most and that’s not a huge problem. I actually quite love the fact that stable releases twice a year, as opposed to Debian’s once every two years
 which is not really viable for a desktop. I do think occasional LTS releases would be a good idea, if only we had the funding.

The problem I had, as a new nix user, is that I started with a NixOS system. I didn’t try the package manager first, I just dove right in. So whenever I looked up how to do something, as flakes are not first class citizens in NixOS, I always ignored the “flake version” and was extremely frustrated when there was no traditional configuration in the examples. The reason for this, was that I was already rawdogging the NixOS system, and spending hours finding solutions that would involve one web search and command on Debian/Manjaro/OpenSUSE, so I wasn’t interested in even trying to figure out how to use flakes at all. They looked like an extension to the language, not a required part, and the syntax was already esoteric enough without adding flakes’ magic attributes and DSL. And trying to use the flake version of every package would probably require dozens of hours of prerequisite learning.

As it is, I still have absolutely no idea how a “flake system” would even work, and that’s after over a year of using NixOS as my daily driver. That command means nothing to me because I don’t know how to hook the flakes up in the first place.

That’s why I want a nix channel command with those quirks ironed out. Channels do not need to be limited to channels.nixos.org. In fact, I don’t only use channels.nixos.org. I use home-manager and a custom nixpkgs for testing. You could pull directly from the git repository, or even a specific git commit. And since the channels are mirrored in the git repository, you could reproduce a person’s entire system from the channels, if only nix-channel provided a way to get the specific git revisions and simply print them out. channels.nixos.org already provides that information, ex: https://releases.nixos.org/nixos/25.05/nixos-25.05.802746.7282cb574e06/git-revision.

The command itself is not pure, because it does not follow the first point in the definition. If you run nix flake update, you will get different lockfiles at different times.

Sure, the flake itself, including the lockfile, might be pure: but not the command that creates the lock. That is the point I am making about channels, they have the potential to be just as reproducible as flakes. All you’d have to do is create a command like nix channel lock export to export a channels.lock and nix channel lock import for importing the lockfile. The information for rebuilding the channels is already in the nixpkgs repo. You could also add the lock output to the nix-info command. And if there is a backwards-compatible way to introduce a feature, why not? Why completely reinvent the wheel?

What I am looking at, from an engineering/architectural standpoint, is that I don’t see how a domain specific language was necessary in the first place (it is probably bad practice to reach for a DSL first when you have control of the language, especially from the perspective of language servers). I think that these features should have been properly RFC’d and introduced into core nix as optional features in a backwards-compatible way, instead of creating a walled garden where flakes are completely incompatible with regular nix expressions. And also perpetually “experimental” because of the controversy. It was frustrating for me as a new nix user, and it still frustrates me now, even though I at least somewhat understand the flake syntax now (I still haven’t made much use of them).

Also, the main use I have for flakes is reproducible (cross-)compilation, but I haven’t had much luck figuring that out.

2 Likes

I’m not super interested in re-litigating the past, but if you want practical non-flakes solutions they exist, just not in the official project. Here is a nicely written up example of such a workflow. I have a very similar setup, and I nh with a shell abbreviation to make it pleasant

programs.fish.shellAbbrs."nos" = 
  ''nh os switch -f '<nixpkgs/nixos>' -- -I nixpkgs="$(nixpkgs-path-with-eval)"'';

and nixpkgs-path-with-eval is morally

nix eval -f - <<< '"${(import ./npins).nixpkgs}"' | jq -r .

which hopefully will be simplified in a future npins release. This allows me to follow the 25.05 branch and enjoy stability and reproducibility without needing all of flakes, while having a nice nom-enabled update workflow.

2 Likes

Well, I wasn’t a nix user when “the past” happened. So I don’t really care all that much. I’m fine with things as they are, but being able to criticize the current system without starting a flame war is important for the health of any project.

I’m not anti-flake, I am writing one now (or trying anyway). Regardless of if it could have been done better or not, it exists, and is the current best way AFAIK to build packages outside of nixpkgs.

I like the idea of nh, I already implemented my own shell scripts to use nom under the hood lol!

Back on topic


The original problem brought up in this thread was the lack of documentation of tarball caching in key legacy nix commands, such as nix-channel and nixos-rebuild. I’d simply like a mention in the command documentation that updates are not guaranteed to happen without --tarball-ttl 0. nix-channel is still the default in NixOS, so this should be documented for new users.

1 Like

Not at all. We’re just quieter because we have fewer problems. :wink:

4 Likes

And they aren’t, except for security fixes and honest mistakes. Never claimed otherwise. Not sure what magic you expect from the language, in every distro stability is a promise kept via maintainer policies.

Contradictory with the prior point, unless we introduced a separate subcommand to nixos-rebuild to cross release boundaries.

nix flake update is just “fetch me the latest update that matches this refspec” modulo tarball-ttl. That’s not fundamentally a flakes problem though nor do I see why that’s a weakness of flakes. An update command being “pure” makes no sense because you’re fetching something outside your code to get the latest updates. So no kidding, the update command is impure, in every language imaginable.

Sure you could design a lockfile that doesn’t require a flake.nix, and it’s been done with npins and whatnot. In fact if I could get past my c++ skill issue and patch (n/l)ix to use pure eval (not the copying-to-store nonsense but some saner mechanism that only looks at the files withon your project) outside of a flakes context, I would 100% do so.

Pull request with a change to this file appreciated! Ping me for a review.

If I understand your desired user experience correctly, you may want to try the following setup. It will always build the latest version of the stable release you specify. This code is tested and should work as is with your configuration.nix.

Assuming you use Bash or Zsh, try it out with $(nix-build -A run-vm). When you’re happy, no need to run nixos-rebuild, just do $(nix-build -A nixos) switch.

let
  pkgs = import (fetchTarball "channel:nixos-25.05") { };
in
rec {
  eval = pkgs.nixos ./configuration.nix;
  nixos = pkgs.writeShellApplication {
    name = "switch";
    result = eval.config.system.build.toplevel;
    text = ''
      nix-env -p /nix/var/nix/profiles/system --set "$result"
      exec "$result"/bin/switch-to-configuration "$@"
    '';
    derivationArgs = {
      inherit postCheck;
    };
  };
  run-vm = pkgs.writeShellApplication {
    name = "run-vm";
    text = ''
      # let QEMU create the disk image in memory
      cd "$(mktemp -d)"
      # always clean up
      trap 'rm -f nixos.qcow2' EXIT
      "${pkgs.lib.getExe eval.config.system.build.vm}" "$@"
      # clean up the terminal, useful when running with `-nographic`
      reset
    '';
    derivationArgs = {
      inherit postCheck;
    };
  };
  # this allows running e.g. `$(nix-build -A run-vm)` directly
  postCheck = ''
    mv $out/bin/$name /tmp/$name
    rm -rf $out && mv /tmp/$name $out
  '';
}
2 Likes

I don’t expect any, my point was about reproducibility via pinning unstable vs reliability in using nixos-stablebranch and updating. I was just trying to explain that I prefer traditional maintainer-guaranteed stability over 100% stable but potentially insecure pinned unstable releases.

Everyone seems to have different definitions and preferences of stability/reproducibility/purity

As a flake target: it would be useful to know that updating your flake won’t usually randomly break, but only when you are updating across release boundaries. nixos-stable might not be a good name for it, maybe. But the idea is to have a branch that always points to the latest stable. Think how e.g. pkgs.winePackages.stable works. Maybe nix flake update or nixos-rebuild --update could warn and require user input if the underlying branch was changed, say from 25.05 → 25.11. IDK, it’s just annoying that NixOS and flakes don’t have an easy way to say “update to the next stable release” without manually editing the file. Which is not great when sharing flakes, because a consumer of a flake targeting stable written in 2023 would have to edit the inputs in 2025 to get the flake working again. That’s probably one reason why shared flakes almost always target unstable.

The point I wanted to make is not that it is uniquely a flakes problem/weakness, only that a lot of people seem to think that flakes solve that problem, and that flakes were the only way to solve it. nix-channel could easily have been (and still could be) updated to support importing and exporting lock files, and that would solve the system channel reproducibility problem without any backwards-incompatible additions.

What I’d prefer is a universal lock file format that is supported (can optionally be used) by shell.nix, configuration.nix (through channels), and flake.nix, that is in upstream nix and is actually agreed on by everybody, maybe called something like nix.lock. Nobody is contesting (AFAIK) the usefulness of reproducible local builds.

The problem is that flakes represent an entirely new way of doing things, where perhaps the old way could have been (and should still be) improved upon, in a way that consumers of nix have a chance to posit their use cases (through RFC’s). The problem is that if a person decides not to use flakes to configure their system because they don’t like the design/experimental status of flakes, they are just SOL when it comes to being able to share their exact configuration so someone else can rebuild it.

I think flakes are a great addition to nix, and should be in 3.0. But they are simply not a total replacement for the old way of doing things. The work that went into building the old tools shouldn’t be wasted on the principle of “newer is always better”. As long as people use the old tools they should be supported. And that’s coming from a guy that likes shiny new things :slight_smile: . I switched to nixos precisely because I was tired of things breaking and not being able to find documentation on how to fix it. Nix has mostly solved one of those problems for me.

3 Likes

I will take a look at it! Thanks.

1 Like

@fricklerhandwerk

The pull request is ready when you are

2 Likes

It doesn’t though; your proposed feature still inherently relies on system state. You’ve made it easier to share and reproduce that state, sure, but project evaluation itself is still tied to global system state and therefore not reproducible.

If you view NixOS entirely in a vacuum, and assume that there is nothing but the very system you are rebuilding, I can see how you’d arrive at that path (and that is where nix-channel undoubtedly comes from), but that thinking is precisely why channels fall short; it’s inherently global state.

If you want to build a VM or nixos-rebuild switch another system remotely, you would need to remember to first change your system state to match theirs, and then also remember to change it back. A design like that is deeply flawed, since multiple evaluations can give unexpected behavior, and the overall intent of what the state persists becomes meaningless; you’re just having a global variable for the sake of having a global variable.

I think you just haven’t thought out the lockfile thing to its conclusion. Your skepticism of flakes is valid (and I believe @waffle8946 actually largely shares it), but the lockfile concept itself isn’t really your issue.

To open your horizon a little, if you only ever care about one evaluation, you can think of nix flake update as the same as nix channel update, but it stores the channels in /etc/nixos instead of /nix/var, and therefore doesn’t need import/export functionality in the first place.

Flakes obviously still come with a bunch of other baggage, and I think it is valid to not like that.

For this reason, I think npins still sound to me like exactly what you actually want. They are essentially just a standardization of what @fricklerhandwerk suggested, except the URL that is downloaded is read from a json file in /etc/nixos instead of a directory in /nix/var.

Standardization of that lockfile format to be shared between the flake world and npins world would be an interesting endeavour, but I don’t think it’s really that useful, since you can’t evaluate flakes without parsing flake.nix anyway, and the projects are cross-compatible even without such standardization already thanks to the load-flake builtin or whatever it was called. Fair enough @fricklerhandwerk, my point is still that cross-compat is already possible and not reliant on lockfile format standardization (it’s anyway just json).

2 Likes

Nit! :stuck_out_tongue:

Both statements are not exactly true.

  1. If you parse flake.lock you can evaluate the outputs from flake.nix just fine given you mimic how flakes are composed inside experimental Nix.
  2. Yes, you can use getFlake, to fetch and evaluate a flake from an expression, but it’s still behind an experimental feature flag.

Here’s a composable way via stable Nix: GitHub - fricklerhandwerk/flake-inputs: A helper to use remote references from `flake.lock` in stable Nix.
It’s extracted from the original flake-compat.

1 Like

???: you have made it easier to share and reproduce that state
 therefore not reproducible.

That does not compute. It isn’t a Schrödinger’s cat, it either is reproducible or isn’t. The word you might be looking for is “pure”. If it relies on global state, it isn’t pure. My focus is that reproducibility is far more important than purity, and flakes have many circumstances where they are neither pure nor reproducible (read: development shells). Purity and reproducibility should be striven for, but it isn’t always useful to have both. We have a command that is expected to be run when contributing/bug reporting in nixpkgs, and the reason for that is that there is no (technically vanilla) NixOS system in existence that is entirely pure without some ungodly flake black magic (and the obscurity of the black magic probably negates any positives purity might bring).

In the context of a flake.nix, it technically relies on “global state” as well. The flake.lock is not written in nix and is not directly referred to within flake.nix. So running nix build with a different lock with the same flake will produce different results. We get around that by defining the flake not as the file and the files it refers to itself, but as the directory that contains the flake, including all its members. I could easily make up some similar garbage definition of purity by saying that “my Ubuntu system is reproducible, since if you have everything in / you will have the same system as me”. That’s not what reproducibility/purity means, but it is if you take the flake definition of purity to its extreme.

Also, there are still bugs in how flakes interpret “the current directory”, given that a flake takes git versioning into account in a not-so-sane (imo) way. I have had many issues in my development flow with flakes that I haven’t bothered to report, including nix build overwriting my flake.lock because it wasn’t version controlled. Insanity. Hair pulling ensues as I redownload a ton of dependencies on a terrible internet connection because I have no way of recovering the flake.lock that was totally clobbered. And this isn’t ideal for the same reason it isn’t ideal for a Cargo.lock to be clobbered just because it is gitignored.

Practically, what we are trying (I hope) to achieve is create a reliable and lightweight way of reproducing bugs and development environments. I don’t think it particularly matters whether it is technically pure or not. Nobody is going to agree on what purity means. That is obvious. And what even is the point of purity beyond a certain point excepting “but functional programming, bro”. But reproducibility? That is easily definable by ordinary means. I don’t actually care about purity as long as another person can see the same thing I see with minimal effort. Right now, there is no single command that can reliably do this in a vanilla NixOS. That is why I am so frustrated with flakes. They are an addon that doesn’t even solve the biggest problem.

Back to functional programming and purity. Here is an article I found, see especially section 5. Functional programming is great. But functional programming is a subset of computation. By definition, when you enforce purity, you are losing features. Most of nix’s scope and usefulness come from its impure parts. What parts are impure?

Well, IO is one. You can’t install packages in a completely pure way. Theoretically, there could be a bug in how a FS is implemented that only shows up when files are in a certain order on disk. You could be on a COW system. You could be on a filesystem with limited path lengths. You could be on a filesystem without hard linking support. All of these things, nix tries to adapt to and eliminate problems with. But the reality is that the layer of nix that deals with these things is inherently impure. But removing that functionality would remove nix’s ability to be useful.

The user could make a mistake and edit part of the (technically still there) global state. I have (I know I’m special) using only nix commands. This resulted in a borked system that had to be completely reinstalled from my config. Repair didn’t work. So nix relies on its own global state being controlled strictly by itself and puts things in place to try to prevent users from editing that state: but nevertheless a bug within nix or malicious user action can remove that safety guarantee and result in a non-reproducible system: because nix isn’t actually completely pure (/nix/var may as well be named /nix/globalstate, and this is still an issue with flakes or npins).

And no, npins is not what I want. I’m interested in agreed upon community standards, which npins is not AFAIK. Removing the tarball-ttl does exactly what I want.

Honestly, I’d be interested in learning how to have a flakes based system. As I said before, I am not anti-flakes. I just don’t know how it would work, or if I’d even like it (I would not like having more than one flake.lock). Because of how it was thrown into the nix ecosystem with all the care of a bull in a china shop, all the easily accessible documentation and the default NixOS images don’t use flakes. Yes there is nix.dev, but it isn’t exactly a light read (and you have to find it first). And according to nix.dev on flakes:

New Nix users were and still are encouraged by various individuals to adopt flakes despite there being no stability guarantees and no timeline to conclude the experiment.

This is a huge red flag to any new user of nix. It screams “don’t use this, you can’t trust it”. And why should I, when I get everything I want done without flakes (with the exception of better development shells that actually cache, and independent reproducible builds).

And, off tangent, the fact that 84% of people are using “experimental” features in an ecosystem that favors reproducibility is insane. Even I have nix-command and flakes enabled globally :rofl:

Edit: I forgot to mention that the entire nix system configuration is editable via an environment variable and it is easy to add this to a shell hook within any flake/shell.nix (or even a .zshrc)

export NIX_CONFIG="experimental-features = nix-command flakes"

Which is again, not pure.

1 Like