-
-
Notifications
You must be signed in to change notification settings - Fork 363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support multiple versions of nixpkgs in one network #665
Conversation
Having a machine named foo, described as: foo = { # ...snipped... deployment.nix_path.nixpkgs = (builtins.filterSource (path: type: type != "directory" || baseNameOf path != ".git") ./../nixpkgs); }); will have the custom nixpkgs set in the `NIX_PATH` as `nixpkgs=path-to-custom-nixpkgs`. Note this does not work with foo = { config, ... }: {... machines, but having a second nix file in the network would work, and also: let canary = machine: { deployment.nix_path.nixpkgs = (builtins.filterSource (path: type: type != "directory" || baseNameOf path != ".git") ./../nixpkgs); imports = [machine]; }; machine = { ... }: { # your machine config }; in { machineA = machine; machineB = canary machine; } Note that because this uses scopedImport, the nixops network and machines may use `import <nixpkgs>` and have a consistent view of nixpkgs.
Thank you, @cleverca22, for the excellent suggestions & help with scopedImport. |
Multiple nixpkgs look like an overkill to me. Usually overriding individual packages and using custom modules is enough. |
Depends on the size and variety of the network. Three critical use cases of mine:
I'm practically unable to use nixops without this patch, which I'm doing already: (pkgs.nixops.overrideAttrs (x: {
patches = [
(pkgs.fetchpatch {
# Allow specifying custom nixpkgs for a machine
url = "https://github.com/NixOS/nixops/pull/665.patch";
sha256 = "0q7sk3fq3x7r2sh6f853hcbykm74px9i0m5bqhg2fi0s4nckj5x0";
})
];
})) |
@@ -103,6 +103,13 @@ in | |||
''; | |||
}; | |||
|
|||
deployment.nix_path = mkOption { | |||
default = {}; | |||
type = types.attrsOf types.str; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe path
is more adequate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be nixPath
. (NixOS already has a nix.nixPath
option.)
Arguably the type should be types.listOf types.str
, like nix.nixPath
. Nix search path entries are not required to have a prefix.
Does it work well with modules, overrides, etc.? I mean, if I use some custom modules overriding some pkgs, which pkg set will be overridden? |
And, of course, there is a plain workaround - different deployments with different nix path :) |
It works well with
like
Yes, different deployments or nixops deploy with different |
I mean {
# ...
machineFoo = {config, ...} : {
imports = [ <my-modules> ]; # with `nixpkgs.config.packageOverrides`, probably recursive.
# ...
};
# ...
} My point is to be able to use hierarchy of modules (via |
As far as I understand, you have to evaluate machine's spec in order to get it's specific nix path. And once evaluated, new nix path will override all packages overridden during evaluation. Correct? P. S. Probably I'm wrong :) |
|
||
importSources = | ||
(concatMap (module: | ||
if (!builtins.isFunction module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't it be a function? Is module
a "machine" definition? If yes, it usually a function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #665 (comment): we can't introspect a function in this way.
No, we don't evaluate any functions to find the nix path. This also answers your question about why it can't be a function: We can't call a machine's function without passing in a For this reason, the imports and overrides all work just fine. Examples, this works: {
machine = {
deployment.nix_path.nixpkgs = "https://github.com/nixos/nixpkgs/archives/master.tar.gz";
nixpkgs.config.packageOverrides = {};
};
} This won't work, because it is a function and we can't fetch the nix_path without first executing the function: {
machine = { ... }: {
deployment.nix_path.nixpkgs = "https://github.com/nixos/nixpkgs/archives/master.tar.gz";
};
} This will work: {
machine = {
deployment.nix_path.nixpkgs = "https://github.com/nixos/nixpkgs/archives/master.tar.gz";
imports = [{ ... }: {
nixpkgs.config.packageOverrides = {};
}];
};
} |
Ok, I think I understood. What you are doing is exactly I remember a try to make nixops modular with a means to define nix path. This didn't end well. See https://github.com/zalora/nixops. I think wrappers of nixops is more flexible, safer and cleaner solution ( |
NixOS modules is an extremely cool and powerful mechanism, maybe underestimated yet. So I'd say no to features that do not integrate flawlessly into module system (like not working with functions) |
Yes, that is true :( a What if we took advantage of the {
network = {
description = "Load balancer test";
default_nix_path = {
nixpkgs = "./stable-nixpkgs";
};
nix_path_overrides = {
machineB = {
nixpkgs = "./unstable-nixpkgs";
};
};
};
machineB = { ... }: {};
} Now it is out of band as far as the machine is aware, yet declared in the file. |
Maybe |
The problem Igor is pointing out is that if you inside a module set the Nix
path it may or may not take effect, depending on if it was set inside a
function or not.
…On Tue, May 16, 2017 at 8:21 AM Domen Kožar ***@***.***> wrote:
Maybe network.nixpath and deployment.nixpath?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#665 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAErrCbxpkWJUB-CwEsHSN0PUvOADQeXks5r6ZS7gaJpZM4NaEED>
.
|
Well, yes. To me, the only feasible way is to have nix path defined somewhere out of machine's "mega-module". I don't really care if it would be bash or nix :). You can define you |
|
||
__nixPath = importSources; | ||
|
||
machineImport = builtins.scopedImport { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, scopedImport
slows down evaluation because it disables the file cache in the evaluator. If that's still the case, machineImport
should be something like machineImport = if __nixPath == [] then import else builtins.scopedImport ...
.
Semantically, it would be cleanest to move the NixOS configuration of a machine to an option below the machine, so we can add options like
This allows
This is more elegant than having a separate However it's not clear how to do this in a backwards-compatible way... |
I'm really interested in this feature. Any chance this would be merged? |
I am also interested in this feature. @grahamc, did you ever move forward with your PR attempt? |
Hello! Thank you for this PR. In the past several months, some major changes have taken place in
This is all accumulating in to what I hope will be a NixOps 2.0 My hope is that by adding types and more thorough automated testing, However, because of the major changes, it has become likely that this If you would like to see this merge, please bring it up to date with Thank you again for the work you've done here, I am sorry to be Graham |
Having a machine named foo, described as:
will have the custom nixpkgs set in the
NIX_PATH
asnixpkgs=path-to-custom-nixpkgs
.Note this does not work with foo = { config, ... }: {... machines, but
having a second nix file in the network would work, and also:
Note that because this uses scopedImport, the nixops network and
machines may use
import <nixpkgs>
and have a consistent view ofnixpkgs.
Closes #649 (comment)