---
myst:
  html_meta:
    "description lang=en": "Setting up a binary cache for store objects"
    "keywords": "Nix, caching"
---

(setup-http-binary-cache)=
# HTTP 바이너리 캐시 설정하기

```{contributors}
:authors: tfc
:editors: fricklerhandwerk
```

바이너리 캐시는 미리 빌드된 [Nix 스토어 객체](https://nix.dev/manual/nix/latest/store/store-object)를 저장하고 네트워크를 통해 다른 머신에 제공합니다. Nix 스토어가 있는 머신이라면 어떤 머신이든 다른 머신을 위한 바이너리 캐시가 될 수 있습니다.

## 소개

이 튜토리얼에서는 NixOS 머신의 스토어 객체를 HTTP 또는 HTTPS로 제공하는 Nix 바이너리 캐시를 설정합니다.

### 무엇을 배우게 됩니까?

다음 방법을 배웁니다:
- 캐시용 서명 키 설정하기
- 캐시를 제공하는 NixOS 머신에서 필요한 서비스 활성화하기
- 설정이 의도한 대로 동작하는지 확인하기

### 무엇이 필요합니까?

- 로컬 머신에 정상적으로 동작하는 [Nix 설치](<install-nix>)

- 캐시로 사용할 NixOS 머신에 대한 SSH 접근 권한

  NixOS를 처음 사용한다면 [모듈 시스템](module-system-tutorial)에 대해 알아보고 [](nixos-vms)로 첫 번째 시스템을 설정하십시오.

- (선택 사항) 공인 IP와 DNS 도메인

  직접 호스팅하지 않는다면 NixOS 위키의 [NixOS 친화적인 호스팅 업체](https://wiki.nixos.org/wiki/NixOS_friendly_hosters)를 확인하십시오. [](provisioning-remote-machines-tutorial)에 대한 튜토리얼을 따라 NixOS 설정을 배포하십시오.

로컬 네트워크의 캐시에 대해서는 다음을 가정합니다:
- 호스트 이름은 `cache`입니다(자신의 호스트 이름이나 IP 주소로 바꾸십시오)
- 호스트는 80번 포트에서 HTTP로 스토어 객체를 제공합니다(기본값입니다)

공개적으로 접근 가능한 캐시에 대해서는 다음을 가정합니다:
- 도메인 이름은 `cache.example.com`입니다(자신의 도메인 이름으로 바꾸십시오)
- 호스트는 443번 포트에서 HTTPS로 스토어 객체를 제공합니다(기본값입니다)

### 얼마나 걸립니까?

- 25분

## 서비스 설정하기

캐시를 호스팅하는 NixOS 머신을 위해 `binary-cache.nix`에 새 설정 모듈을 만드십시오:

```{code-block} nix
{ config, ... }:

{
  services.nix-serve = {
    enable = true;
    secretKeyFile = "/var/secrets/cache-private-key.pem";
  };

  services.nginx = {
    enable = true;
    recommendedProxySettings = true;
    virtualHosts.cache = {
      locations."/".proxyPass = "http://${config.services.nix-serve.bindAddress}:${toString config.services.nix-serve.port}";
    };
  };

  networking.firewall.allowedTCPPorts = [
    config.services.nginx.defaultHTTPListenPort
  ];
}
```

[`services.nix-serve`] 아래의 옵션은 바이너리 캐시 서비스를 설정합니다.

`nix-serve`는 IPv6나 SSL/HTTPS를 지원하지 않습니다. [`services.nginx`] 옵션은 호스트 이름 `cache`로 들어오는 요청을 처리할 프록시를 설정하는 데 사용되며, 이 프록시는 IPv6를 지원합니다.

[`services.nix-serve`]: https://search.nixos.org/options?query=services.nix-serve
[`services.nginx`]: https://search.nixos.org/options?query=services.nginx

:::{important}
이 튜토리얼의 끝에 [선택 사항인 HTTPS 섹션](https-binary-cache)이 있습니다.
:::

새 NixOS 모듈을 기존 머신 설정에 추가하십시오:

```{code-block} nix
{ config, ... }:

{
  imports = [
    ./binary-cache.nix
  ];

  # ...
}
```

로컬 머신에서 새 설정을 배포하십시오:

```shell-session
nixos-rebuild switch --no-flake --target-host root@cache
```

:::{note}
아직 비밀 키 파일이 없으므로 바이너리 캐시 데몬이 오류를 보고합니다.
:::

## 서명 키 쌍 생성하기

캐시에 있는 스토어 객체가 진본임을 보장하려면 개인 키와 공개 키 한 쌍이 필요합니다.

<!-- TODO: link to the remote builds tutorial for the case where store objects are signed after building them -->

바이너리 캐시용 키 쌍을 생성하려면 예시 호스트 이름 `cache.example.com`을 여러분의 호스트 이름으로 바꾸십시오:

```shell-session
nix-store --generate-binary-cache-key cache.example.com cache-private-key.pem cache-public-key.pem
```

`cache-private-key.pem`은 바이너리 캐시 데몬이 바이너리를 제공할 때 서명하는 데 사용됩니다. 캐시를 호스팅하는 머신에서 `services.nix-serve.secretKeyFile`에 설정된 위치로 이 파일을 복사하십시오:

```shell-session
scp cache-private-key.pem root@cache:/var/secrets/cache-private-key.pem
```

지금까지 바이너리 캐시 데몬은 비밀 키 파일이 없어서 재시작을 반복하고 있었습니다. 이제 올바르게 작동하는지 확인하십시오:

```shell-session
ssh root@cache systemctl status nix-serve.service
```

:::{important}
[](custom-binary-cache) — 로컬 머신에서 `cache-public-key.pem`을 사용하십시오.
:::

## 가용성 테스트하기

다음 단계에서는 모든 것이 올바르게 설정되었는지 확인하며, 문제를 파악하는 데 도움이 될 수 있습니다.

### 일반 가용성 확인하기

캐시에 쿼리를 보내 바이너리 캐시, 리버스 프록시, 방화벽 규칙이 의도한 대로 작동하는지 테스트하십시오:

```shell-session
$ curl http://cache/nix-cache-info
StoreDir: /nix/store
WantMassQuery: 1
Priority: 30
```

### 스토어 객체 서명 확인하기

스토어 객체가 올바르게 서명되었는지 테스트하려면 예시 derivation의 메타데이터를 살펴보십시오. 바이너리 캐시 호스트에서 `hello` 패키지를 빌드하고 캐시에서 `.narinfo` 파일을 가져오십시오:

```shell-session
$ hash=$(nix-build '<nixpkgs>' -A pkgs.hello | awk -F '/' '{print $4}' | awk -F '-' '{print $1}')
$ curl "http://cache/$hash.narinfo" | grep "Sig: "
...
Sig: cache.example.org:GyBFzocLAeLEFd0hr2noK84VzPUw0ArCNYEnrm1YXakdsC5FkO2Bkj2JH8Xjou+wxeXMjFKa0YP2AML7nBWsAg==
```

출력에 `Sig:`로 시작하는 줄이 포함되어 있고 그 줄에 여러분이 생성한 공개 키가 표시되는지 확인하십시오.

(https-binary-cache)=
### HTTPS로 바이너리 캐시 제공하기

바이너리 캐시에 공개적으로 접근할 수 있다면 [Let's Encrypt](https://letsencrypt.org/) SSL 인증서로 HTTPS를 강제할 수 있습니다. 다음과 같이 `binary-cache.nix`를 편집하고, 예시 URL과 메일 주소를 반드시 여러분의 것으로 바꾸십시오:

```{code-block} diff
   services.nginx = {
     enable = true;
     recommendedProxySettings = true;
-    virtualHosts.cache = {
+    virtualHosts."cache.example.com" = {
+      enableACME = true;
+      forceSSL = true;
       locations."/".proxyPass = "http://${config.services.nix-serve.bindAddress}:${toString config.services.nix-serve.port}";
     };
   };

+   security.acme = {
+     acceptTerms = true;
+     certs = {
+       "cache.example.com".email = "you@example.com";
+     };
+   };

   networking.firewall.allowedTCPPorts = [
     config.services.nginx.defaultHTTPListenPort
+    config.services.nginx.defaultSSLListenPort
   ];
```

시스템을 다시 빌드하여 이 변경 사항을 배포하십시오:

```shell-session
nixos-rebuild switch --no-flake --target-host root@cache.example.com
```

## 다음 단계

바이너리 캐시가 이미 [원격 빌드 머신](https://nix.dev/manual/nix/latest/advanced-topics/distributed-builds)이라면 해당 Nix 스토어의 모든 스토어 객체를 제공합니다.

- [](custom-binary-cache) — 바이너리 캐시의 호스트 이름과 생성한 공개 키를 사용하십시오
- [](post-build-hooks) — 스토어 객체를 바이너리 캐시에 업로드하는 방법
- [](distributed-build-setup-tutorial)

저장 공간을 절약하려면 다음 NixOS 설정 속성을 참고하십시오:

- [`nix.gc`](https://search.nixos.org/options?query=nix.gc): 자동 가비지 컬렉션 옵션
- [`nix.optimise`](https://search.nixos.org/options?query=nix.optimise): 주기적인 Nix 스토어 최적화 옵션

## 대안

- [`nix-serve-ng`](https://github.com/aristanetworks/nix-serve-ng): Haskell로 작성된 `nix-serve`의 드롭인 대체품

- [SSH 스토어](https://nix.dev/manual/nix/latest/store/types/ssh-store), [실험적 SSH 스토어](https://nix.dev/manual/nix/latest/store/types/experimental-ssh-store), [S3 바이너리 캐시 스토어](https://nix.dev/manual/nix/latest/store/types/s3-binary-cache-store)도 캐시를 제공하는 데 사용할 수 있습니다. S3 호환 스토리지를 제공하는 상용 업체는 많이 있습니다. 예를 들면 다음과 같습니다.
  - Amazon S3
  - Tigris
  - Cloudflare R2

- [attic](https://github.com/zhaofengli/attic): S3 호환 스토리지 제공 업체를 기반으로 하는 Nix 바이너리 캐시 서버

- [Cachix](https://www.cachix.org): 서비스형 Nix 바이너리 캐시

## 참고 자료

- [HTTP 바이너리 캐시 스토어에 관한 Nix 매뉴얼](https://nix.dev/manual/nix/latest/store/types/http-binary-cache-store)
- [`services.nix-serve` 모듈 옵션][`services.nix-serve`]
- [`services.nginx` 모듈 옵션][`services.nginx`]
