A while ago I noticed that my OpenSSH often has to be rebuilt when I make completely unrelated changes to my NixOS configurations.
TL;DR
- openssh with a single patch added
- not overriden globally, just
programs.ssh.package
- not overriden globally, just
- patch is stored in flake’s git repo
- patch store path somehow depends on flake’s store path, but also not
- constantly have to rebuild this package
- but it should already be on system or at least on binary cache
My setup
I don’t use nixos-rebuild and instead use:
nix build --eval-store auto --store ssh-ng://"<user>@<hostname>" \
.#nixosConfigurations.<name>.config.system.build.toplevel
The remote store is either the target server or a build server when compiling for a low-power server. All servers have access to the binary cache (Minio S3 bucket with anonymous RO access) that my GitLab CI pushes to.
All store paths for the main branch of my repo are guaranteed to be on that binary cache because everything gets built by the CI before merging. Most of the servers are also automatiacally deployed by the main branch pipeline.
The code
no public repo, sorry
In my flake, I have an overlay that adds an openssh-mptcp package, which is just openssh with a patch for MPTCP. I then set this as programs.ssh.package.
The overlay generally uses infuse.nix, but I’m not fully making use of it for this particular package yet, as per the TODO:
# TODO: figure out how to do this with infuse
openssh-mptcp.__init =
if final.stdenv.hostPlatform.isLinux
then
prev.openssh.overrideAttrs (self: super: {
patches =
super.patches
or []
++ (cleanPatches [
./openssh-${self.version}-mptcp-support.patch
]);
})
else prev.openssh;
(I maintain the patch for multiple versions as the overlay is applied to multiple NixOS releases).
What I already tried
Because the patch files are stored in the flake’s repo, I considered that making changes to the flake may also change the store path of the patch, thereby changing the openssh-mptcp package’s store path even though the content of the patch hasn’t changed.
When I looked into it a while ago, I could see via nix repl that the store path of the MPTCP patch in the derivations patches attribute did change when making unrelated changes in the flake. That’s because the patch path is relative to the flake’s store path, which changes whenever any Git-tracked file is modified, added, or deleted.
So I added a cleanPatches function that ensures the patches get the same store path regardless of the flake’s store path:
cleanPatches = patches: map (patchPath: builtins.path {path = patchPath;}) patches;
What I didn’t notice before is that after I remove the cleanPatches function again, even when the patch’s store path changes, the package’s drvPath and outPath remain the same (really!).
I suppose this might be some kind of flake-related magic. I have also never heard of flake’s having to decouple source files or patches from their Nix flake’s path.