Do flakes also set the system channel?

But if the flake is set to follow the release-branch, then it should be possible to use sth. like

inputs.nixos-channel.url = "https://releases.nixos.org/nixos/22.05/nixos-22.05.1056.d423c0ce15a/nixexprs.tar.xz"

(modulo the build number) where the commit-id-part is determined from the lockfile…

Lack of command-not-found behavior has bugged me ever since I deleted my channels, so I made a rather more involved solution which always gets the programs.sqlite associated with the exact commit your input is set to. See the commit to my personal config repo here:
https://github.com/tejing1/nixos-config/commit/4856caf264a9b8a62e1ca9e5c430f627835b739a

Assuming you follow a ref which corresponds to a channel, I think this should always work, though integrating it into your own config will take some adjustment.

Notes:

  • my.lib.mkShellScript is a minor convenience wrapper around pkgs.resholve.writeScript. In this case, all it really does is add the interpreter attribute.
  • inputSpecs is calculated from (import (self + "/flake.nix")).inputs with a bit of code that translates url forms to attrset forms. See https://github.com/tejing1/nixos-config/blob/4856caf264a9b8a62e1ca9e5c430f627835b739a/genericModules/inputSpecs.nix (EDIT: builtins.parseFlakeRef exists now for this purpose.)
  • hred is not packaged in nixpkgs yet (A shame. It’s the best html/xml data extractor around), but node2nix handles it with no tweaks. Or you could use xq from pkgs.yq to accomplish the same task. EDIT: It’s in nixpkgs now.

do a PR :slight_smile:

that only works if you’re on nixos-unstable or release and do not have any custom commits on top of it.

do a PR :slight_smile:

I probably should. I didn’t at first because I wasn’t familiar enough with nixpkgs’ node stuff, but I could figure it out.

that only works if you’re on nixos-unstable or release and do not have any custom commits on top of it.

Yeah, like I said, “Assuming you follow a ref which corresponds to a channel, I think this should always work.” If that assumption doesn’t hold, you either need to determine a “nearby” commit by whatever means is appropriate for how you consume nixpkgs and adapt this system to that, or you need to generate programs.sqlite yourself.

I’ve flakeified my system following https://nixos.wiki/wiki/Flakes#Using_nix_flakes_with_NixOS a while ago, and just now noticed that the program I tested with nix-shell -p foo wasn’t the same that was installed when I then added it to my system configuration, and was quite surprised.

So I’m curious whether a single official best practice to tie NIX_PATH to the system’s flake configuration has already emerged? Is it on the way to becoming default (or at least added to the “official” instructions on the wiki)?

I don’t know if this is best practice, but this is what I do:

let nixPath = "/etc/nixPath";

in
{
  systemd.tmpfiles.rules = [
    "L+ ${nixPath} - - - - ${pkgs.path}"
  ];

  nix = {
    nixPath = [ "nixpkgs=${nixPath}" ];
  };
}

Instead of using /etc/nixPath, you could of course also just set the NIX_PATH environment variable, but that would require closing terminals in order to pick up the new value, so the on-disk version is more flexible.

EDIT: just to clarify, doing this means that all your regular nix-* tools work as expected with flakes.

1 Like

Thanks @peterhoeg . I confirmed this works for me.

Another alternative that I found in lovesegfault’s dotfiles, is to create a symlink to the outpath.

He creates the symlink for NixOS systems here, and for nix-darwin systems here

Then it’s possible to set the nix.nixPath to the stable link created, which differs slightly between Darwin and Nixos. That’s done here.

I like this slightly more since it works even outside of Nixos, and doesn’t add the dependency on systemd.

I had originally thought to do this as an activationScript, but his approach seems much cleaner.

3 Likes

I think this is very similar to what I do here: ~r-vdp/nixos-config (main): modules/nix.nix - sourcehut git

Which was inspired by the blog post mentioned in the comment.

I think I have a similar problem at Getting older nixpkgs in nix-shell, if system uses nix flakes, does anyone have advice on that as well?

I think I did it with https://github.com/pbek/nixcfg/commit/7cddcb47054b351a484c4959dcf162f9c5c6a2fe!
Thank you for the hint, @vamega!

In my case, I switched "/etc/nixPath" for "/tmp/nixPath" because it seems like nix shells modify the /etc contents based on the shell environment. /etc/nixPath would disappear and I would be unable to switch shells when using direnv at the same time.

So for anyone else scrolling, my config is:

nix-channel.nix

{ config, pkgs, inputs, ... }:

let nixPath = "/tmp/nixPath";

in
{
  systemd.tmpfiles.rules = [
    "L+ ${nixPath} - - - - ${pkgs.path}"
  ];

  nix = {
    nixPath = [ "nixpkgs=${nixPath}" ];
  };
}

There is something very strange with your setup then - using /etc/nixPath absolutely works and the link doesn’t disappear.

You can of course put it elsewhere, but /tmp is a bad idea as it might get automatically cleaned out. If you really don’t want /etc (or can’t figure out what makes it disappear), I suggest /run or /var instead.

Maybe it’s something to do with direnv? Or something else surrounding that. There was one shell I had where each time I entered direnv, the nixPath would disappear from /etc along with many other folders (the environment variable was still there though), and because of that I couldn’t use nix shell anymore, even via direnv, inside that folder. Worked fine in other folders.

I’ll use /run instead.

That sounds like something strange about the shell, not this approach. Though it seems like you’d have to be doing something pretty cursed in the shell for that to happen… I’m not even sure how a direnv-based shell even could mess with /etc

I wasn’t doing anything particularly cursed, just importing a couple of packages. Was very confused by it as well, will report back if I find the reason.

Maybe an fhs env? But direnv shouldn’t drop into a shell so it could not actually drop into such an environment?

A custom activation script that did something it wasn’t supposed to maybe?

If I were you I would definitely focus on finding out why this happens instead of applying workarounds. There is something very wrong with your setup somewhere.

I think I figured it out, it’s because I’m running vscode inside FHS, so pretty sure it’s expected behavior.

That tracks. The dev shell itself can’t possibly do that, but if it’s being run from inside an FHS container it makes perfect sense.