Preferred way to set System Architecture

Here is my current working config.

{
  description = "My system configuration";

  inputs = {

    # nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
    nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";
    catppuccin.url = "github:catppuccin/nix";

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

    nixvim = {
      url = "github:nix-community/nixvim";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs =
    {
      self,
      nixpkgs,
      nixpkgs-unstable,
      home-manager,
      ...
    }@inputs:

    let
      system = "x86_64-linux";
    in
    {

      # nixos - system hostname
      nixosConfigurations.oakenshield = nixpkgs.lib.nixosSystem {
        specialArgs = {
          pkgs = import nixpkgs {
            inherit system;
            config.allowUnfree = true;
          };
          inherit inputs system;
        };
        modules = [
          ./nixos/configuration.nix
          inputs.nixvim.nixosModules.nixvim
          inputs.catppuccin.nixosModules.catppuccin
        ];
      };

      nixosConfigurations.rpi4 = nixpkgs.lib.nixosSystem {
        specialArgs = {
          pkgs = import nixpkgs {
            inherit system;
            config.allowUnfree = true;
          };
          inherit inputs system;
        };
        modules = [
          ./systems/rpi4/configuration.nix
          inputs.nixvim.nixosModules.nixvim
          inputs.catppuccin.nixosModules.catppuccin
        ];
      };

      homeConfigurations.kmf = home-manager.lib.homeManagerConfiguration {
        pkgs = nixpkgs.legacyPackages.${system};
        modules = [
          ./home-manager/home.nix
          inputs.catppuccin.homeManagerModules.catppuccin
        ];
      };
    };
}

It works …
I want to add aarch64-linux

How would I modify my code should I use flake-parts or flake-utils it’s not very clear?
How would I do it using just Nix?

What is the right way?

# not working just an example
      system = if hostName == "rpi4" then "aarch64-linux"; else "x86_64-linux";

Setting system to x86_64-linux in the let-in for outputs doesn’t really make sense if not all your nixosConfigurations are x86_64-linux. I would move the system let-in to the individual nixosConfigurations (also note that I changed the system reference in the home-manager configuration):

{
  # ...
  outputs =
    {
      self,
      nixpkgs,
      nixpkgs-unstable,
      home-manager,
      ...
    }@inputs:
    {

      # nixos - system hostname
      nixosConfigurations.oakenshield = let
        system = "x86_64-linux";
      in nixpkgs.lib.nixosSystem {
        specialArgs = {
          pkgs = import nixpkgs {
            inherit system;
            config.allowUnfree = true;
          };
          inherit inputs system;
        };
        modules = [
          ./nixos/configuration.nix
          inputs.nixvim.nixosModules.nixvim
          inputs.catppuccin.nixosModules.catppuccin
        ];
      };

      nixosConfigurations.rpi4 = let
        system = "aarch64-linux";
      in nixpkgs.lib.nixosSystem {
        specialArgs = {
          pkgs = import nixpkgs {
            inherit system;
            config.allowUnfree = true;
          };
          inherit inputs system;
        };
        modules = [
          ./systems/rpi4/configuration.nix
          inputs.nixvim.nixosModules.nixvim
          inputs.catppuccin.nixosModules.catppuccin
        ];
      };

      homeConfigurations.kmf = home-manager.lib.homeManagerConfiguration {
        pkgs = nixpkgs.legacyPackages.x86_64-linux;
        modules = [
          ./home-manager/home.nix
          inputs.catppuccin.homeManagerModules.catppuccin
        ];
      };
    };
}

A couple more points:
nixpkgs.lib.nixosSystem can take a system argument. Then you don’t have to import pkgs yourself, because nixpkgs.lib.nixosSystem will automatically import the pkgs from the input it’s from. This also makes it possible to use the nixpkgs.config options (which will have no effect if you use an imported pkgs). There you can set allowUnfree (nixpkgs.config.allowUnfree = true;).
The system special arg is also superfluous, because pkgs has the attribute system, so you can just use pkgs.system.

{
  # ...
  outputs =
    {
      self,
      nixpkgs,
      nixpkgs-unstable,
      home-manager,
      ...
    }@inputs:
    {

      # nixos - system hostname
      nixosConfigurations.oakenshield = let
        system = "x86_64-linux";
      in nixpkgs.lib.nixosSystem {
        inherit system;
        specialArgs = {
          inherit inputs;
        };
        modules = [
          ({...}: { nixpkgs.config.allowUnfree = true; })
          ./nixos/configuration.nix
          inputs.nixvim.nixosModules.nixvim
          inputs.catppuccin.nixosModules.catppuccin
        ];
      };

      nixosConfigurations.rpi4 = let
        system = "aarch64-linux";
      in nixpkgs.lib.nixosSystem {
        inherit system;
        specialArgs = {
          inherit inputs;
        };
        modules = [
          ({...}: { nixpkgs.config.allowUnfree = true; })
          ./systems/rpi4/configuration.nix
          inputs.nixvim.nixosModules.nixvim
          inputs.catppuccin.nixosModules.catppuccin
        ];
      };

      homeConfigurations.kmf = home-manager.lib.homeManagerConfiguration {
        pkgs = nixpkgs.legacyPackages.x86_64-linux;
        modules = [
          ./home-manager/home.nix
          inputs.catppuccin.homeManagerModules.catppuccin
        ];
      };
    };
}

(I set nixpkgs.config.allowUnfree via an “anonymous” module here, but you could obviously do that in any of your existing module files)

Since quite recently I would use nixpkgs.hostPlatform = "x86_64-linux";
This way your main flake can be system agnostic.
I have as well aarch64-linu and 86_64-linu in my configs.

If you need the system somewhere you can then refere to it like this:

This is the commit I made when I migrated away from the system variable: Replace system with hostPlatform · b92e801fc5 - nixos - Gitea: Git with a cup of tea

1 Like

Using hostname in a conditional will make your config unmaintainable very quickly.

And yes as mentioned above passing system to lib.nixosSystem is deprecated, and nixpkgs.hostPlatform is the current method. Passing pkgs is discouraged as well unless you use readOnlyPkgs.

Thanks for answering :smiley:

I agree, the idea to modular and not hard code anything as far possible

Thanks for this I’ll investigate further.

@edwinistrator thanks for putting in a lot of effort in your answer, I’ll refactor my code.

my assumption here is that home-manager will on work on x86_64-linux ?

Yes. If you also need the home-manager configuration for aarch64-linux, you should create a separate one with the same config (except pkgs being for aarch64-linux, of course). The reason is that the same home-manager configuration with pkgs for different systems will result in different store paths.

If you can I would use the home-manger module directly in your NixOS configuration, then you don’t have to care about the system in home-manager.

I only have a separate home-manager configuration for an Ubuntu system I have to use at work.

Thanks all it’s working great.