[[ch-nix-flakes]]
== Nix Flakes

:nixos-wiki-flakes: https://nixos.wiki/wiki/Flakes

Home Manager is compatible with {nixos-wiki-flakes}[Nix Flakes]. But
please be aware that the support it is still experimental and may
change in backwards incompatible ways.

Just like in the standard installation you can use the Home Manager
flake in three ways:

1. Using the standalone `home-manager` tool. For platforms other than
NixOS and Darwin, this is the only available choice. It is also
recommended for people on NixOS or Darwin that want to manage their
home directory independently of the system as a whole. See
<<sec-flakes-standalone>> for instructions on how to perform this
installation.

2. As a module within a NixOS system configuration. This allows the
user profiles to be built together with the system when running
`nixos-rebuild`. See <<sec-flakes-nixos-module>> for a description of
this setup.

3. As a module within a {nix-darwin}[nix-darwin] system configuration.
This allows the user profiles to be built together with the system
when running `darwin-rebuild`. See <<sec-flakes-nix-darwin-module>>
for a description of this setup.

[[sec-flakes-prerequisites]]
=== Prerequisites

* Install Nix 2.4 or later, or have it in `nix-shell`.

* Enable experimental features `nix-command` and `flakes`.
+
** When using NixOS, add the following to your `configuration.nix` and rebuild your system.
+
[source,nix]
nix = {
  package = pkgs.nixFlakes;
  extraOptions = ''
    experimental-features = nix-command flakes
  '';
};
+
** If you are not using NixOS, add the following to `nix.conf` (located at `~/.config/nix/` or `/etc/nix/nix.conf`).
+
[source,bash]
experimental-features = nix-command flakes
+
You may need to restart the Nix daemon with, for example, `sudo systemctl restart nix-daemon.service`.
+
** Alternatively, you can enable flakes on a per-command basis with the following additional flags to `nix` and `home-manager`:
+
[source,console]
----
$ nix --extra-experimental-features "nix-command flakes" <sub-commands>
$ home-manager --extra-experimental-features "nix-command flakes" <sub-commands>
----

* Prepare your Home Manager configuration (`home.nix`).
+
Unlike the channel-based setup,
`home.nix` will be evaluated when the flake is built,
so it must be present before bootstrap of Home Manager from the flake.
See <<sec-usage-configuration>> for introduction about
writing a Home Manager configuration.

[[sec-flakes-standalone]]
=== Standalone setup

To prepare an initial Home Manager configuration for your logged in user,
you can run the Home Manager `init` command directly from its flake.

For example, if you are using the unstable version of Nixpkgs or NixOS,
then to generate and activate a basic configuration run the command

[source,console]
$ nix run home-manager/master -- init --switch

For Nixpkgs or NixOS version 23.05 run

[source,console]
$ nix run home-manager/release-23.05 -- init --switch

This will generate a `flake.nix` and a `home.nix` file in
`~/.config/home-manager`, creating the directory if it does not exist.

If you omit the `--switch` option then the activation will not happen.
This is useful if you want to inspect and edit the configuration before activating it.

[source,console]
----
$ nix run home-manager/$branch -- init
$ # Edit files in ~/.config/home-manager
$ nix run home-manager/$branch -- init --switch
----

Where `$branch` is one of `master` or `release-23.05`.

After the initial activation has completed successfully then building
and activating your flake-based configuration is as simple as

[source,console]
$ home-manager switch

It is possible to override the default configuration directory, if you want.
For example,

[source,console]
----
$ nix run home-manager/$branch -- init --switch ~/hmconf
$ # And after the initial activation.
$ home-manager switch --flake ~/hmconf
----

[NOTE]
====
The flake inputs are not automatically updated by Home Manager.
You need to use the standard `nix flake update` command for that.

If you only want to update a single flake input,
then the command `nix flake lock --update-input <input>` can be used.

You can also pass flake-related options
such as `--recreate-lock-file` or `--update-input <input>`
to `home-manager` when building or switching,
and these options will be forwarded to `nix build`.
See the {nixos-wiki-flakes}[NixOS Wiki page] for details.
====

[[sec-flakes-nixos-module]]
=== NixOS module

To use Home Manager as a NixOS module,
a bare-minimum `flake.nix` would be as follows:

[source,nix]
----
{
  description = "NixOS configuration";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = inputs@{ nixpkgs, home-manager, ... }: {
    nixosConfigurations = {
      hostname = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          ./configuration.nix
          home-manager.nixosModules.home-manager
          {
            home-manager.useGlobalPkgs = true;
            home-manager.useUserPackages = true;
            home-manager.users.jdoe = import ./home.nix;

            # Optionally, use home-manager.extraSpecialArgs to pass
            # arguments to home.nix
          }
        ];
      };
    };
  };
}
----

The Home Manager configuration is then part of the NixOS configuration
and is automatically rebuilt with the system when using the appropriate command
for the system, such as `nixos-rebuild switch --flake <flake-uri>`.

You can use the above `flake.nix` as a template in `/etc/nixos` by

[source,console]
$ nix flake new /etc/nixos -t github:nix-community/home-manager#nixos

[[sec-flakes-nix-darwin-module]]
=== nix-darwin module

The flake-based setup of the Home Manager nix-darwin module
is similar to that of NixOS. The `flake.nix` would be:

[source,nix]
----
{
  description = "Darwin configuration";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    darwin.url = "github:lnl7/nix-darwin";
    darwin.inputs.nixpkgs.follows = "nixpkgs";
    home-manager.url = "github:nix-community/home-manager";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = inputs@{ nixpkgs, home-manager, darwin, ... }: {
    darwinConfigurations = {
      hostname = darwin.lib.darwinSystem {
        system = "x86_64-darwin";
        modules = [
          ./configuration.nix
          home-manager.darwinModules.home-manager
          {
            home-manager.useGlobalPkgs = true;
            home-manager.useUserPackages = true;
            home-manager.users.jdoe = import ./home.nix;

            # Optionally, use home-manager.extraSpecialArgs to pass
            # arguments to home.nix
          }
        ];
      };
    };
  };
}
----

and it is also rebuilt with the nix-darwin generations.
The rebuild command here may be `darwin-rebuild switch --flake <flake-uri>`.

You can use the above `flake.nix` as a template in `~/.config/darwin` by

[source,console]
$ nix flake new ~/.config/darwin -t github:nix-community/home-manager#nix-darwin
