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?
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.
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:
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'.