morph
morph copied to clipboard
Building for other architecture is unintuitive
Building for different architectures on a per deployment base feels not very intuitive.
I got it working by setting network.pkgs to an instance of nixpkgs with no further configuration while setting nixpkgs.pkgs in the relevant deployments to a nixpkgs called with system = "...". In addition, I have to set nixpkgs.localSystem.system to the architecture, too.
I'm not even sure, if this is the right way to do it. If so, I feel like this needs some documentation / examples (which I'm happy to contribute).
An example of a currently working version can be found here: https://github.com/fooker/nixcfg/blob/363d14b53ef17c01e66fa086ce21ca7039f628b5/deployment.nix
The example is a bit complicated, but getting morph to work that way is really just about setting nixpkgs.pkgs.system and nixpkgs.localSystem.system for each machine in deployment.nix, isn't it?
I also don't fully understand @fooker's example, but I think this could be solved reasonably well by just specifying distinct nixpkgs for each machine. The best way to do this, however, is unclear to me.
Maybe @johanot can give us some ideas?
For those who come across this in the future here's my hacky solution to the issue: https://github.com/lovesegfault/nix-config/blob/e7bd275a37b2268978bb875cedb47aac41482d34/deployment.nix
It amounts to:
- not setting
network.pkgs - setting
nixpkgs.pkgsfor each machine individually through a small function
cfg: system:
let
pkgs = import ./nix/nixpkgs.nix { inherit system; config.allowUnfree = true; };
in
{ lib, ... }: {
imports = [ cfg ];
nixpkgs.pkgs = lib.mkForce pkgs;
}
The example is a bit complicated, but getting morph to work that way is really just about setting [...]
nixpkgs.localSystem.systemfor each machine indeployment.nix, isn't it?
That doesn't work, as morph sets nixpkgs.pkgsto the value of network.pkgs, in which case nixpkgs.localSystem/nixpkgs.crossSystem is ignored. I think if you set evalConfig instead of pkgs, you could then set nixpkgs.localSysetm and it would build the pkgs argument from the nixpkgs that evalConfig comes from and nixpkgs.localSystem etc.
@tomprince https://github.com/DBCDK/morph/issues/104#issuecomment-589954838 is what most of us with that use case use.
That doesn't work, as morph sets nixpkgs.pkgsto the value of network.pkgs, in which case nixpkgs.localSystem/nixpkgs.crossSystem is ignored.
This doesn't appear to be true. I managed to get a working configuration like @lovesegfault described, with
config = {
nixpkgs.system = "aarch64-linux";
nixpkgs.pkgs = import sources.pkgs {
system = "aarch64-linux";
};
};
However, one indeed requires the evalConfig hack for anything that involves more than simply building packages, i.e. using a different channel or overriding modules.
Share a setup which works in my daily usage.
I'm using morph on macOS for building software on my x86_64-linux machines.
The core idea is simple:
- run a
x86_64-linuxmachine on macOS (virtual machine or docker container) - set the machine as the build machine for Nix.
- let morph know you are building for
x86_64-linux.
For 1 / 2, checkout a possible guide which can be found at Provisioning a NixOS server from macOS. In the article, docker container is used. But, you can also use a virtual machine.
For 3, there's a possible network.nix:
let
pkgs = import <nixpkgs> {
system = "x86_64-linux"; # a. eval pkgs with right `system`
};
in
{
network = {
inherit pkgs; # b. use the pkgs for morph.
description = "your network name";
};
machine-n = {
deployment.targetHost = "...";
# nix 2 is using `nixpkgs.localSystem.system`, not `nixpkgs.system`
nixpkgs.localSystem.system = "x86_64-linux"; # c. declare the machine's system
# ...
};
# ...
}
Then, morph it. Enjoy yourself.
If you care about clean code, checkout the solution of lovesegfault, which is a higher abstraction of above code.