# Pinning NixOS with npins

**URL:** https://discourse.nixos.org/t/pinning-nixos-with-npins/63721
**Category:** Links
**Created:** [May 1, 2025, 10:25am UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721 "2025-05-01T10:25:54Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![piegames](https://discourse.nixos.org/user_avatar/discourse.nixos.org/piegames/32/5324_2.png) [@piegames](https://discourse.nixos.org/u/piegames)
#### Post date: [May 1, 2025, 10:25am UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/1 "2025-05-01T10:25:54Z")

</div>

> **[Pinning NixOS with npins, this time without flakes for real](https://piegames.de/dumps/pinning-nixos-with-npins-revisited/)**
>
> How to have your Nixpkgs pinned and in sync with your NixOS configuration, and have always point to it.

> **[Globally applying overlays onto Nixpkgs](https://piegames.de/dumps/nixpkgs-global-overlays/)**
>
> Normally, overlays are applied to individual Nixpkgs instances, but there are ways of applying them system-wide.

---

<div class="post-metadata">

### Author: ![justinas](https://discourse.nixos.org/user_avatar/discourse.nixos.org/justinas/32/30061_2.png) [@justinas](https://discourse.nixos.org/u/justinas)
#### Post date: [May 1, 2025, 11:04am UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/2 "2025-05-01T11:04:24Z")

</div>

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

Now that nixos-rebuild has [gained the ability](https://github.com/NixOS/nixpkgs/pull/320462) to pass it an instantiated NixOS system, I’m quite fond of that approach:

```nix
# 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`.

---

<div class="post-metadata">

### Author: ![Infinisil](https://discourse.nixos.org/user_avatar/discourse.nixos.org/infinisil/32/26523_2.png) [@Infinisil](https://discourse.nixos.org/u/Infinisil)
#### Post date: [May 1, 2025, 11:06am UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/3 "2025-05-01T11:06:32Z")

</div>

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

- [nixos-{rebuild; install}: rework logic; use `system.nix` by amozeo · Pull Request #389487 · NixOS/nixpkgs · GitHub](https://github.com/NixOS/nixpkgs/pull/389487)
- [nixos-rebuild: add --arg, --argstr by justinas · Pull Request #351661 · NixOS/nixpkgs · GitHub](https://github.com/NixOS/nixpkgs/pull/351661)

---

<div class="post-metadata">

### Author: ![piegames](https://discourse.nixos.org/user_avatar/discourse.nixos.org/piegames/32/5324_2.png) [@piegames](https://discourse.nixos.org/u/piegames)
#### Post date: [May 1, 2025, 11:14am UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/4 "2025-05-01T11:14:39Z")

</div>

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

---

<div class="post-metadata">

### Author: ![fzakaria](https://discourse.nixos.org/user_avatar/discourse.nixos.org/fzakaria/32/2643_2.png) [@fzakaria](https://discourse.nixos.org/u/fzakaria)
#### Post date: [May 1, 2025, 9:46pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/5 "2025-05-01T21:46:43Z")

</div>

That’s great!  
I have been doing before

```auto
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.

---

<div class="post-metadata">

### Author: ![piegames](https://discourse.nixos.org/user_avatar/discourse.nixos.org/piegames/32/5324_2.png) [@piegames](https://discourse.nixos.org/u/piegames)
#### Post date: [May 2, 2025, 6:37am UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/6 "2025-05-02T06:37:11Z")

</div>

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?

---

<div class="post-metadata">

### Author: ![Lillecarl](https://discourse.nixos.org/user_avatar/discourse.nixos.org/lillecarl/32/34279_2.png) [@Lillecarl](https://discourse.nixos.org/u/Lillecarl)
#### Post date: [May 2, 2025, 1:33pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/7 "2025-05-02T13:33:25Z")

</div>

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!

---

<div class="post-metadata">

### Author: ![justinas](https://discourse.nixos.org/user_avatar/discourse.nixos.org/justinas/32/30061_2.png) [@justinas](https://discourse.nixos.org/u/justinas)
#### Post date: [May 2, 2025, 1:35pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/8 "2025-05-02T13:35:18Z")

</div>

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`.  
.

> <https://github.com/NixOS/nixpkgs/blob/cbc2586506c4f64170c71f67fb1f301a7d3fce36/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh#L799-L803>

---

<div class="post-metadata">

### Author: ![SergeK](https://discourse.nixos.org/user_avatar/discourse.nixos.org/sergek/32/2972_2.png) [@SergeK](https://discourse.nixos.org/u/SergeK)
#### Post date: [May 2, 2025, 1:40pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/9 "2025-05-02T13:40:32Z")

</div>

> 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 ☹ Unfortunately, `nixos-rebuild` is also responsible for generating the `system` and `system-$n-link` symlinks in `/nix/var/nix/profiles/system`

---

<div class="post-metadata">

### Author: ![Lillecarl](https://discourse.nixos.org/user_avatar/discourse.nixos.org/lillecarl/32/34279_2.png) [@Lillecarl](https://discourse.nixos.org/u/Lillecarl)
#### Post date: [May 2, 2025, 1:47pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/10 "2025-05-02T13:47:45Z")

</div>

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](https://github.com/Lillecarl/nixos/blob/0cd25a6656976b10b9caf49b4dd637d91b5245f5/users/lillecarl/dotfiles/.config/fish/functions/rebuild-os.fish) 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.

---

<div class="post-metadata">

### Author: ![fzakaria](https://discourse.nixos.org/user_avatar/discourse.nixos.org/fzakaria/32/2643_2.png) [@fzakaria](https://discourse.nixos.org/u/fzakaria)
#### Post date: [May 2, 2025, 4:39pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/11 "2025-05-02T16:39:41Z")

</div>

Looks like I had already

```auto
# 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.

---

<div class="post-metadata">

### Author: ![piegames](https://discourse.nixos.org/user_avatar/discourse.nixos.org/piegames/32/5324_2.png) [@piegames](https://discourse.nixos.org/u/piegames)
#### Post date: [May 3, 2025, 7:53am UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/12 "2025-05-03T07:53:28Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![fzakaria](https://discourse.nixos.org/user_avatar/discourse.nixos.org/fzakaria/32/2643_2.png) [@fzakaria](https://discourse.nixos.org/u/fzakaria)
#### Post date: [May 3, 2025, 4:35pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/13 "2025-05-03T16:35:28Z")

</div>

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.)

---

<div class="post-metadata">

### Author: ![TeofilC](https://discourse.nixos.org/user_avatar/discourse.nixos.org/teofilc/32/34667_2.png) [@TeofilC](https://discourse.nixos.org/u/TeofilC)
#### Post date: [May 6, 2025, 12:23pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/14 "2025-05-06T12:23:39Z")

</div>

Great posts! It might be worth mentioning that there is an unexpectedly high performance cost to using `pkgs.path`. It causes the entire nixpkgs source to be refiltered again\[1\]. This can take a few seconds. I work around this by overriding `path` with the actual source of nixpkgs, but any way of passing down the actual source should work.

* * *

1. This happens because the definition of `path` is just a normal path expression like `../.` and nix isn’t smart enough to know that you are just pointing at an already existing storepath, so it does the work of filtering and hashing again.

---

<div class="post-metadata">

### Author: ![piegames](https://discourse.nixos.org/user_avatar/discourse.nixos.org/piegames/32/5324_2.png) [@piegames](https://discourse.nixos.org/u/piegames)
#### Post date: [May 6, 2025, 1:07pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/15 "2025-05-06T13:07:48Z")

</div>

Yeah, I’ve run into several other gotchas around using `pkgs.path` naively, however all of my grievances were fixed by using `builtins.storePath pkgs.path` instead.

---

<div class="post-metadata">

### Author: ![TeofilC](https://discourse.nixos.org/user_avatar/discourse.nixos.org/teofilc/32/34667_2.png) [@TeofilC](https://discourse.nixos.org/u/TeofilC)
#### Post date: [May 6, 2025, 1:15pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/16 "2025-05-06T13:15:23Z")

</div>

Cool I’ll try that as well!

---

<div class="post-metadata">

### Author: ![viperML](https://discourse.nixos.org/user_avatar/discourse.nixos.org/viperml/32/34002_2.png) [@viperML](https://discourse.nixos.org/u/viperML)
#### Post date: [May 6, 2025, 5:40pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/17 "2025-05-06T17:40:37Z")

</div>

For the record, nh v4.0 added support for non-flake installables (I still need to make the annoucement…).

Regular nixos-rebuilds maps to `nh os switch -f <nixpkgs>` but you may want to evaluate nixos manually.

---

<div class="post-metadata">

### Author: ![fzakaria](https://discourse.nixos.org/user_avatar/discourse.nixos.org/fzakaria/32/2643_2.png) [@fzakaria](https://discourse.nixos.org/u/fzakaria)
#### Post date: [May 28, 2025, 4:20pm UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/18 "2025-05-28T16:20:38Z")

</div>

Here is the home-manager equivalent:

```nix
{
  inputs,
  outputs,
  config,
  pkgs,
  ...
}: {
  # keep the source of the nixpkgs we are using easy to find
  home.file.".nixpkgs".source = inputs.nixpkgs;
  nix = {
    package = pkgs.unstable.nixVersions.latest;
    nixPath = ["nixpkgs=~/.nixpkgs"];
    settings = {
      show-trace = true;
      experimental-features = ["nix-command" "flakes"];
    };
  };
}

```

---

<div class="post-metadata">

### Author: ![waffle8946](https://discourse.nixos.org/user_avatar/discourse.nixos.org/waffle8946/32/27221_2.png) [@waffle8946](https://discourse.nixos.org/u/waffle8946)
#### Post date: [May 30, 2025, 1:54am UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/19 "2025-05-30T01:54:26Z")

</div>

Isn’t the whole point of the post to _not_ use flakes?

---

<div class="post-metadata">

### Author: ![fzakaria](https://discourse.nixos.org/user_avatar/discourse.nixos.org/fzakaria/32/2643_2.png) [@fzakaria](https://discourse.nixos.org/u/fzakaria)
#### Post date: [May 30, 2025, 2:05am UTC](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721/20 "2025-05-30T02:05:25Z")

</div>

There was two points AFIR. The other was how to avoid channels on NixOS or make it the same channel you built the system with.

[Next page](https://discourse.nixos.org/t/pinning-nixos-with-npins/63721.md?page=2)
