Pinning NixOS with npins

15 Likes

Always nice to see people documenting flake-less, channel-less approaches.

Now that nixos-rebuild has gained the ability to pass it an instantiated NixOS system, I’m quite fond of that approach:

# name this e.g. mymachine.nix
let
  nixpkgs = builtins.fetchGit {
    name = "nixos-24.05-2024-05-31";
    url = "https://github.com/NixOS/nixpkgs";
    ref = "refs/heads/nixos-24.05";
    rev = "805a384895c696f802a9bf5bf4720f37385df547";
  };
in
import "${nixpkgs}/nixos/lib/eval-config.nix" {
  system = null;
  modules = [
    ./configuration.nix
  ];
}

and then using nixos-rebuild -f mymachine.nix.

6 Likes

Also just wanted to mention that, there’s also some follow-ups to make this even more powerful (one by @justinas themselves)

4 Likes

That’s neat, thank you for pointing it out! I personally use colmena for all my machines instead of nixos-rebuild, but I might want to revisit that with these improvements

2 Likes

That’s great!
I have been doing before

let
  nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/5ef6c425980847c78a80d759abc476e941a9bf42.tar.gz";
  pkgs = import nixpkgs {};
  what-is-my-ip = import ./what-is-my-ip.nix {inherit pkgs;};
  nixos = import "${nixpkgs}/nixos" {
    configuration = {
      users.users.alice = {
        isNormalUser = true;
        # enable sudo
        extraGroups = ["wheel"];
        packages = [
          what-is-my-ip
        ];
        initialPassword = "swordfish";
      };

      system.stateVersion = "24.05";
    };
  };
in
  nixos.vm

How is this different? Could I have returned back nixos.config.build.toplevel (or whatever it is) and done so already?

I love the simplicity of 1-file examples.

1 Like

The key difference is that the nixpkgs you import here is only used for building your configuration and then available nowhere else. Notably, if within that system you then do nix-shell, which Nixpkgs will it use?

2 Likes

One nixpkgs to rule them all! Personally if i had the setup I want I’d use my npins sources to set my nixpkgs source, but I would like to be able to use a local nixpkgs without copying it into store every eval.

Some day when i finally unflake!

Yeah, at the end of the day what nixos-rebuild does is invoke nix-build for either toplevel or vm, depending on whether you’re doing build (switch etc.) or build-vm.
.

1 Like

From this information, one could pretty much write a NixOS build tool: it really is just nix build -f '<nixpkgs/nixos>' config.system.build.toplevel (in old syntax, nix-build '<nixpkgs/nixos>' -A config.system.build.toplevel), then result/bin/switch-to-configuration. That’s all it does.

This bit me before :frowning_face: Unfortunately, nixos-rebuild is also responsible for generating the system and system-$n-link symlinks in /nix/var/nix/profiles/system

1 Like

Yep @SergeK that’s why there are so many and why there’s no point writing them in Rust or any fancy language. Here’s a link to my “nixos-rebuild” reimplemented in fish-shell. Since i don’t support remote building or any other fancy flags it’s really barebones and should make for a good example to build your own with.

The only “magic” is that i pipe the output of nix build through tee to save it to file and process it with “nom” that makes for a nicer rebuild TUI progress experience.

Looks like I had already

# Put nixpkgs into /etc/nixpkgs for convenience
  environment.etc.nixpkgs.source = inputs.nixpkgs;
  # Point nixpath to that nixpkgs so that the system uses the same nix
  nix = {
    nixPath = ["nixpkgs=/etc/nixpkgs" "nixos-config=/etc/nixos/configuration.nix"];

Not sure if i’m missing more.

This makes me so glad I wrote this post!

Because it took me quite a few iterations to find this solution from first principles, and how I’m hearing from a handful of people that they’ve been doing it like this all along. It really seems to be a useful pattern, and we should document and spread it more. Maybe somewhere in the Wiki as well?

Also no you’re not really missing out on much, the base solution really is only a couple of lines long.

5 Likes

Cool.
I can’t remember whose nixOS config I cribbed it from; maybe @Infinisil or jonringer.

Either way – I can attest 100% it’s a good base setting for a starter NixOS project.
(Anything else is “weird” – cause I couldn’t figure out what the nixpath was actually set to.)