Automatic sleep and wake up for my local nix builder
Nov 12, 2026I use an older desktop computer as my Nix builder at home for all my untrusted Nixpkgs work (reviewing PRs, running tests, etc). Since I don't want it powered on and consuming power 24/7, but only run when I want to test builds, here's my quick hack for getting the host to automatically suspend and wake up on demand to build packages.
I use the autosuspend daemon, a program that runs in the background and periodically checks for certain conditions. If a specific state is reached based on those conditions, it automatically suspends the system. Autosuspend supports a wide range of checks to decide if the system should suspend or not.
There's already a NixOS module for autosuspend and I have it configured so that after 5 minutes of not finding an active network connection on the SSH port, the host will suspend. Due to the versatility of NixOS modules, the SSH port is automatically picked up based on the host settings.
Then, on my desktop and laptop, I've got a script that tries to connect to a port on my remote builder host. If it fails, it sends the Wake-On-LAN magic packet to it. This wakes up the builder host in a second or two.
wake-host = pkgs.writeShellApplication {
name = "wake-host";
runtimeInputs = with pkgs; [ coreutils netcat wakeonlan ];
text = ''
host=$1
port=$2
mac=$3
nc -z -w1 "$host" "$port" && exit 0
wakeonlan "$mac" >/dev/null
for _ in $(seq 60); do
nc -z -w1 "$host" "$port" && exit 0
sleep 1
done
exit 1
'';
};
Finally, a shell function and an SSH config Match entry tie everything
together.
~/.ssh/config
Host builder
HostName 192.168.1.99
Port 222
Match originalhost builder exec "wake-host %h %p de:ad:be:ef:13:37"Shell function
rbuild() {
nix-build --option restrict-eval true \
--option allow-import-from-derivation false \
-I "$(pwd -P)" \
--eval-store auto --store ssh-ng://builder -A "$1"
}
The shell function uses --eval-store auto so evaluation and instantiation of
derivations happen locally, while --store ssh-ng://builder makes the remote
builder's Nix store the one where things are built. Opening the SSH connection
due to ssh-ng:// is what triggers the wake-host script and wakes up the host
with wakeonlan if needed. It's important to note that restrict-eval is set to
true, so evals can't access files outside of the current working directory or
make network calls.
From the root of my Nixpkgs checkout, once I've reviewed a commit or I've made
some changes I want to test, I run rbuild packagename or rbuild
nixosTests.nameoftest. The expressions get evaluated locally and the
derivations are transferred to the builder over SSH. The builder, then, downloads
the source code of the target packages and builds them or runs the NixOS test as
requested. The build outputs stay in the builder's store (which will be
garbage-collected automatically later) and never touch my local store. Five
minutes after the build has finished and the SSH connection has closed, the
builder host goes back to sleep.
This setup isn't without issues. If the SSH connection drops, say because I closed the lid of my laptop, the build will be canceled on the remote builder. In an ideal setup, I would schedule builds in a proper build system (maybe nix-grpc-store?) and have builder hosts wake up and pick up builds on their own. But hey, it's a hack, it works and hacks are fun :).
Tags: nix nixosComments on Fediverse.
