---
myst:
  html_meta:
    "description lang=en": "Provisioning remote machines"
    "keywords": "Nix, deployment, remote, provisioning, nixos-anywhere, disko, partitioning, installation"
---

(provisioning-remote-machines-tutorial)=
# SSH를 통한 원격 머신 프로비저닝

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

[`nixos-anywhere`]와 [`disko`]를 사용하면 실행 중인 시스템에서 어떤 Linux 설치든 NixOS 설정으로 교체할 수 있습니다.

[`nixos-anywhere`]: https://nix-community.github.io/nixos-anywhere/
[`disko`]: https://github.com/nix-community/disko

## 소개

이 튜토리얼에서는 실행 중인 컴퓨터에 NixOS 설정을 배포합니다.

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

다음 방법을 배웁니다.
- 선언적 디스크 레이아웃과 SSH 접근을 갖춘 최소한의 NixOS 설정을 지정하는 방법
- 설정이 유효한지 확인하는 방법
- 원격 머신에 NixOS 설정을 배포하고 업데이트하는 방법

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

- [Nix 언어](reading-nix-language)에 대한 이해
- [](module-system-tutorial)에 대한 이해

무인 설치를 성공적으로 수행하려면 *대상 머신*이 다음 조건을 충족하는지 확인하십시오.

- Linux를 실행하는 QEMU 가상 머신이어야 합니다
  - [`kexec`](https://en.wikipedia.org/wiki/Kexec)를 지원해야 합니다
  - `x86-64` 또는 `aarch64` 명령어 집합 아키텍처(ISA)여야 합니다
  - RAM이 최소 1GB 이상이어야 합니다

  [NixOS 설치 프로그램](https://nixos.org/download/#download-nixos-accordion)처럼 USB로 부팅한 라이브 시스템이어도 됩니다.

- IP 주소가 DHCP로 자동 설정되어야 합니다
- SSH로 로그인할 수 있어야 합니다
  - 공개 키 인증(권장) 또는 비밀번호를 사용해야 합니다
  - `root` 사용자 또는 `sudo` 권한이 있는 다른 사용자로 로그인해야 합니다

*로컬 머신*에는 정상적으로 동작하는 [Nix 설치](install-nix)만 있으면 됩니다.

이 튜토리얼에서는 *대상 머신*을 `target-machine`이라고 부릅니다. 이를 실제 호스트 이름 또는 IP 주소로 바꾸십시오.

## 환경 준비하기

새 프로젝트 디렉터리를 만들고 셸에서 해당 디렉터리로 이동하십시오.

```shell-session
mkdir remote
cd remote
```

`nixpkgs`, `disko`, `nixos-anywhere`에 대한 [의존성을 지정하십시오](dependency-management-npins).

```shell-session
$ nix-shell -p npins
[nix-shell:remote]$ npins init
[nix-shell:remote]$ npins add github nix-community disko
[nix-shell:remote]$ npins add github nix-community nixos-anywhere
```

고정된 의존성을 사용하여 필요한 모든 도구를 제공하는 새 파일 `shell.nix`를 만드십시오.

```{code-block} nix
let
  sources = import ./npins;
  pkgs = import sources.nixpkgs {};
in

pkgs.mkShell {
  nativeBuildInputs = with pkgs; [
    npins
    nixos-anywhere
    nixos-rebuild
  ];
  shellHook = ''
    export NIX_PATH="nixpkgs=${sources.nixpkgs}:nixos-config=$PWD/configuration.nix"
  '';
}
```

이제 임시 환경을 종료하고 새로 지정한 환경에 진입하십시오.

```shell-session
[nix-shell:remote]$ exit
$ nix-shell
```

이 셸 환경에서는 `nixos-anywhere` 및 `nixos-rebuild`와 함께 명확하게 정의된 버전의 Nixpkgs를 사용할 수 있습니다.

:::{important}
이후의 모든 명령은 이 환경에서 실행하십시오.
:::

## NixOS 설정 만들기

새 NixOS 설정은 일반 시스템 설정과 디스크 레이아웃 명세로 구성됩니다.

이 예제의 디스크 레이아웃은 [마스터 부트 레코드](https://en.wikipedia.org/wiki/Master_boot_record)(MBR)와 [EFI 시스템 파티션](https://en.wikipedia.org/wiki/EFI_system_partition)(ESP) 파티션, 그리고 남은 가용 공간 전체를 차지하는 루트 파일 시스템을 갖춘 단일 디스크를 기술합니다. 이 레이아웃은 EFI 시스템과 BIOS 시스템 모두에서 동작합니다.

디스크 레이아웃 명세를 담은 새 파일 `single-disk-layout.nix`를 만드십시오:

{lineno-start=1}
```nix
{ ... }:

{
  disko.devices.disk.main = {
    type = "disk";
    content = {
      type = "gpt";
      partitions = {
        MBR = {
          priority = 0;
          size = "1M";
          type = "EF02";
        };
        ESP = {
          priority = 1;
          size = "500M";
          type = "EF00";
          content = {
            type = "filesystem";
            format = "vfat";
            mountpoint = "/boot";
          };
        };
        root = {
          priority = 2;
          size = "100%";
          content = {
            type = "filesystem";
            format = "ext4";
            mountpoint = "/";
          };
        };
      };
    };
  };
}
```

디스크 레이아웃 정의를 가져오고 포맷할 디스크를 지정하는 파일 `configuration.nix`를 만드십시오:

:::{tip}
대상 디스크의 장치 식별자를 모른다면 `lsblk`로 *대상 머신*의 모든 장치를 나열하십시오:

```shell-session
$ ssh target-machine lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda      8:0    0   256G  0 disk
├─sda1   8:1    0 248.5G  0 part /nix/store
│                                /
└─sda2   8:2    0   7.5G  0 part [SWAP]
sr0     11:0    1  1024M  0 rom
```

이 예제에서 디스크 이름은 `sda`입니다. 따라서 블록 장치 경로는 `/dev/sda`입니다. 나중을 위해 이 값을 기록해 두십시오.
:::

{lineno-start=1}
```nix
{ modulesPath, ... }:

let
  diskDevice = "/dev/sda";
  sources = import ./npins;
in
{
  imports = [
    (modulesPath + "/profiles/qemu-guest.nix")
    (sources.disko + "/module.nix")
    ./single-disk-layout.nix
  ];

  disko.devices.disk.main.device = diskDevice;

  boot.loader.grub = {
    devices = [ diskDevice ];
    efiSupport = true;
    efiInstallAsRemovable = true;
  };

  services.openssh.enable = true;

  users.users.root.openssh.authorizedKeys.keys = [
    "<your SSH key here>"
  ];

  system.stateVersion = "24.11";
}
```

:::{important}
`/dev/sda`를 사용하는 디스크의 블록 장치 경로로 바꾸십시오.

`<your SSH key here>` 문자열을 앞으로 `root` 사용자로 로그인할 때 사용할 SSH 공개 키로 바꾸십시오.
:::

:::{dropdown} 자세한 설명

`let` 블록의 `diskDevice` 변수는 디스크 블록 장치의 경로를 정의합니다:

{lineno-start=3 emphasize-lines="2"}
```nix
let
  diskDevice = "/dev/sda";
  sources = import ./npins;
in
```

이 변수는 디스크 레이아웃 명세에 기술된 대로 파티션 분할과 포맷의 대상을 지정하는 데 사용됩니다. 또한 부트 로더 설정에서도 사용되어 레거시 BIOS와 UEFI 시스템 모두에서 부팅할 수 있게 합니다:

{lineno-start=14 emphasize-lines="1,4"}
```nix
  disko.devices.disk.main.device = diskDevice;

  boot.loader.grub = {
    devices = [ diskDevice ];
    efiSupport = true;
    efiInstallAsRemovable = true;
  };
```

`qemu-guest.nix` 모듈은 이 시스템이 QEMU 가상 머신 안에서 실행될 수 있도록 호환성을 제공합니다:

{lineno-start=8 emphasize-lines="2"}
```nix
  imports = [
    (modulesPath + "/profiles/qemu-guest.nix")
    (sources.disko + "/module.nix")
    ./single-disk-layout.nix
  ];
```

`disko` 라이브러리는 디스크 레이아웃 명세로부터 파티션 분할 스크립트와, 부팅 시 파티션을 그에 맞게 마운트하는 NixOS 설정 부분을 생성합니다. 첫 번째 줄은 라이브러리를 가져오고, 두 번째 줄은 디스크 레이아웃을 적용합니다:

{lineno-start=8 emphasize-lines="3,4"}
```nix
  imports = [
    (modulesPath + "/profiles/qemu-guest.nix")
    (sources.disko + "/module.nix")
    ./single-disk-layout.nix
  ];
```
:::

## 디스크 레이아웃 테스트하기

디스크 레이아웃이 유효한지 확인하십시오:

```shell-session
nix-build -E "((import <nixpkgs> {}).nixos [ ./configuration.nix ]).installTest"
```

이 명령은 `disko` 모듈이 제공하는 `installTest` 속성의 derivation을 빌드하여 가상 머신에서 전체 설치 과정을 실행합니다.

## 시스템 배포하기

시스템을 배포하려면 설정과 그에 해당하는 디스크 포맷 스크립트를 빌드한 뒤, 그 결과를 사용하여 `nixos-anywhere`를 실행하십시오:

:::{important}
`target-host`를 *대상 머신*의 호스트 이름 또는 IP 주소로 바꾸십시오.
:::

```shell-session
toplevel=$(nixos-rebuild build --no-flake)
diskoScript=$(nix-build -E "((import <nixpkgs> {}).nixos [ ./configuration.nix ]).diskoScript")
nixos-anywhere --store-paths "$diskoScript" "$toplevel" root@target-host
```

:::{note}
공개 키 인증을 사용하지 않는 경우: 환경 변수 `SSH_PASS`에 비밀번호를 설정한 다음 `nixos-anywhere` 명령에 `--env-password` 플래그를 덧붙이십시오.
:::

이제 `nixos-anywhere`가 대상 시스템에 로그인하여 디스크를 파티션 분할, 포맷, 마운트하고 NixOS 설정을 설치합니다. 그런 다음 시스템을 재부팅합니다.

## 시스템 업데이트하기

시스템을 업데이트하려면 `npins`를 실행하고 설정을 다시 배포하십시오:

```shell-session
npins update nixpkgs
nixos-rebuild switch --no-flake --target-host root@target-host
```

디스크 레이아웃을 변경하려는 경우가 아니라면 `nixos-anywhere`는 더 이상 필요하지 않습니다.


# 다음 단계

- [](binary-cache-setup)
- [](post-build-hooks)

## 참고 자료

- [`nixos-anywhere` 프로젝트 페이지][`nixos-anywhere`]
- [`disko` 프로젝트 저장소][`disko`]
- [디스크 레이아웃 예제 모음](https://github.com/nix-community/disko/tree/master/example)
