How to use git with flakes for nixos config

I have been following vimjoyer’s Ultimate NixOS Guide:

I know have my nixos config using flakes with this

flake.nix

{
  description = "Nixos config flake";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
  };

  outputs = { self, nixpkgs, ... }@inputs: {
    nixosConfigurations.aster-nixos = nixpkgs.lib.nixosSystem {
      specialArgs = {inherit inputs;};
      modules = [
        ./configuration.nix
      ];
    };
  };
}

I want to keep track of my configuration files with git, however I don’t want git to keep track of my hardware configuration as that is only for this machine and I won’t be changing it.
I added it to .gitignore, and commited all my other configuration files.
However, when I run sudo nixos-rebuild switch --flake ~/nixos#aster-nixos I get an error as it does not see the hardware configuration file, is there something I am supposed to toggle to stop nix from checking git for this? Or is there a way for me to organize my configuration so that this problem doesn’t arise?

Your flake should live in /etc/nixos, same as configuration.nix; your code snippet suggests it doesn’t live there.

I addition, you should have flakes and nix-command enabled in your configuration.nix before you move that flake to /etc/nixos and rebuild.

Once you’ve done that, nixos-rebuild switch should just work with your flake by taking precedence over configuration.nix.

You don’t have to put it in /etc/nixos/ if you don’t want to referring to the path with --flake is fine.

You will however need to commit your hardware-configuration.nix (or any file you want to source within the flake). What is your reason for not including it, if it’s not a security concern then there isn’t much harm in adding to your repo.

1 Like

I managed to go around this by removing hardware configuration from my config directory and changing configuration.nix to point to /etc/nixos/hardware-configuration.nix, this requires running nix rebuild with --impure, but other than that it works.

to answer your question, it’s not a security concern, but it should not be in the repo as it is not shared with any other system, so all it would do is cause conflicts when using the repo on a different device.

All of the nixos configuration is specific to your device, and as part of that you need to define options specific to your hardware.

so all it would do is cause conflicts when using the repo on a different device.

A way to handle multiple systems is to have separate hardware-configuration.nix files for each host.

For examples you might have a directory called hosts and refer to it like this in your config:

...
nixosConfigurations.aster-nixos = nixpkgs.lib.nixosSystem {
      specialArgs = {inherit inputs;};
      modules = [
        ./hosts/aster/configuration.nix
        ./hosts/aster/hardware-configuration.nix
      ];
    };
...
3 Likes

I’ve got the same kind of issue here. I’d like to use my config (in its git repo) in my laptop + desktop. For me, there are 2 files that I’m trying to gitignore: hardware-configuration.nix and my own settings.nix, which holds custom sets settings whether Hyprland or Waybar should use laptop or desktop config (slight differences), along with some user-specific things.
I’ve managed to use setting.nix that way (ignored by git) by placing

        dev_specific_config = {
            url = "path:./device-specific/";
            flake = false;
        };

in my flake.nix. However, the same approach does not work for hardware-configuration.nix. Can’t figure out why (tried renaming it to hardwareConfiguration as a last-attempt). Ended up putting those in /etc/nixos/, adding --impure to my aliases and calling it a day.

You can make your config as modular as you’d like. For example, you can have the following structure:

├── configuration.nix
├── hosts
│   ├── desktop
│   │   ├── hardware.nix
│   │   └── settings.nix
│   └── laptop
│       ├── hardware.nix
│       └── settings.nix
└── modules
    └── hyprland
        ├── binds.nix
        ├── common.nix
        ├── desktop.nix
        ├── laptop.nix
        └── plugins.nix

Then, each device imports its own specific modules from the hosts directory:

{
  description = "Nixos config flake";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
  };

  outputs = { self, nixpkgs, ... }@inputs: {
    nixosConfigurations.laptop = nixpkgs.lib.nixosSystem {
      specialArgs = {inherit inputs;};
      modules = [
        # shared between both machines
        ./configuration.nix

        # device-specific
        ./hosts/laptop/settings.nix
        ./hosts/laptop/hardware.nix
      ];
    };
    
    nixosConfigurations.desktop = nixpkgs.lib.nixosSystem {
      specialArgs = {inherit inputs;};
      modules = [
        # shared between both machines
        ./configuration.nix

        # device-specific
        ./hosts/desktop/settings.nix
        ./hosts/desktop/hardware.nix
      ];
    };
}

And in those modules, you can import other modules depending on your needs, for example:

# ./hosts/desktop/settings.nix
{ ... }:
{
  imports = [
    # settings which both systems share
    ../../modules/hyprland/binds.nix
    ../../modules/hyprland/common.nix
    ../../modules/hyprland/plugins.nix

    # settings only for the desktop
    ../../modules/hyprland/desktop.nix
  ];

  # other settings ...
}

Finally, you can just build the system that you need:

$ sudo nixos-rebuild switch --flake ~/nixos#laptop
$ sudo nixos-rebuild switch --flake ~/nixos#desktop

This is just an example. You should of course choose the layout that suits you most.

3 Likes