빌드 후 훅 설정하기#

Author:

Graham Christensen @grahamc

이 가이드에서는 Nix post-build-hook 설정 옵션을 사용하여 빌드 결과를 S3 호환 바이너리 캐시에 자동으로 업로드하는 방법을 설명합니다.

구현 시 주의 사항#

이 예제는 간단하고 실제로 동작하지만, 모든 사용 사례에 적합하지는 않습니다.

빌드 후 훅 프로그램은 빌드가 실행될 때마다 그 뒤에 실행되며, 빌드 루프를 차단합니다. 훅 프로그램이 실패하면 빌드 루프가 종료됩니다.

구체적으로 말하면, 이 구현을 사용하면 네트워크 연결이 느리거나 불안정할 때 Nix가 느려지거나 사용할 수 없게 됩니다. 더 발전된 구현에서는 스토어 경로를 사용자가 제공한 데몬이나 큐에 넘겨 빌드 루프 밖에서 스토어 경로를 처리하게 할 수 있습니다.

사전 준비 사항#

이 튜토리얼은 S3 호환 바이너리 캐시를 설정했고, root 사용자의 기본 AWS 프로필로 버킷에 업로드할 수 있다고 가정합니다.

서명 키 설정하기#

nix-store --generate-binary-cache-key를 사용하여 암호화 키 쌍을 생성하십시오. 개인 키로 경로에 서명하고, 경로의 진위를 검증할 수 있도록 공개 키를 배포합니다.

$ nix-store --generate-binary-cache-key example-nix-cache-1 /etc/nix/key.private /etc/nix/key.public
$ cat /etc/nix/key.public
example-nix-cache-1:1/cKDz3QCCOmwcztD2eV6Coggp6rqc9DGjWv7C0G+rM=

버킷에 접근할 모든 머신에서 사용자 지정 바이너리 캐시를 사용하도록 Nix 설정하기. 예를 들어, nix.conf의 substituters에 캐시 URL을, trusted-public-keys에 공개 키를 추가하십시오:

substituters = https://cache.nixos.org/ s3://example-nix-cache
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= example-nix-cache-1:1/cKDz3QCCOmwcztD2eV6Coggp6rqc9DGjWv7C0G+rM=

캐시용으로 빌드하는 머신은 개인 키를 사용하여 derivation에 서명해야 합니다. 방금 생성한 개인 키가 담긴 파일의 경로를 해당 머신의 secret-key-files 설정에 추가해야 합니다:

secret-key-files = /etc/nix/key.private

빌드 훅 구현하기#

다음 스크립트를 /etc/nix/upload-to-cache.sh에 작성하십시오:

#!/bin/sh
set -eu
set -f # disable globbing
export IFS=' '
echo "Uploading paths" $OUT_PATHS
exec nix copy --to "s3://example-nix-cache" $OUT_PATHS

$OUT_PATHS 변수는 공백으로 구분된 Nix 스토어 경로 목록입니다. 여기서는 셸이 단어 분할을 수행하여 각 출력 경로가 nix store sign의 개별 인자가 되기를 기대하며, 또 그렇게 되어야 합니다. Nix는 경로에 공백이 포함되지 않음을 보장하지만, 스토어 경로에 glob 문자가 포함될 수는 있습니다. set -f는 셸의 glob 확장을 비활성화합니다.

root 사용자가 훅 프로그램을 실행할 수 있는지 확인하십시오:

# chmod +x /etc/nix/upload-to-cache.sh

Nix 설정 업데이트하기#

로컬 머신에서 훅이 실행되도록 post-build-hook 설정 옵션을 지정하십시오:

post-build-hook = /etc/nix/upload-to-cache.sh

그런 다음 관련된 모든 머신에서 nix-daemon을 재시작하십시오. 예를 들면 다음과 같습니다.

pkill nix-daemon

테스트#

아무 derivation이나 빌드하십시오. 예를 들면 다음과 같습니다.

$ nix-build -E '(import <nixpkgs> {}).writeText "example" (builtins.toString builtins.currentTime)'
this derivation will be built:
  /nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv
building '/nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv'...
running post-build-hook '/home/grahamc/projects/github.com/NixOS/nix/post-hook.sh'...
post-build-hook: Signing paths /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
post-build-hook: Uploading paths /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
/nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example

훅이 적용되었는지 확인하려면 스토어에서 해당 경로를 삭제한 뒤 바이너리 캐시에서 대체해 보십시오:

$ rm ./result
$ nix-store --delete /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
$ nix-store --realise /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
copying path '/nix/store/m8bmqwrch6l3h8s0k3d673xpmipcdpsa-example from 's3://example-nix-cache'...
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
/nix/store/m8bmqwrch6l3h8s0k3d673xpmipcdpsa-example

결론#

이제 모든 로컬 빌드를 자동으로 서명하여 원격 S3 호환 바이너리 캐시에 업로드하도록 Nix를 설정했습니다.

이를 프로덕션에 배포하기 전에 반드시 구현상 주의 사항을 검토하십시오.