I am still a relative beginner in all of this, so excuse me if I say wrong things, but please do correct me so I can learn and improve.
I find the normal way of building a NixOS configuration somewhat odd (considering Nix encourages not relying on environment state). I bet I am misunderstanding this. Please help me fix my mistakes.
The method I currently use is dependent only on explicit inputs, i.e. nix-build <nix-files-root>
, and I can switch to it and so on if I want.
By <nix-files-root>
I do NOT mean something defined in NIX_PATH, depending on NIX_PATH is exactly the state I am trying to avoid when building the system (note that on random nix-build
s I do not mind the extra convenience). This is just syntax to mean some path on my system, for this thread.
By “explicit inputs” I mean things which are not:
- nixpkgs/nixos in /etc/nixos (or is it nix-channels directory?) or somewhere pointed to by NIX_PATH, at some revision that is not specified in the system’s nix expression
- A nixpkgs config file you might or might not have in your home directory
- Overlays you may or may not have in your home directory
- nix channels
- ? I don’t know what else as I am not familiar with this way of building
Each of these things are outside of <nix-files-root>
and yet affect the system output and so, hurt reproducibility. You might say that I can have those files in <nix-files-root>
and symlink but then I have to do the symlink to get to that state, If I forget and there happens to be different files there, I get a different system.
The method I use works for me. The reasons I made this post are the following:
- I am curious as to why NixOS with its emphasis on avoiding state and being declarative and reproducible has these stateful defaults. Is it to be user-friendly? If so, that’s appreciated. But I am not sure this is easier to grasp for beginners than having everything derived from your nix expressions without dependencies on stuff in the environment.
- The method I use breaks when using tools like
nixos-rebuild
,nixos-option
unless I jump through a couple of hoops, that start to make the system building more stateful. I am probably approaching this in the wrong manner so I would be very appreciative if people share their ways of doing this. I don’t really know what I am doing.
The method I use is instead of having a configuration.nix like so:
{ config, lib, pkgs, ... }:
{
...config...
}
I have a default.nix in some <nix-files-root>/<host-name>
path that looks like so:
let
defaultPkgs = import ../nixpkgs {};
in { pkgs ? defaultPkgs } :
import "${pkgs.pkgsSrc}/nixos" {
system = "x86_64-linux";
configuration = {
...config...
};
}
I think I got this idea from Gabriel Gonzalez blog post, but it was a long time ago so excuse me for not remembering exactly where.
As you can see from defaultPkgs
nixpkgs itself ALSO comes from some nix exprssion, that fetches the repo at the needed revision and applies config and overlays that are all defined as nix expressions inside this same <nix-files-root>
without depending on files in /etc/nixos
, /home/<user>/.config
, nix-channels directory, and without depending on having nixpkgs/nixos
as it is fetched along with the nixpkgs repo for the build. There is also the added advantage that the system can now be built just like every
other thing is built with Nix using nix-build
. Yes you have to invoke a second command to choose if you want to test
, switch
or none at all. I just have a bash function to do that along with adding to the system profile so it is selectable from the boot menu.
In order to be able to use nixos-option
I had to have a configuration.nix in the format shown above with an extra nixpkgs.config = import ...
to get the same config I use for my regular setup. This is not so bad. But I am also forced to clone the nixpkgs repo somewhere, and set NIX_PATH nixpkgs/nixos to point to it, as well as nixos-config to point to the configuration.nix I just made. The nix files are in a git repo so now I need to have the nixpkgs repo as a submodule correct? And when I want to use a different revision, instead of changing a revision inside a nix expression, I now have to change the revision of the submodule instead?
Is there an easy way to have <nixpkgs/nixos>
being fetched during the nix-build from the nixpkgs repo (and have config/overlays applied as defined by what I am building rather than environmental files)? Rather than using nix-channels or some other place pointed to by NIX_PATH? And still have support for nixos-option
/nixos-rebuild
/who-knows-what-other-commands-in-the-future?
In other words, is it possible to adjust the current scheme I use to support these tools?
They fail because <nixpkgs/nixos>
is not found. But I don’t know the path in the nix store it’s going to have and it’s going to change every couple of builds, so I can’t possibly set it in NIX_PATH.
BTW I am using nix-eval --instantiate
instead at the moment as an alternative to nixos-option
but it’s not as good.
Any intention to help in fixing my understanding or methods is greatly appreciated!
Looking forward to using NixOS the way it was meant to be used so that I can get support from NixOS tools.