Hah, me too. :)
> I really love NixOS, but I'm at best lukewarm on Nix as a language.
My biggest issue as of now is that the documentation focuses on which individual files you need to touch, but doesn't really explain the big picture. For example, /etc/nixos/configuration.nix contains a function that takes { config, pkgs, ... }. Where do these come from? Where can I find documentation for them? What is in the ellipsis? More generally, where can I find a high-level overview of how the different components interact with each other during, for instance, nixos-rebuild?
To answer your question, { config, pkgs, ... }: declares a function that takes an attribute set containing values for "config" and "pkgs". The ellipsis indicates that it's okay to pass extra attributes.
Nixos-rebuild calls your function by: with (import <nixpkgs> {}); callPackage ./configuration.nix {}
<nixpkgs> is a file containing the set of all symbols (packages are under pkgs, Nix config lives in config, etc.) like a root namespace. callPackage inherits all those symbols and passes them to the function, which is how they got bound.
0. https://nixos.org/nixos/nix-pills/index.html
1. https://learnxinyminutes.com/docs/nix/
EDIT: I guess it's also like Git where it's really confusing until a moment of enlightenment where it all makes sense.
Here is some context, with corresponding criticsm by the person behind Guix, which might give some interesting insights
https://discourse.nixos.org/t/best-resources-for-learning-ab...
What about using .gitIgnore or using a git submodule for them? Ideally you could have one central repo for nix workflows, and then just have git submodule point to the repo's subfolder, so when you do submodule init, it pulls down that specific folder. Otherwise, you could use .gitignore and a symlink to that as you might do with your dotfiles if you manage those through version control.
I think so far my preference might actually be to just have a separate folder, separately versioned, containing my nix expressions for doing work, centrally. But then I kinda want a system for launching into them so I'm not constantly calling nix-shell manually, and that's where I wonder if I actually just want some more tooling for this here.
For shells, I have a custom `env-python [-p <packageNames>] [-f <extraPaths>]` which brings a fully-configured VS Code (with per-environment config), debuggers and neovim with all the trimmings. Everything inherits in layers so I can add different kinds of environments quite easily.
If you'd like, I can share my dotfiles with you. It's pretty custom but the beauty of Nix is you can clone and run!
Have a look at home manager[0], I use it and have been very happy so far.
I'm not familiar with Jetbrains or dotnet, but you could probably use makeWrapper to make a "jetbrains-with-dotnet" package, something like this:
with import <nixpkgs> {};
runCommand "jetbrains-with-dotnet"
{
inherit dotnet jetbrains;
buildInputs = [ makeWrapper ];
}
''
mkdir "$out/bin"
makeWrapper "$jetbrains/bin/jetbrains" "$out/bin/jetbrains-with-dotnet" --prefix PATH : "$dotnet/bin"
''
This package provides a `jetbrains-with-dotnet` script, which adds the `bin` directory of the `dotnet` package to the start of $PATH then runs the `jetbrains` executable from the `jetbrains` package.Installing such a package globally will put the `jetbrains-with-dotnet` script in your PATH, but it won't pollute your system with anything from dotnet or jetbrains: those will be downloaded/built and cached in the Nix store, but are only accessible via that script.
I use nix-buffer[0], which lets Emacs pick up the environment automatically when I open any file in the project. And as long as you only use setq-local it'll stay scoped to those files, "normal" files still open in the regular user environment. It's even seamless to keep files from multiple such projects open at once.
What do you mean it won't work? I think rider will launch without dotnet, If not then rider dependencies should be fixed to include dotnet. Otherwise, it's the same case for any other distro.
> but I don't think it belongs in version control.
Why not? In fact you should put them in vc since anyone with nix can easily build the program exactly same as on your machine.
> Should it be personally suited, with my IDE and developer tools?
You can create different nix files: e.g. in ide/default.nix you can inherit your default shell.nix and put extra dependency. You may want to skip checking this in vc though.
For a good organization of nix files look at the reflex-frp haskell project.
Of course, if you wanted to use rider without dotnet, you could. But it doesn't fit my workflow.
And yes, like I said, this is still better than the situation on other distros, but it feels like it's close to being even better than that.
>Why not? In fact you should put them in vc since anyone with nix can easily build the program exactly same as on your machine.
For starters, because I work on a lot of projects that aren't mine. But also, because it's not really standardized.
Like there's a fairly standard practice for putting a package.json in a repository but not really so for default.nix. And it's also not exactly orthogonal to Nixpkgs; if you wanted your project to be in Nixpkgs, your expression would be (slightly) different. That is probably solved by importing the Nixpkg into default.nix, but I haven't tried yet.
Finally, this doesn't capture everything. If I want an environment where I have VSCode with the Go extension installed, I would prefer that to be isolated from other VSCode instances.
That's why I think I want more than just a Nix expression. The tools to do what I want are all here, but the tool to automate the workflow is not.
You can absolutely do this by overriding the derivations. The tool to automate your workflow is there(just create a bunch of nix files and a makefile to call nix-shell/nix-build), but not as convenient as you might like.
The specific reason is Ruby + RoR leading to nokogiri... which is something people have been dealing with for several years and there's no solution, and I lost the one file where I managed to get it working good enough to launch rubymine in a way that sees everything necessary.
Similar issues crop in other places, due to how Nix dependencies are handled like unflattened node_modules at times :/
Being able to run `nix-shell -p` and get a shell with a program installed is super cool. Also, being able to add a package to the system declaratively is super cool. However, one thing I wonder about is workflows.
For example, I have a lot of Jetbrains IDEs installed for various languages, but I don't want to pollute my global environment with tools, especially command line tools that pollute the PATH. Let's say I want to use Jetbrains Rider. I can easily start a shell with the dotnet SDK with `nix-shell -p dotnet`, then start Rider under that shell. This is OK, but it feels wrong to me. It feels weird that launching Rider outside of nix-shell won't ever work, yet it's installed globally. And yet, I also kind of want it to be globally installed...
Another solution would be to have Nix expressions for every project I work on. This actually seems better and I've adopted it for a couple projects, but it also irks me because it feels half-baked. I don't know where to put these expressions other than next to the project, but I don't think it belongs in version control. Also, I'm very mixed for what belongs in these environments. Should it be personally suited, with my IDE and developer tools? If I do that, I can't share the same code I'd use for my tooling as I would for my Nixpkg (assuming there is a nixpkg) which leads to a divergence I don't like. (Though maybe that can be solved?)
I almost want a robust system of working environments that encapsulates this. So, I could think about my Nix workflows as separate environments. Declarative or imperative, and ideally with more encapsulation than a typical nix-shell. Maybe instead of orienting my workflow around opening an IDE and opening a project, I can orient it around opening a project environment and then opening an IDE inside of it.
At this point I'm just rambling. I still prefer NixOS for practical reasons, since it makes my complex IOMMU setup a cinch and keeps all of the configuration for it surfaced and documented. But dang, the potential here to shift workflow paradigms is enormous, it feels.