I’m trying to pin nixpkgs in my system configuration with niv. The installed system is 20.09, and I’m trying to replace it with unstable. I could upgrade to unstable with nix channels and then do this, but the errors I’m encountering here suggest that both the methods I found don’t actually guarantee reproducibility as they depend on things outside the configuration folder.
The first method doesn’t seem to do anything. The system derivation is named /nix/store/qhpm821ppi9fixc46ywpx43mrp8fhy6s-nixos-system-illustris-thinkpad-20.09.3882.5c0e6a8c319.drv. It’s using 20.09 despite the nixpkgs provided by niv being unstable.
The second method throws this error:
# nixos-rebuild test
building Nix...
building the system configuration...
error: 'makeDBusConf' at /nix/store/4dhw8s1gz46715m3zzgklczx882k2agw-nixpkgs-src/pkgs/top-level/all-packages.nix:14102:18 called without required argument 'apparmor', at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/services/system/dbus.nix:13:15
(use '--show-trace' to show detailed location information)
This method also appears to be using nixpkgs from /nix/var/nix/profiles instead of niv.
What is the correct way to make sure configuration.nix uses only the nixpkgs version provided by niv for packages and modules?
let
nixexprs = builtins.fetchTarball {
url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz";
};
in
{
nixpkgs.pkgs = import "${nixexprs}" {
inherit (config.nixpkgs) config overlays localSystem crossSystem;
};
# and so on...
# nixos-rebuild test
building Nix...
building the system configuration...
error: 'makeDBusConf' at /nix/store/sgzx9z0nshhgajjpjp23mi7fvr187g9x-source/pkgs/top-level/all-packages.nix:14093:18 called without required argument 'apparmor', at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/services/system/dbus.nix:13:15
(use '--show-trace' to show detailed location information)
{ config, pkgs, ... }:
let
nixexprs = builtins.fetchTarball {
url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz";
};
in
{
nixpkgs.pkgs = import "${nixexprs}" {
inherit (config.nixpkgs) config overlays localSystem crossSystem;
};
nix.autoOptimiseStore = true;
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
./desktop-configuration.nix
./networking-configuration.nix
];
nixpkgs.overlays = [
];
boot.kernelPackages = pkgs.linuxPackages_latest;
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "thinkpad"; # Define your hostname.
hardware.bluetooth = {
enable = true;
config = {
General = {
Enable = "Source,Sink,Media,Socket";
};
};
};
services.blueman.enable = true;
# Set your time zone.
time.timeZone = "Asia/Kolkata";
networking.hostId = "dddddddd"; # needed by ZFS, not networking
users.users = {
illustris = {
isNormalUser = true;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keyFiles = [ ./secrets/ssh_pubkeys ];
};
root.openssh.authorizedKeys.keyFiles = [ ./secrets/ssh_pubkeys ];
};
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
networkmanager
];
# Enable the OpenSSH daemon.
services.openssh = {
enable = true;
forwardX11 = true;
};
# Open ports in the firewall.
networking.firewall.allowedTCPPorts = [ 22 ];
# 60000-3 opened for mosh
networking.firewall.allowedUDPPorts = [ ];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. It‘s perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "20.09"; # Did you read the comment?
}
I think the easiest way to “pin” nixpkgs, is to do it from the “outside”, similar to how the “home-manager template” does it for Home-Manager.
The technique remains the same.
Create a nix shell that has a NIX_PATH set that points to the pinned nixpkgs version and run all rebuilds through this command only.
An alternative to that approach is to use flakes, which get you the pinning for “free”, at the cost of using an indev and explicitely marked as experimental system.
nix-build '<nixpkgs/nixos>' --arg configuration ./vm.nix -A system
which is what nixos-rebuild does under the hood. I’ll investigate this further, because this definitely worked in the past. I used this for quite some time before I switched to flakes.
This mostly works. I’ve added aliases to run test and switch with this shell to avoid accidentally using system nixpkgs. as per @hmenke 's suggestion I’ve also had to add
let sources = import ./nix/sources.nix; in
{
programs.bash.interactiveShellInit = "export NIX_PATH=nixpkgs=${sources.nixpkgs.outPath}:nixos-config=/etc/nixos/configuration.nix";
nix.nixPath = [ "nixpkgs=${sources.nixpkgs.outPath}" "nixos-config=/etc/nixos/configuration.nix" ];
}