Greetings!
I couldn’t find any MacOS examples for a Nix binary cache, so I wrote a module for it using attic and am running it on my M1 Mac Mini.
I’m using flakes, so I’m going to assume you have an input like so:
inputs.attic.url = "github:zhaofengli/attic";
And then here’s my module which runs on my M1 Mac Mini (and therefore populates the cache with MacOS binaries):
{ config, pkgs, lib, attic, ... }:
let
system = pkgs.system;
atticServer = attic.packages.${system}.attic-server;
atticClient = attic.packages.${system}.attic-client;
garbageCollectCache = pkgs.writeShellScriptBin "nix-darwin-cache-garbage-collect" ''
${atticServer}/bin/atticd --mode garbage-collector-once &>>/tmp/binary-cache.log
'';
populateCache = pkgs.writeShellScriptBin "nix-darwin-cache-populate" ''
rm -rf /tmp/nixos-configs
${pkgs.git}/bin/git clone https://github.com/heywoodlh/nixos-configs /tmp/nixos-configs
cd /tmp/nixos-configs
# aarch64 build
${pkgs.nix}/bin/nix build .#darwinConfigurations.mac-mini.config.system.build.toplevel
${atticClient}/bin/attic push nix-darwin ./result
rm -rf /tmp/nixos-configs
'';
runCache = pkgs.writeShellScript "serve-cache" ''
${atticServer}/bin/atticd --listen 0.0.0.0:8080 &>>/tmp/binary-cache.log
'';
in {
launchd.daemons.cache-populate = {
command = "${populateCache}/bin/nix-darwin-cache-populate";
serviceConfig.StartInterval = 86400; # run once a day
};
launchd.daemons.cache-garbage-collect = {
command = "${populateCache}/bin/nix-darwin-cache-garbage-collect";
serviceConfig.StartInterval = 604800; # run once a week
};
launchd.daemons.nix-cache = {
command = "${runCache}";
serviceConfig.RunAtLoad = true;
serviceConfig.KeepAlive = true;
};
environment.systemPackages = [
garbageCollectCache
populateCache
];
}
This builds my nix-darwin flake at this URI:
github:heywoodlh/nixos-configs#mac-mini
and loads them into the cache. Obviously, this is specific to my setup, so you’ll likely want to change the things you build in the populateCache
attribute.
Caveat: on your machine running this module, you need to login to your attic instance with the attic client (you can get the command to login from /tmp/binary-cache.log
after this module is loaded):
attic login local http://localhost:8080 ...
Then, create the nix-darwin
cache like this:
attic cache create nix-darwin
attic cache configure nix-darwin --public
attic cache configure nix-darwin --retention-period '7d'
Then populate the cache by running the nix-darwin-cache-populate
script provided in the populateCache
attribute.
Check the availability for your cache like so:
curl http://127.0.0.1:8080/nix-darwin/nix-cache-info
Obviously, this example specifically targets Nix-Darwin stuff in my setup, but could be extended to any other thing you can build with Nix. You could also easily extend this into building Linux things on MacOS with the linux-builder provided with Nix-Darwin and load them into attic
. Alternatively, you could have a MacOS remote builder and push the build result into a different NixOS machine running attic
. The options are endless with Nix!
I would be very interested in other MacOS-specific binary cache implementations because I couldn’t find any. Should probably contribute an attic module to Nix-Darwin, but don’t yet have willpower for it.
Here’s my binary-cache.nix
at the time of writing this, will likely evolve as time goes on: https://github.com/heywoodlh/nixos-configs/blob/abcc5d8a61f51304426df88ac8c6e63440036db7/darwin/roles/binary-cache.nix
edit: added the commands to create the nix-darwin
cache after attic is running