Nix is an expression language, not a programming language. The end result of any piece of code must always be a value.
What’s the value of your expression when options.location.atHome = true?
It’s undefined? That’s not legal. Therefore, an if expression must always have an else branch.
The next part of your confusion is that the return value of your expression is an attrset binding which is not a valid data type in Nix. You can only do it the other way around; bind an attrset key to the value of an expression like this:
{
foo = if cond then "bar" else "baz";
}
You could use lib.optionals as @jlode mentioned. It’s effectively the same as
networking.nameservers = if (options.location.atHome == false) then
[ "9.9.9.9" "149.112.112.112" ]
else
[ ];
For NixOS module purposes, there is the mkIf function which effectively “unsets” the value if the condition is false.
This would be considered cleaner since you’re explicitly saying that the value should only be touched if the condition is true; with optionals you’d explicitly be setting the value to [ ] eventhough you didn’t intend to set it at all.
Some people have written themselves a mkIfElse wrapper for this purpose. I proposed it should be added to Nixpkgs but I don’t think that has happened yet.
I get errors: error: attribute 'config' already defined at /etc/nixos/file.nix I have read that there can be only one config, so is two working a side effect or something?
Where can I read up on the mkMerge?
I have also tried putting mkMerge on top – that worked.
Now i have
Yup, that’s the expected solution to the first half of this post.
In Nix, lib.mkIf !atHome is parsed as ‘exproperatorexpr’, and ! isn’t an infix binary operator. When using ! or prefix - at the beginning of an argument to a function, you need to wrap it in parentheses (much like Haskell, if you’re familiar): lib.mkIf (!atHome).