From 560d58bbde4694812b24a1cd41c157c62d6d3f9d Mon Sep 17 00:00:00 2001 From: 0xrsydn Date: Mon, 5 Oct 2026 16:59:26 +0700 Subject: [PATCH] feat(darwin): add kache build cache with R2 remote Wire the kunobi-ninja/kache darwin module into the flake: global RUSTC_WRAPPER, /etc/kache/config.toml pointing at the kache-build-cache R2 bucket, and a launchd daemon whose wrapper loads sops-decrypted KACHE_S3_* credentials at runtime (launchd does not inherit the shell environment). Ignore the cf CLI's local cache dir. --- .gitignore | 3 ++ flake.lock | 101 ++++++++++++++++++++++++++++++++++----- flake.nix | 15 +++++- modules/darwin/kache.nix | 49 +++++++++++++++++++ 4 files changed, 155 insertions(+), 13 deletions(-) create mode 100644 modules/darwin/kache.nix diff --git a/.gitignore b/.gitignore index 78e7022..f2a9a41 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ result-* # Neovim modules/home/rsydn/programs/nvim/lazy-lock.json + +# Cloudflare CLI (cf) local cache +.cloudflare/ diff --git a/flake.lock b/flake.lock index bbb6126..7e9d690 100644 --- a/flake.lock +++ b/flake.lock @@ -215,20 +215,40 @@ "type": "github" } }, + "kache": { + "inputs": { + "nixpkgs": "nixpkgs_2", + "rust-overlay": "rust-overlay_2", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1791194368, + "narHash": "sha256-Kbww7mmdUAASh1sbjdoqoosSA76EALJata+Aa8SJUnE=", + "owner": "kunobi-ninja", + "repo": "kache", + "rev": "7c27329c286e32c17a8dac05cff22442926ff719", + "type": "github" + }, + "original": { + "owner": "kunobi-ninja", + "repo": "kache", + "type": "github" + } + }, "llm-agents": { "inputs": { "bun2nix": "bun2nix", "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs_3", "systems": "systems", - "treefmt-nix": "treefmt-nix" + "treefmt-nix": "treefmt-nix_2" }, "locked": { - "lastModified": 1790918187, - "narHash": "sha256-F3py52yPDHBSKKkx4CzpTMc5KxzCBT+jLUIRNOYpr4Q=", + "lastModified": 1791175671, + "narHash": "sha256-1szYaEAFYPApOgy2HGLbqtVys8SIqk5mlvz9agPFLr0=", "owner": "numtide", "repo": "llm-agents.nix", - "rev": "20762f12777a611184868a1a4408bc42a014adf1", + "rev": "ba24820b562c0e1ff95d283a2e2e1debcbcbad83", "type": "github" }, "original": { @@ -240,8 +260,8 @@ "llm-agents-pinned": { "inputs": { "blueprint": "blueprint", - "nixpkgs": "nixpkgs_3", - "treefmt-nix": "treefmt-nix_2" + "nixpkgs": "nixpkgs_4", + "treefmt-nix": "treefmt-nix_3" }, "locked": { "lastModified": 1765334436, @@ -329,6 +349,22 @@ } }, "nixpkgs_2": { + "locked": { + "lastModified": 1773597492, + "narHash": "sha256-hQ284SkIeNaeyud+LS0WVLX+WL2rxcVZLFEaK0e03zg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "a07d4ce6bee67d7c838a8a5796e75dff9caa21ef", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { "locked": { "lastModified": 1790600678, "narHash": "sha256-6k3n7X2UsZ6tAlWTz99RimiZab+17tMUrw9sRUcELiA=", @@ -344,7 +380,7 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_4": { "locked": { "lastModified": 1764947035, "narHash": "sha256-EYHSjVM4Ox4lvCXUMiKKs2vETUSL5mx+J2FfutM7T9w=", @@ -360,7 +396,7 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_5": { "locked": { "lastModified": 1770197578, "narHash": "sha256-AYqlWrX09+HvGs8zM6ebZ1pwUqjkfpnv8mewYwAo+iM=", @@ -381,9 +417,10 @@ "chaotic": "chaotic", "darwin": "darwin", "home-manager": "home-manager_2", + "kache": "kache", "llm-agents": "llm-agents", "llm-agents-pinned": "llm-agents-pinned", - "nixpkgs": "nixpkgs_4", + "nixpkgs": "nixpkgs_5", "nixpkgs-stable": "nixpkgs-stable", "sops-nix": "sops-nix", "try": "try" @@ -410,6 +447,27 @@ "type": "github" } }, + "rust-overlay_2": { + "inputs": { + "nixpkgs": [ + "kache", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1791101754, + "narHash": "sha256-y/GF+9B0t0TZ0nQiSRMqDXpr76yT7sdDbS/3GNLhzkE=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "dbc715a4b7c0ace63b9769a032d1dd34cd89e5bd", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, "sops-nix": { "inputs": { "nixpkgs": [ @@ -461,6 +519,27 @@ } }, "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "kache", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1784369104, + "narHash": "sha256-47cxbcZODibHv3rELFQ9vZly0vUNkND/atn/U7HLeb0=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "df3c0640565d04a0261253cdd89fce78ec50168a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_2": { "inputs": { "nixpkgs": [ "llm-agents", @@ -481,7 +560,7 @@ "type": "github" } }, - "treefmt-nix_2": { + "treefmt-nix_3": { "inputs": { "nixpkgs": [ "llm-agents-pinned", diff --git a/flake.nix b/flake.nix index 9ed0cc1..db1d7c6 100644 --- a/flake.nix +++ b/flake.nix @@ -24,6 +24,9 @@ try.url = "github:tobi/try"; try.inputs.nixpkgs.follows = "nixpkgs"; + + # Rust/C++ build cache (RUSTC_WRAPPER + launchd daemon, backed by R2) + kache.url = "github:kunobi-ninja/kache"; }; outputs = @@ -37,6 +40,7 @@ sops-nix, chaotic, try, + kache, ... }: let @@ -58,7 +62,11 @@ # No overlays needed for Darwin builds # - gitOverlay: removed - was causing mypy to rebuild from source # - chaotic: removed - only needed for NixOS, was causing nix to rebuild with failing tests - overlaysList = [ ]; + # kache overlay (includes rust-overlay) so pkgs.kache builds with the + # toolchain pinned in kache's rust-toolchain.toml + overlaysList = [ + kache.overlays.default + ]; mkPkgs = system: @@ -68,7 +76,10 @@ config.allowUnfree = true; }; - sharedDarwinModules = [ ./modules/darwin/system.nix ]; + sharedDarwinModules = [ + ./modules/darwin/system.nix + ./modules/darwin/kache.nix + ]; sharedNixosModules = [ ./modules/nixos/system.nix chaotic.nixosModules.default diff --git a/modules/darwin/kache.nix b/modules/darwin/kache.nix new file mode 100644 index 0000000..2e5443a --- /dev/null +++ b/modules/darwin/kache.nix @@ -0,0 +1,49 @@ +{ + inputs, + pkgs, + lib, + config, + ... +}: +let + cfg = config.services.kache; + + # launchd agents do not inherit the user shell environment, so the daemon + # would miss the sops-decrypted KACHE_S3_* credentials. This wrapper loads + # them from the runtime secret files, then execs the real daemon. + # Values are read at activation/runtime only - never baked into the store. + kacheDaemonWrapper = pkgs.writeShellScript "kache-daemon-wrapper" '' + secret_dir="''${XDG_CONFIG_HOME:-$HOME/.config}/secrets/global-env" + + for secret_file in "$secret_dir"/KACHE_S3_*; do + [ -e "$secret_file" ] || continue + name="$(basename "$secret_file")" + case "$name" in + *[!A-Za-z0-9_]*) continue ;; + esac + export "$name=$(<"$secret_file")" + done + + exec ${lib.getExe cfg.package} daemon run + ''; +in +{ + imports = [ inputs.kache.darwinModules.default ]; + + services.kache = { + enable = true; + daemon.enable = true; + + settings.cache.remote = { + type = "s3"; + bucket = "kache-build-cache"; + endpoint = "https://bb8d9158f0640a3d950d2597f52e9104.r2.cloudflarestorage.com"; + region = "auto"; + }; + }; + + # Point the upstream module's launchd agent at the credential wrapper. + launchd.user.agents.kache.serviceConfig.ProgramArguments = lib.mkForce [ + "${kacheDaemonWrapper}" + ]; +}