Remote Nix Builds & Distributed Caching
Offloading heavy compilation to a dedicated remote build machine and sharing build artifacts across devices transforms the Nix development experience.
For quick, one-off builds on a remote host over SSH without modifying your system configuration, you can point the Nix store flag directly to a remote machine:
nix build --eval-store auto --store ssh-ng://nix-builder@host ...Or copy closures manually between remote stores:
nix-copy-closure --from nix-builder@host /nix/store/...While ad-hoc commands work well for temporary tasks, NixOS natively
supports declarative distributed builds via
nix.distributedBuilds and nix.buildMachines.
On the build server, set up a restricted builder user:
users.users.nix-builder = {
isNormalUser = true;
description = "Nix remote builder user";
openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5..." ];
};On client machines, configure nix.buildMachines to
delegate builds automatically over SSH:
nix = {
distributedBuilds = true;
buildMachines = [
{
hostName = "builder.internal";
sshUser = "nix-builder";
sshKey = "/home/dom/.ssh/id_build_key";
systems = [
"x86_64-linux"
"aarch64-linux"
];
maxJobs = 4;
supportedFeatures = [
"nixos-test"
"benchmark"
"big-parallel"
"kvm"
];
}
];
};When building locally, the Nix daemon transparently forwards
derivations requiring specific resources (big-parallel,
kvm, or secondary architectures like
aarch64-linux) to the remote builder. If you need to bypass
remote build servers temporarily (e.g. when offline or troubleshooting),
pass --builders "" to force the build locally:
nix build --builders "" ...To share build artifacts across multiple machines on your network, pair distributed builds with Harmonia, a high-performance Nix binary cache server written in Rust that queries the local store directly and signs derivations on demand:
services.harmonia = {
cache.enable = true;
cache.settings.bind = "127.0.0.1:5005";
cache.signKeyPaths = [ config.sops.secrets."services/harmonia/sign-key".path ];
};On client machines, configure the private cache as a trusted substituter in Nix settings:
nix.settings = {
substituters = [ "https://cache.internal" ];
trusted-public-keys = [ "cache.internal-1:..." ];
};If you ever need to bypass binary substituters and rebuild directly
from source (e.g. to verify build reproducibility or when a cache server
is unavailable), pass --option substitute false:
nix build --option substitute false ...This workflow automates remote build execution, speeds up builds with instant artifact substitution, and keeps network traffic secure over SSH and signed cache outputs.