Support early build cache hints

This commit is contained in:
Timothy J. Aveni
2026-07-02 11:21:53 -07:00
parent 837dea284c
commit f8c9ef03bf
2 changed files with 57 additions and 1 deletions
+26
View File
@@ -15,6 +15,32 @@ also disables the default shell-oriented `amazon-init` service and enables a
small generic service that treats EC2 user-data as `/etc/nixos/flake.nix`, then
runs `nixos-rebuild switch --flake /etc/nixos`.
## First-Boot Build Cache Hints
The first user-data switch is built by the AMI's existing Nix configuration,
before the target NixOS system has activated its own `nix.settings`. A caller
flake can optionally expose `quixosEarlyBuildNixConfig` to make that first
build use known binary caches without baking any project-specific cache into
the AMI:
```nix
{
quixosEarlyBuildNixConfig = {
hosts = {
"2600:..." = [ "nix-cache.internal.example.org" ];
};
substituters = [ "http://nix-cache.internal.example.org/cache" ];
trustedPublicKeys = [ "nix-cache.internal.example.org-1:..." ];
};
}
```
The AMI runner evaluates this output after writing `/etc/nixos/flake.nix`,
appends the host hints to `/etc/hosts`, and passes the substituters and trusted
public keys through `NIX_CONFIG` only for the first `nixos-rebuild switch`.
The target NixOS configuration should still declare the same cache in
`nix.settings` for all later rebuilds.
## Publish
The normal flow builds on a temporary EC2 instance, so your local machine does
+31 -1
View File
@@ -75,7 +75,7 @@ write_config() {
wantedBy = [ "multi-user.target" ];
after = [ "fetch-ec2-metadata.service" "network-online.target" "nix-daemon.socket" ];
wants = [ "fetch-ec2-metadata.service" "network-online.target" "nix-daemon.socket" ];
path = [ pkgs.coreutils pkgs.git pkgs.systemd ];
path = [ pkgs.coreutils pkgs.git pkgs.jq pkgs.nix pkgs.systemd ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
@@ -102,11 +102,41 @@ write_config() {
install -m 0644 "$user_data" /etc/nixos/flake.nix
early_build_config=/run/nixos-user-data-flake-early-build-config.json
early_build_error=/run/nixos-user-data-flake-early-build-config.err
early_nix_config=/run/nixos-user-data-flake-early-nix.conf
: > "$early_nix_config"
if nix --extra-experimental-features 'nix-command flakes' \
eval --json /etc/nixos#quixosEarlyBuildNixConfig \
> "$early_build_config" 2> "$early_build_error"; then
jq -r '(.hosts // {}) | to_entries[] | select(.key != "" and (.value | length > 0)) | [.key, (.value | join(" "))] | @tsv' "$early_build_config" |
while IFS="$(printf '\t')" read -r address names; do
if [ -n "$address" ] && [ -n "$names" ]; then
printf '%s %s # quixos early build nix cache\n' "$address" "$names" >> /etc/hosts
fi
done
substituters="$(jq -r '(.substituters // []) | join(" ")' "$early_build_config")"
trusted_public_keys="$(jq -r '(.trustedPublicKeys // []) | join(" ")' "$early_build_config")"
if [ -n "$substituters" ]; then
printf 'extra-substituters = %s\n' "$substituters" >> "$early_nix_config"
fi
if [ -n "$trusted_public_keys" ]; then
printf 'extra-trusted-public-keys = %s\n' "$trusted_public_keys" >> "$early_nix_config"
fi
else
echo "No quixosEarlyBuildNixConfig flake output found; first switch will use the AMI Nix configuration."
fi
runner=/run/nixos-user-data-flake-apply
cat > "$runner" <<RUNNER_EOF
#!$${pkgs.runtimeShell}
set -eu
export PATH="$${lib.makeBinPath [ pkgs.coreutils pkgs.git pkgs.systemd ]}"
if [ -s "$early_nix_config" ]; then
export NIX_CONFIG="\$(cat "$early_nix_config")"
fi
$${config.system.build.nixos-rebuild}/bin/nixos-rebuild switch --flake /etc/nixos
printf '%s\n' "$new_hash" > "$applied_hash_file"