morph
morph copied to clipboard
suggestion: make evalConfig configurable
PR #96 has already greatly improved working with machines that have differing requirements/architecture, however there is still one use-case that is largely unsupported: Multiple nixpkgs versions.
From what I understand the issue lies with nixpkgs/nixos/lib/eval-config.nix, as evaluating a configuration that uses a differing nixpkgs version seems to be unsupported.
I propose this problem could be fixed by making the new evalConfig option a function with the ability to inspect either the deployment name, or the value of the deployment. I suppose the former would be easier to understand and implement, while the later would potentially be more extensible.
Of course, I would also be happy with any alternative solution.
Example code (name)
let
sources = import ../sources/nix/sources.nix;
pinned-stable = import sources.nixos-19_09-small { };
pinned-unstable = import sources.nixos-unstable { };
in {
network = {
description = "Home network";
overlays = [ ];
config = {
allowUnfree = true;
allowBroken = false;
};
# NOTE: evalConfig also passes nixpkgs.pkgs
lib = pinned-stable.lib;
evalConfig = name:
if (name == "nixos-laptop.local") then
pinned-stable.path + "/nixos/lib/eval-config.nix"
else
pinned-unstable.path + "/nixos/lib/eval-config.nix";
runCommand = pinned-stable.runCommand;
};
} // {
"nixos-laptop.local" = import ./laptop/configuration.nix;
"nixos-fujitsu.local" = import ./fujitsu.nix;
"nixos-rpi.local" = import ./rpi.nix;
}
It seems that the 20.03 gnupg module have an eval-dependency on pkgs.pinentry.flavors which doesn't exist in the 19.09 package-set. This effectively mean that you cannot eval 19.09-nixpkgs with 20.03 NixOS-modules and eval'ing 20.03-packages with 19.09-modules is not possible either, which... in turn leads to the conclusion that..: Currently morph cannot have 19.09 and 20.03 machines in the same deployment/network. :(
I don't know if there are any upstream opinions about backward compatibility or at least opinions about not having strict eval dependencies to packages in the first place? I tried to "complain" here: https://logs.nix.samueldr.com/nixos/2020-02-21#3093582;
I was about to create a new issue for making evalConfig - or the entire "buildTime-nixpkgs" - configurable at per-host level in morph, but realized it was already here :) :+1:
@johanot Right, but it definitely seems to be possible to eval both nixos 20.03 with evalConfig 20.03 and nixos 19.09 with evalConfig 19.09, in the same file.
I also think that use-case is more interesting than the mixing of versions you describe.
Maybe I'm missing what exact problem you are trying to describe?
I just patched morph, adapted my deployment and everything seems to be working.
Morph Patch
diff --git a/data/eval-machines.nix b/data/eval-machines.nix
index 86ba52d..4cdc426 100644
--- a/data/eval-machines.nix
+++ b/data/eval-machines.nix
@@ -5,7 +5,7 @@ let
network = import networkExpr;
nwPkgs = network.network.pkgs or {};
lib = network.network.lib or nwPkgs.lib or (import <nixpkgs/lib>);
- evalConfig = network.network.evalConfig or "${nwPkgs.path or <nixpkgs>}/nixos/lib/eval-config.nix";
+ evalConfig = network.network.evalConfig or (_: "${nwPkgs.path or <nixpkgs>}/nixos/lib/eval-config.nix");
runCommand = network.network.runCommand or nwPkgs.runCommand or ((import <nixpkgs> {}).runCommand);
in
with lib;
@@ -21,7 +21,7 @@ rec {
modules = [ { imports = [ network.${machineName} ]; } { inherit (network) _file; } ];
in
{ name = machineName;
- value = import evalConfig {
+ value = import (evalConfig machineName) {
modules =
modules ++
[ ({ config, lib, options, ... }: {
My Deployment
let
sources = import ../sources/nix/sources.nix;
pinned = import sources.nixos-19_09-small { };
unstable = import sources.nixos-unstable { };
in {
network = {
description = "Home network";
overlays = [ ];
config = {
allowUnfree = true;
allowBroken = false;
};
# NOTE: evalConfig also passes nixpkgs.pkgs
lib = pinned.lib;
evalConfig = name:
if name == "nixos-laptop.local" then
unstable.path + "/nixos/lib/eval-config.nix"
else
pinned.path + "/nixos/lib/eval-config.nix";
runCommand = pinned.runCommand;
};
} // {
"nixos-laptop.local" = import ./laptop/configuration.nix;
"nixos-fujitsu.local" = import ./fujitsu.nix;
"nixos-rpi.local" = import ./rpi.nix;
}
@leotaku For the record, this demonstrates the nixpkgs/nixos-modules conflict I was referring to:
let
common = { pkgs, ... }: {
environment.systemPackages = [ pkgs.hello ];
fileSystems."/" = {
fsType = "ext4";
label = "root";
};
boot.loader.grub.devices = [ "/dev/sda" ];
};
loris = import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs-channels/archive/c2c5dcc00b05f0f6007d7a997dc9d90aefb49f28.tar.gz";
sha256 = "1sjy9b1jh7k4bhww42zyjjim4c1nn8r4fdbqmyqy4hjyfrh9z6jc";
}) { config = {}; overlays = []; };
markhor = import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs-channels/archive/153baa2674010416bed78f797f8239e1cbfed956.tar.gz";
sha256 = "0kf6xx5lawhlkxwk8j3qb7x4bvn1snpixmw4y9qxa2glbgk5h9zr";
}) { config = {}; overlays = []; };
in
{
network = {
inherit (markhor) runCommand lib;
evalConfig = "${markhor.path}/nixos/lib/eval-config.nix"; # try changing this to "loris.path"
description = "test";
};
loris = { config, pkgs, ... }: {
imports = [ common ];
nixpkgs.pkgs = loris;
};
markhor = { config, pkgs, ... }: {
imports = [ common ];
nixpkgs.pkgs = markhor;
};
}
"markhor"-pkgs don't build with "loris"-nixos (eval-config), and vice versa.
I am running into a similar issue. I have most of my machines follow the latest stable channel but some machines (currently just one) is following nixos-unstable due to changes in there that I require for it to operate at all. While I could continue backporting those changes manually (i.e. rebasing my custom branch on the latest channel) that becomes tedious.
I am currently tempted to use something as described in https://github.com/DBCDK/morph/issues/104#issuecomment-589954838.
I've ran into the same issue. Mainly due to the fact that few servers I run use a service which changed in unstable (different module options/config) so now it won't eval. I could use a separate machine for building the machines using unstable, but almost all of my infra is in stable so I don't want to make exceptions just for a few servers. And this seems like a nice and wonderful fix.
Yeah, I went ahead and just apllied that patch to morph in my packages: https://github.com/andir/infra/blob/master/nix/packages/morph-evalConfig-machinename.patch
I am still not entirely happy about that approach as now you have to specify the nixpkgs for a machine twice.
On Sun, May 24, 2020, 1:44 PM 1000101 [email protected] wrote:
I've ran into the same issue. Mainly due to the fact that few servers I run use a service which changed in unstable (different module options/config) so now it won't eval. I could use a separate machine for deployment of the machines using unstable, but almost all of my infra is in stable so I don't want to make exceptions for a few servers. And this seems like a nice and wonderful fix.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/DBCDK/morph/issues/104#issuecomment-633218674, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAE365EHELPDVAW3V2FG5SLRTECBNANCNFSM4KKYLFHQ .
I'm also rolling with the approach in https://github.com/DBCDK/morph/issues/104#issuecomment-589954838, although with a different take on my entrypoint, that allows me to set defaults and overwrite them when needed.
let
sources = import ../nix/sources.nix;
defaultArch = "x86_64-linux";
defaultPkgs = sources."nixos-20.09";
lib = import (defaultPkgs + "/lib");
machines = {
"a.local" = {
system = "aarch64-linux";
packages = sources.nixos-unstable;
};
"g.local" = {};
"j.local" = {};
"h.local" = {};
};
mkMachine = hostName: { system ? defaultArch, packages ? defaultPkgs }:
let
pkgs = import packages {
inherit system;
};
in
{ config, ... }: {
imports = [
(./machines + "/${hostName}")
];
nixpkgs.pkgs = pkgs;
deployment = {
substituteOnDestination = true;
tags = [ system ];
};
};
in
{
network = {
inherit lib;
description = "local";
evalConfig = machineName:
(machines."${machineName}".packages or defaultPkgs) + "/nixos/lib/eval-config.nix";
};
} // (lib.mapAttrs mkMachine machines)
The patch above no longer applies. This seems to work:
diff --git a/data/eval-machines.nix b/data/eval-machines.nix
index 86ba52d..4cdc426 100644
--- a/data/eval-machines.nix
+++ b/data/eval-machines.nix
@@ -5,7 +5,7 @@ let
network = import networkExpr;
nwPkgs = network.network.pkgs or {};
lib = network.network.lib or nwPkgs.lib or (import <nixpkgs/lib>);
- evalConfig = network.network.evalConfig or ((nwPkgs.path or <nixpkgs>) + "/nixos/lib/eval-config.nix");
+ evalConfig = network.network.evalConfig or (_: (nwPkgs.path or <nixpkgs>) + "/nixos/lib/eval-config.nix");
runCommand = network.network.runCommand or nwPkgs.runCommand or ((import <nixpkgs> {}).runCommand);
in
with lib;
@@ -42,7 +42,7 @@ rec {
uncheckedNodes =
listToAttrs (map (machineName:
{ name = machineName;
- value = import evalConfig {
+ value = import (evalConfig machineName) {
modules = modules machineName;
extraArgs = { nodes = uncheckedNodes; name = machineName; };
check = false;
@@ -54,7 +54,7 @@ rec {
nodes =
listToAttrs (map (machineName:
{ name = machineName;
- value = import evalConfig {
+ value = import (evalConfig machineName) {
modules = modules machineName;
extraArgs = { nodes = uncheckedNodes ; name = machineName; };
};
I think this might be related:
trace: warning: The extraArgs argument to eval-config.nix is deprecated. Please set config._module.args instead.