
Home in Nix – dotfile management - devhugo
https://hugoreeves.com/posts/2019/nix-home/
======
the_duke
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](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.

~~~
danieldk
_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.

~~~
DerSaidin
> 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?

~~~
danieldk
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.

~~~
speedplane
> 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.

------
gbrown_
My $HOME _is_ a git repo for my dotfiles, with a .gitignore containing just
"*". Simple, zero abstractions, no need for additional management.

~~~
deepaksurti
Further, you can create a bare git repo and make $HOME it's working tree.

More details here [1].

[1]
[https://news.ycombinator.com/item?id=11071754](https://news.ycombinator.com/item?id=11071754)

------
trevorrr
Would prefer GNU stow for simplicity.

[https://www.gnu.org/software/stow/](https://www.gnu.org/software/stow/)

~~~
devhugo
I've looked at and read about other's experiences with stow in the past. I'm
uncertain about this so please correct me where I am wrong, but the issues I
see with stow are: 1\. It's somewhat dated/may have a tail of legacy features
2\. I'm unsure of it's value beyond of what can be provided via the Git Bare
Repo solution linked in the intro of my post. 3\. More importantly, it's not a
programmable solution where you can override default files based on the
current system. The main value proposition I see in my system is that I can
define a single default configuration for, say, my terminal Alacritty, and
override the configuration where necessary based on either my user, machine or
role. Nix is a programming language, so I essentially have my system
configuration managed via a programming language and can control things with a
great level of detail.

~~~
padthai
I use Stow, it is simple and only does a few things, but for a lot of users
like me it is more than enough:

1\. Probably it will not receive more features any time soon.

2\. You can have several configurations and mix them, also it makes very easy
to adopt changes from the current system and/or rollback changes.

3\. No, it is not programmable, but you can have several folder for different
systems and configurations. I for example have a folder called unix for all
*nix systems, other called x11 for x11 programs, darwin for macOS, etc. You
could do the same with roles.

If you want really fine grained control over machine/user/role, it is not
enough, and it does not take into account package managing at all.

I use a mix of Stow/Ansible for Desktops and HashiCorp/Ansible for the
`cattle`. Nix is more powerful than my setting, but I still need to evaluate
if it is flexible enough for the orgs I work with.

------
hrchak
I have very similar setup
[https://github.com/dejanr/dotfiles](https://github.com/dejanr/dotfiles) it
was inspired by
[https://github.com/peel/dotfiles](https://github.com/peel/dotfiles) and few
other repositories.

Also i still symlink some stuff like stow is doing, but with few shell
scripts. The main difference is that my dotfiles are not start with '.'.

Idea is to move everything to nix, so that when you rollback, you rollback
your dotfiles as well.

What i wish maybe, is that i used home manager but that some future focus.

------
tomerbd
stay simple, simple dot files, don't create overkill work for yourself so you
don't need to manage your dot files.

------
tyrion
Nice post, thanks for sharing. I currently use vcsh and myrepos and they work
great for me. Now that I switched to Nixos maybe I could give home-manager a
try.

I wrote about my approach here in case you are interested (
[https://germano.dev/dotfiles/](https://germano.dev/dotfiles/) )

~~~
devhugo
Interesting. Home manager will enable you to manage your dotfiles. The more
interesting proposition comes from Nix. I've absolutely loved using it in
general and run NixOS by choice as my desktop OS. The great thing about using
Nix and Home Manager to manage dotfiles is that your configuration is defined
in a _programming langauge_. You have broad scope to control things based on
whatever environment you are deploying the files to. It's a really powerful
solution, it just takes a bit more time than some other dotfile systems. Give
Home Manager a go if you have time to tinker, and if you have questions feel
free to contact me through my email on my homepage.

------
DarkWiiPlayer
I just clone my dotfile repo from github into ~/darkrc and include the config
files I want on each system, so my ~/.bashrc will have a "source
$HOME/darkrc/bashrc" at the end, ~/.config/ranger/rc.conf will have "source
~/darkrc/ranger.conf", etc.

~~~
devhugo
That's certainly one option. The unique thing about dotfiles is that everyone
has a different 'best solution'. The setup outlined in my post has the
advantage of being highly configurable and programmable. However, for some
people it might make more sense to use a plain git repo with symlinks as
installing Nix on all their devices could be a nonstarter. I'm curious, what
do you use to manage tools that don't have a `source $SOME_PATH` option. Do
you symlink?

~~~
pletnes
I used to symlink and have a simple dotfiles repo, but this forces you to have
exactly identical rc files. Different computers simply need different setups,
so I started with ansible and a few playbooks running locally.

~~~
roryrjb
This was posted recently
[https://drewdevault.com/2019/12/30/dotfiles.html](https://drewdevault.com/2019/12/30/dotfiles.html),
but I actually liked the idea of using uname, hostname etc in constructing
$PATH and even though I was already using git to track my dotfiles I adapted
some parts of my setup like Drew describes and made $HOME a git repo itself
ignoring everything by default. Works quite well across different OSs,
machines and shells.

------
streb-lo
I for one am waiting for systemd homed.

~~~
jacobush
As always with anything about systemd, it's impossible to know if it's satire
without looking at the source code. Sometimes, not even then.

