I’m using nixops
to deploy a few NixOS severs. One problem I have is that the channels of the servers are basically never used so they get left behind. This causes issues when using things like nix-shell
or the command-not-found
helper as the programs it fetch will be outdated. My goal is to configure the default Nix path to use the nixpkgs
version used to deploy the server.
My initial attempt was something like this:
nix = {
# Don't use mutable channels, always use the deployed version.
nixPath = ["nixpkgs=${<nixpkgs>}"];
channel.enable = false;
};
This is seemingly close to what I want. The nix-channel
command is removed (unnecessary but nice to remind people) and the NIX_PATH
var has any previous channels removed.
However the store path that is pointed to is a dangling symlink, causing evaluations to fail. If I do nixos=${<nixpkgs/nixos>}
I do get a nixos
path that works. But this doesn’t get nixpkgs
. It seems that any sub-file of <nixpkgs>
is fine, but referencing the root will get a dangling symlink.
Is there a way to make this work? Maybe we can add something like pkgs.nixpkgs
to nixpkgs that points at its own root directory as a derivation?
I think pkgs.path
is what you’re looking for, should give you a path to the nix store:
$ nix-channel --list
home-manager https://github.com/rycee/home-manager/archive/master.tar.gz
nixos https://nixos.org/channels/nixos-unstable
$ nix-instantiate --eval -E 'with import <nixpkgs> { }; pkgs.path'
/nix/store/nfmbc543kq6i6q16klizax5rgghwjlrp-nixos/nixos
$ ls /nix/store/nfmbc543kq6i6q16klizax5rgghwjlrp-nixos/nixos
CONTRIBUTING.md COPYING default.nix doc flake.nix lib maintainers nixos nixpkgs pkgs programs.sqlite README.md svn-revision
2 Likes
Thanks! pkgs.path
was exactly what I was looking for.
However this revealed a poor interaction (bug?) between nix.nixPath
and nix.channel.enable = false
. It seems that setting nix.channel.enable = false
sets a default value for nix.settings.nix-path
which causes the NIX_PATH
environment variable set by nix.nixPath
to be ignored. For my case I could easily work around this by setting nix.settings.nix-path
directly. But IDK if it is worth fixing this for everyone.
My final config looks like this. Now my servers will pull programs from their deployed version which is very nice.
nix = {
channel.enable = false;
settings.nix-path = ["nixpkgs=${pkgs.path}"];
};
programs.command-not-found.dbPath = "${pkgs.path}/programs.sqlite";
1 Like
One problem that I noticed is when deploying with a Git checkout of nixpkgs this would include the .git
dir and things like ./result
if I did a build in the checkout. This would copy a huge amount of always different data. (Although store hard-linking optimizations likely helped avoid exploding the actually used storage space.) This isn’t an issue for channels because they are already “clean”.
I managed to work around this by using lib.fileset
to remove untracted files from whatever nixpkgs
is being used.
{lib, pkgs, ...}: let
path = lib.fileset.toSource {
root = pkgs.path;
fileset = lib.fileset.gitTracked pkgs.path;
};
in {
nix = {
channel.enable = false;
settings.nix-path = ["nixpkgs=${path}"];
};
programs.command-not-found.dbPath = "${path}/programs.sqlite";
}
This works with both nixpkgs from git (like -I nixpkgs=/path/to/nixpkgs
) and when using regular channels.