Document how Home Manager handles activation-time file collisions in the usage manual, including standalone backup flags, NixOS and nix-darwin module options, per-file force handling, recursive directory behavior, and out-of-store symlink sources. Also clarify the home.file-style ignorelinks option description so recursive symlink behavior is easier to understand from the generated option docs.
5.3 KiB
Keeping your ~ safe from harm
To configure programs and services Home Manager must write various things to your home directory. To prevent overwriting any existing files when switching to a new generation, Home Manager will attempt to detect collisions between existing files and generated files. If any such collision is detected the activation will terminate before changing anything on your computer.
For example, suppose you have a wonderful, painstakingly created
~/.config/git/config and add
{
# …
programs.git = {
enable = true;
userName = "Jane Doe";
userEmail = "jane.doe@example.org";
};
# …
}
to your configuration. Attempting to switch to the generation will then result in
$ home-manager switch
…
Activating checkLinkTargets
Existing file '/home/jdoe/.config/git/config' is in the way
Please move the above files and try again
This error is about a file that Home Manager wants to manage as a
symbolic link in your home directory. It is separate from package
profile collisions, which usually mention installPackages or a
collision between .../bin/... path. For package collisions, see
Why is there a collision error when switching generation?.
Resolving file collisions
The safest resolution is to inspect the existing path, move any settings you want Home Manager to manage into your configuration, and remove or move the unmanaged file before switching again.
For a standalone Home Manager installation, you can ask Home Manager to move unmanaged non-symlink paths out of the way during activation:
home-manager switch -b backup
With the command above, a colliding ~/.config/git/config is moved to
~/.config/git/config.backup before Home Manager links the managed
file. If the backup path already exists then activation still aborts, so
choose an extension whose backup path does not already exist.
Standalone activation can also run a custom command for each collision:
home-manager switch -B trash-put
The command receives the colliding path as an argument and must move or
remove that path. If both -B and -b are set, the custom command takes
precedence; the command may still use the
HOME_MANAGER_BACKUP_EXT environment variable set by -b.
When Home Manager is used as a NixOS or nix-darwin module, configure the corresponding module options instead of passing standalone command line flags:
{
home-manager.backupFileExtension = "backup";
}
or
{
home-manager.backupCommand = "${pkgs.trash-cli}/bin/trash-put";
}
If both {option}home-manager.backupCommand and
{option}home-manager.backupFileExtension are set, the command takes
precedence. The extension is still exported to the command as
HOME_MANAGER_BACKUP_EXT, so the command can use it when implementing
its own backup naming. With
{option}home-manager.backupFileExtension, Home Manager refuses to
replace an existing backup path unless
{option}home-manager.overwriteBackup is enabled:
{
home-manager.backupFileExtension = "backup";
home-manager.overwriteBackup = true;
}
::: {.warning}
{option}home-manager.overwriteBackup allows activation to clobber
existing backup files. Only enable it when those backup paths are
disposable.
:::
For individual files, many file options also support force = true:
{
home.file.".config/example" = {
source = ./example;
force = true;
};
}
This skips the collision check for the affected target and lets Home Manager replace the existing file or link. Use it sparingly; it can silently delete local changes.
Backup commands and backup extensions are intended for unmanaged
non-symlink paths. If the colliding target is an unmanaged symbolic
link, move it manually or use force = true after checking that the
link target is safe to replace.
Advanced file behavior
The notes below apply to {option}home.file and to options based on the
same file type, such as {option}xdg.configFile.
When a file source is a directory, {option}home.file.<name>.recursive
changes how the directory is linked. With the default recursive = false, the target is one symbolic link to the source directory. With
recursive = true, Home Manager creates a matching directory tree and
links each leaf file into it.
Recursive directory linking has special overlap behavior. A direct
duplicate target, such as two managed files both targeting foo, is an
error. If a recursively linked directory provides foo/bar and another
managed file also targets foo/bar, Home Manager keeps the recursive
file by default and ignores the overlapping regular file.
The {option}home.file.<name>.onChange hook runs after the new files
are linked. For recursive file entries, the hook is always run, so it
should be written to be safe even when no leaf file actually changed.
Normally a path assigned to {option}home.file.<name>.source is copied
or linked through the Nix store. To make Home Manager create a link to a
live path outside the store, use
config.lib.file.mkOutOfStoreSymlink:
{ config, ... }:
{
home.file.".config/example".source =
config.lib.file.mkOutOfStoreSymlink ./example;
}
This is useful when the target should follow changes to a mutable file or directory outside the store.