Build root filesystem contents for different architecture

I’m trying (unsuccessfully) to build the contents of a root filesystem for a different machine/architecture. I’m using flakes. Here’s what I’ve got so far:

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

  outputs =
    { self
    , nixpkgs
    }:
    let
      pkgs = import nixpkgs {
        system = "aarch64-linux";
      };
    in
    {
      nixosConfigurations = {
        hzitaf = nixpkgs.lib.nixosSystem {
          modules = [
            ({ pkgs, ... }: {
              boot = {
                # disable bootloader
                loader.grub.enable = false;
              };

              fileSystems = {
                "/" = {
                  device = "/dev/disk/by-uuid/94da908d-3dbd-4ae0-b459-4d4d913b73e1";
                };
              };

              nixpkgs = {
                hostPlatform.system = "x86_64-linux";
                buildPlatform.system = "aarch64-linux";
              };

              # system.build.tarball = pkgs.callPackage ./make-system-tarball.nix {
              #   contents = [];
              #   compressCommand = "cat";
              #   compressionExtension = "";
              # };

              system = {
                stateVersion = "23.11";
              };

              users.users.root.password = "";
            })
          ];
        };
      };
    };
}

If I try to build toplevel with nix build .#nixosConfigurations.hzitaf.config.system.build.toplevel I get the error

error: a 'aarch64-linux' with features {} is required to build '/nix/store/x7q8ab5wxm74g9szvfpql5hr3433b2h8-mounts.sh.drv', but I am a 'x86_64-linux' with features {benchmark, big-parallel, kvm, nixos-test, uid-range}

I’m not exactly sure what this means, but it appears as though it’s complaining about the fact that the target system is different than the build system. Moreover, I think toplevel is not actually what I want since apparently it symlinks from the nix store, whereas I need this to be fully isolated so I can copy the contents to a disk partition (eg with rsync). I also tried with tarball (FYI I couldn’t seem to access this attribute under nixpkgs, so I copied make-system-tarball.nix and make-system-tarball.sh to my local flake repo). However, this yielded a similar error.

I also tried the approach of mounting the destination partition directly and installing to it with nixos-install: nixos-install --flake .#hzitaf --root /media/matt.huszagh/94da908d-3dbd-4ae0-b459-4d4d913b73e1, but that gives me a very similar error:

error: a 'aarch64-linux' with features {} is required to build '/nix/store/ap9v7l0npaixb4zahk2zhmw4a33sy2ik-audit-disable.drv', but I am a 'x86_64-linux' with features {benchmark, big-parallel, kvm, nixos-test, uid-range}

Is there a way to accomplish this? Should I be using something like make-disk-image.nix instead? Eventually, I plan to build the full disk image with Nix, including the boot partition. However, building out the contents of the boot partition is quite complex and for the moment I’m doing it imperatively, but would still prefer to use Nix to build the root filesystem in the meantime.

There are three options:

  • use a remote aarch64-linux builder
  • build with qemu-aarch64 (boot.binfmt.emulatedSystems = [ "aarch64-linux" ], this will be fairly slow, but almost everything will be substituted, so unless you have a lot of custom packages, this still works fine )
  • use a cross toolchain (nixpkgs.buildPlatform.system = "x86_64-linux"; nixpkgs.hostPlatform.system = "aarch64-linux";, builds are about as fast as native builds, but you won’t have any cache hits and a lot of stuff doesn’t cross-compile)
1 Like

Thanks so much for this - that got it working. Specifically, I had hostPlatform and buildPlatform backward…

1 Like