Skip to content

Comment on Home in Nix – dotfile management

Comments

I tried out Nix recently, with the intention of using it to get declarative management of my user account.

I discovered too late that Nix basically has no support for this.

While NixOS has some very nice features for declarative setup, user environment management boils down to terminal commands for "install package X, remove package Y".

The mentioned home-manager seems more of an awkward hack than a good solution in my view. It builds up a parallel package repository that you have to use besides the actual packages, and requires a lot of additional work if you want to customize something.

In my understanding (possibly incorrent?) it is also not actually immutable, but just dumps down files into $HOME, losing the most interesting aspect of Nix.

In the end I ditched it and stuck to my Ansible setup.

Nix is a great approach, and definitely worth a look, if you can stomach the other downsides (see below). But right now I would only recommend it for deterministic server builds or isolated dev environments, not for managing you main setup.

* Problems:

- There is plenty of documentation, but it is often incoherent, messy, missing important explanations, and it is generally very awkward to get a good insight and understanding of how all the parts fit together.

- The language... it is full of confusing oddities; clearly something that has grown peace by piece. Switching to something more coherent like Gluon (also functional, https://github.com/gluon-lang/gluon) would seem like a better approach to me.

- Packages: The quality can be very hit and miss. I discovered several that are written poorly. Plenty are also outdated/unmaintained. But: considering the niche nature of Nix, the amount of packages is actually quite impressive.

Nix/OS definitely has some rough edges and discovery problems.

I can't comment directly on home manager, and I have had to put a lot of work into adopting Nix, but FWIW I'm happily using it to manage my NixOS desktop at home (since early 2018; my first daily-driver Linux system) and my macbook (since late 2018--though, caution: Nix hasn't really settled into Catalina yet).

Not quite sure how to express it. I guess the ecosystem isn't yet a full-throated embodiment of its own vision for computing. But, if you buy into the vision enough to sweat a little for it, it is livable.

The mentioned home-manager is more of an awkward hack than a good solution in my view. Tt's not actually immutable, but just dumps down files into $HOME,

That's actually not true. Each home-manager generation is immutable and in the Nix store. E.g., the last two generations on my MacBook:

    home-manager generations | head -n2
    2019-12-23 12:05 : id 12 -> /nix/store/6rig5ip0swmnnfcvgm221n5lig3xsh18-home-manager-generation
    2019-12-12 12:40 : id 11 -> /nix/store/8as4k5x7i5bhf3wjvlcczhx8w2680k46-home-manager-generation
But it symlinks certain files from the store in the home directory, because some programs (e.g. shells) have hardcoded paths to configuration files.

losing the most interesting aspect of Nix

Similarly to the declarative NixOS configuration, you can switch between home-manager generations, etc. It's a purely declarative configuration.

It also basically builds up a parallel package repository that you have to use besides the actual packages,

What do you mean by this? home-manager also uses the Nix store. E.g., my home-manager configuration contains ripgrep in the declarative package configuration:

    $ realpath $(which rg)
    /nix/store/hww0h39bs56hp17ynxcjrk0imgqill07-ripgrep-11.0.2/bin/rg
There is plenty of documentation, but it is often incoherent, messy, missing important explanations,

I fully agree! Often one has to read derivations in nixpkgs to understand how things are done.

The language... It is full of oddities and basically a mess

I disagree. I didn't like it when I started using Nix and seriously looked at Guix because it used scheme. Now, 1.5 year later, I like Nix as a language. It's just a small, functional language.

---

I think the biggest barrier of the Nix ecosystem is that you can't really use NixOS or Nix in a meaningful way without also learning the Nix language and some of the intricacies of writing derivations. So, you are pretty much all-in or it will be a frustrating experience. So, I understand your point about only using NixOS on reproducible servers. I also use NixOS on my desktop (and love it), but admittedly, it's only doable when you invest enough time to learn things.

If someone wants an immutable system with transactional installs and updates, Fedora Silverblue is probably a much easier entry-point, because you do not really have to understand OSTree et al. to use it.

Now, 1.5 year later, I like Nix as a language. It's just a small, functional language.

If nixos used a different language (e.g. gluon), do you think you would have become more comfortable quicker?

Nix as a language is tiny. If you know functional programming at all you won't have any trouble with it and can "learn" it in days if you put in the effort. NixOS isn't complicated because of the language.

I don't know Gluon (from a quick glance, it looks similar to Haskell and ML). But I do not think it will help much. Nix is a small, lazy, functional language. Being a lazy functional language, it will be more difficult for people without a FP background. But laziness and purity provides a lot of benefits.

I think the problem is more about documentation and expectations:

- Nix only has a small number of builtins. A lot of useful functions are in nixpkgs. As a consequence, you often have to look in two places to find if there is an existing function that does what you want to do. Added to that, some functions are undocumented and can only be discovered through the REPL or by reading the relevant nixpkgs sources. Then some functions do have documentation, but the documentation is very terse, does not contain good examples, etc. I think things would be clearer if Nix had a documented standard library and nixpkgs would only be focused on providing package derivations and NixOS modules.

- Expectation-wise: I think a lot of people do not expect to have to learn a new language when starting to use a package manager and/or distribution. This leads to treating derivations akin to RPM spec files (which is what I did in the beginning), which becomes frustrating very quickly.

Disclaimer: I am by no means a Nix expert. These are my observations from learning Nix myself since last year.

Nix is a small, lazy, functional language. Being a lazy functional language, it will be more difficult for people without a FP background. But laziness and purity provides a lot of benefits.

Many functional languages have lazy evaluation, and they do provide benefits. However, unfortunately, this concept has leaked into other areas of programming. In particular, many database ORMs use lazy evaluation to pull data. In one step, you create a database query, then pass that off to another function or class. Then, when it's off in another package and evaluated the query is made.

The main problem with lazy evaluation of database queries is that it treats a database evaluation like normal code, even though under the hood there may be network access, caching, and if you're not careful duplicative database pulls.

Generally, there should be a rule in programming languages that when you make a network call, the programmer has clear visibility into when that is happening. Hiding it with fancy syntax is more of a negative than a positive.

The documentation is not much aimed on a developer workflow.

The `shell.nix` files make it easy to place the environment setup in your repository. The file contains the list of packages that you need and you can make these packages available in just one shell by calling `nix-shell`.

Here's an example of a `shell.nix` file:

    with import <nixpkgs> {};

    stdenv.mkDerivation {
      name = "cv-env";
      buildInputs = [
        libxslt gnumake openjdk entr
      ];
    }

I tried to do this, but I ran into way too many problems.

Each approach I tried failed because of some limitation that made the whole thing awkward or pointless. (like symlinking immutable config files into $HOME)

This admittedly might have been exacerbated by my shallow understanding.

Each approach I tried failed because of some limitation that made the whole thing awkward or pointless.

Could you explain the limitations that you've run into? I have been using shell.nix + direnv + some caching for 1.5 years now and I have been very happy with it.

The only thing I disliked is that shell.nix is underspecified in the sense that it by default relies on your configured nixpkgs channel. So, I am now using niv to pin down nixpkgs and other package sets (mostly my own) to specific revisions. Once Nix flakes become mainline, this can be done easily without third-party tools.

I do this. When I run into problems with a shell.nix, I fix the underlying project, or abandon it. Nix is ruthless but being ruthless is required in the face of the task of taming decades of terrible software.

That's missing the point of immutable reproducible builds i did something similar with arch and ansible long time ago. And it would end up in weird state quite often https://github.com/dejanr/archbox

In the end I ditched it and stuck to my Ansible setup.

For your own workstation- what OS?

Have you got these in github or somewhere i could take a look?

I migrated to this new setup slowly. First of all, I think separating things out from the main Nixpkgs repo is valuable, particularly for this whole new scope of user configuration. Based on what you've written I think you may be missing part of the power of home-manager. Worst case scenario, this is how I manage neovim, you can just write a file that sources a bunch of local files into the correct location on your computer. See https://github.com/HugoReeves/nix-home/tree/master/program/e... ```nix { config, lib, pkgs, ... }: { xdg.configFile."nvim/coc-settings.json".source = ./configs/coc-settings.json; xdg.configFile."nvim/fixers.vimrc".source = ./configs/fixers.vimrc; xdg.configFile."nvim/flags.vimrc".source = ./configs/flags.vimrc; xdg.configFile."nvim/general.vimrc".source = ./configs/general.vimrc; xdg.configFile."nvim/init.vimrc".source = ./configs/init.vimrc; xdg.configFile."nvim/init.vim".source = ./configs/init.vim; xdg.configFile."nvim/keys.vimrc".source = ./configs/keys.vimrc; xdg.configFile."nvim/lsp.vimrc".source = ./configs/lsp.vimrc; xdg.configFile."nvim/status-line.vimrc".source = ./configs/status-line.vimrc; xdg.configFile."nvim/themes.vimrc".source = ./configs/themes.vimrc; xdg.configFile."nvim/vista.vimrc".source = ./configs/vista.vimrc; } ``` So at worst it's an overly complicated way to source files into your home directories. However with the home-manager supported configuration it's much better in my opinion.

In regards to the problems. 1. I totally agree. Everyone using Nix has seen this as an issue for a while, and I'm not entirely sure how it can be fixed in the near term. I would say that Nix is for people who love to tinker and enjoy spending time on this sort of thing. If that's you, go to the riot chat or the subreddit and ask questions there. r/nixos 2. Haven't seen gluon before, interesting. Nix is functional which is key and it's focus as a configuration language offers it some great advantages when used for configuration. I believe a gluon is not feasible as it's not functional. The Nix team seems open to changing parts of the language to improve it, they are looking at removing the special url syntax for example. 3. No comment. I haven't really looked at this space. Nixpkgs if that is what you are referring to is pretty well maintained, particularly for the configuration-less executables.

I use Nix for declarative management of my user account using home-manager. I think you might be missing something.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.