Skip to content

Shared pkgs

yen’s own part of a host’s evaluation is small: 1.4% on the reference fleet’s lb. Most of the time goes to nixpkgs pkgs (56%) and the NixOS module system (36%). By default every host imports nixpkgs again.

With sharedPkgs = true, a host reuses the pkgs of the first sharing host on its system (the leader), through nixpkgs’ readOnlyPkgs module. The out arg gives the leader’s built pkgs, lazily.

modules/fleet.nix
# Hosts with `sharedPkgs` reuse the pkgs of the first sharing host (the leader): nixpkgs is imported once.
{
yen,
lib,
inputs,
...
}:
let
np = inputs.nixpkgs;
in
{
yen.kinds.fleet = {
spawns.host = _: yen.host;
sinks.out.reduce = yen.lib.reduce.merge;
};
yen.kinds.host = {
fields = {
system = yen.lib.opt lib.types.str "x86_64-linux";
sharedPkgs = yen.lib.opt lib.types.bool false;
};
sinks.nixos.out =
{
host,
nixos,
out,
...
}:
let
group = lib.sort (a: b: a < b) (
lib.attrNames (lib.filterAttrs (_: h: h.sharedPkgs && h.system == host.system) yen.host)
); # one group per system
leader = lib.head group;
follower = host.sharedPkgs && leader != host.name;
shared = out.nixosConfigurations.${leader}.pkgs; # the `out` arg: the leader's built pkgs, lazily
readOnly = [
np.nixosModules.readOnlyPkgs
{ options.nixpkgs.system = lib.mkOption { internal = true; }; }
{ nixpkgs.pkgs = shared; }
];
in
{
nixosConfigurations.${host.name} = np.lib.nixosSystem {
inherit (host) system;
modules = nixos ++ lib.optionals follower readOnly;
};
ownPkgs.${host.name} = np.lib.nixosSystem {
inherit (host) system;
modules = nixos;
}; # the oracle: the same host with its own pkgs
};
};
yen.fleet.main = { };
yen.flake = { out, ... }: out;
}
modules/hosts.nix
{ yen, lib, ... }:
{
yen.host = lib.genAttrs [ "app-1" "app-2" "app-3" ] (_: {
sharedPkgs = true;
});
yen.aspects.app = {
at = yen.kinds.host;
nixos =
{ host, pkgs, ... }:
{
networking.hostName = host.name;
environment.systemPackages = [ pkgs.htop ];
boot.loader.grub.device = "nodev";
fileSystems."/" = {
device = "/dev/sda1";
fsType = "ext4";
};
system.stateVersion = "25.05";
};
};
# docs differ when pkgs is shared: keep them off on sharing hosts
yen.aspects.shared-no-docs = {
at = yen.lib.all [
yen.kinds.host
(s: s.sharedPkgs)
];
nixos.documentation = {
enable = false;
nixos.enable = false;
man.enable = false;
};
};
}

A follower must build exactly what it builds alone. ownPkgs is each host built with its own pkgs. The docs check that every host’s toplevel drvPath is the same both ways.

Reference fleet: lb, web-1, web-2 toplevelCPUThunksGC total
each its own pkgs35.3 s36.6 M2.71 GB
shared pkgs24.8 s29.3 M1.96 GB

Measured on the reference fleet, with the same drvPaths both ways (README).

Contribute Community Sponsor