Home-manager: Managing files without symlinks

Created on 3 May 2018  路  5Comments  路  Source: nix-community/home-manager

There are some configuration files that I would like to somehow manage with home-manager, but that also get changed by other tools or that you don't want to put in your home-manager config. An example of the former is the .spacemacs file which most people update directly from spacemacs. An example of the latter is the .ssh/config file which I often want to augment with servers that I do not want to put into my home-manager config (because I would like to be able to make my home-manager config public). The problem is that home-manager creates symlinks to read-only files in the nix store which causes problems for these two use cases. Is there a way this issue could be worked around?

Most helpful comment

The only way I have found to allow that is to load a mutable config from the immutable on. This requires the config file language to have include-like functionality. As an example, I'm doing this for my emacs config:

{
  home.files.".emacs.d/init.el".text = ''
    (message "Hi!")

    (setq custom-file "${toString ./custom.el}")
    (load custom-file)
  '';
}

The toString will make it so that it doesn't import custom.el into an immutable /nix/store path, but rather expands to /path/to/config/custom.el. This allows you to change the custom.el file via emacs 'customize' interface, while still keeping the other part immutable.

This can also be used to have a tmp.el file you include for temporary quick changes, which you can then transfer to home-manager to make them 'permanent'.

All 5 comments

The only way I have found to allow that is to load a mutable config from the immutable on. This requires the config file language to have include-like functionality. As an example, I'm doing this for my emacs config:

{
  home.files.".emacs.d/init.el".text = ''
    (message "Hi!")

    (setq custom-file "${toString ./custom.el}")
    (load custom-file)
  '';
}

The toString will make it so that it doesn't import custom.el into an immutable /nix/store path, but rather expands to /path/to/config/custom.el. This allows you to change the custom.el file via emacs 'customize' interface, while still keeping the other part immutable.

This can also be used to have a tmp.el file you include for temporary quick changes, which you can then transfer to home-manager to make them 'permanent'.

One possibility might be to use an _unsupported_ trick: to set the file source to a string containing the absolute path to the file that should be maintained outside the Nix store. For example,

home.file.".spacemacs".source = "${config.home.homeDirectory}/where/i/keep/my/spacemacs";

Running home-manager switch should produce a symlink ~/.spacemacs pointing to a symlink within the Home Manager generation, which in turn will point to ~/where/i/keep/my/spacemacs which is entirely your responsibility to manage.

I'm not sure I would recommend using this method, instead perhaps simply add an activation script that creates the symlink yourself? It would make it more explicit:

home.activation.linkMyStuff = dag.entryAfter [ "writeBoundary" ] ''
  ln -sf $HOME/where/i/keep/my/spacemacs $HOME.spacemacs
'';

Being more versatile on the generated paths should be mandatory for better nixos/home-manager integration (a module should be able to be installed systemwide e.g., /etc/vimrc vs userwide ~/.vimrc).
Also depending on the programs I would rather include a fixed config or have a config include a generated config (in case you sync your dotfiles with non-nix distros).

Also depending on the programs I would rather include a fixed config or have a config include a generated config (in case you sync your dotfiles with non-nix distros).

I agree with this point especially.

because I would like to be able to make my home-manager config public

A trick how to do this is to create some secrets folder, add it to the gitignore and put all the non-shared configuration into it. The files in there should be sourced in a way that they act like an overlay, the config should still be able to build without them.

I've not done this myself yet, but I know a few public NixOS configs that work this way.

Was this page helpful?
0 / 5 - 0 ratings