---
myst:
  html_meta:
    "description lang=en": "Continuous Integration with GitHub Actions and Cachix"
    "keywords": "NixOS, deployment, Terraform, AWS"
---

(deploy-nixos-using-terraform)=
# Terraform을 사용하여 NixOS 배포하기

```{contributors}
:authors: domenkozar
```
이 튜토리얼은 여러분이 [Terraform의 기초에 익숙하다](https://www.terraform.io/intro/index.html)고 가정합니다. 튜토리얼을 마치면 Terraform으로 Amazon Web Services(AWS) 인스턴스를 프로비저닝하고, Nix를 사용하여 해당 인스턴스에서 실행 중인 NixOS에 점진적인 변경 사항을 배포하게 됩니다.

NixOS 머신을 부팅하는 방법과 점진적인 변경 사항을 배포하는 방법을 살펴보겠습니다.

## NixOS 이미지 부팅하기

1. 먼저 Terraform 실행 파일을 준비하십시오:

```shell-session
$ nix-shell -p terraform
```

2. [Terraform Cloud](https://app.terraform.io)를 [상태/잠금 백엔드](https://www.terraform.io/docs/state/purpose.html)로 사용합니다:

```shell-session
$ terraform login
```

3. Terraform Cloud 계정에 `myorganization`과 같은 [조직을 생성하십시오](https://app.terraform.io/app/organizations/new).
4. `myorganization` 안에서 **CLI-driven workflow**를 선택하여 [워크스페이스를 생성하고](https://app.terraform.io/app/cachix/workspaces/new) `myapp`과 같은 이름을 지정하십시오.
5. 워크스페이스 안의 `Settings / General`에서 Execution Mode를 `Local`로 변경하십시오.
6. 새 디렉터리 안에 다음 내용으로 `main.tf` 파일을 생성하십시오. 이 파일은 SSH 키 쌍 하나와 SSH 보안 그룹을 사용하여 NixOS 이미지로 AWS 인스턴스를 시작합니다:

```terraform
terraform {
    backend "remote" {
        organization = "myorganization"

        workspaces {
            name = "myapp"
        }
    }
}

provider "aws" {
    region = "eu-central-1"
}

module "nixos_image" {
    source  = "git::https://github.com/tweag/terraform-nixos.git//aws_image_nixos?ref=5f5a0408b299874d6a29d1271e9bffeee4c9ca71"
    release = "20.09"
}

resource "aws_security_group" "ssh_and_egress" {
    ingress {
        from_port   = 22
        to_port     = 22
        protocol    = "tcp"
        cidr_blocks = [ "0.0.0.0/0" ]
    }

    egress {
        from_port       = 0
        to_port         = 0
        protocol        = "-1"
        cidr_blocks     = ["0.0.0.0/0"]
    }
}

resource "tls_private_key" "state_ssh_key" {
    algorithm = "RSA"
}

resource "local_file" "machine_ssh_key" {
    sensitive_content = tls_private_key.state_ssh_key.private_key_pem
    filename          = "${path.module}/id_rsa.pem"
    file_permission   = "0600"
}

resource "aws_key_pair" "generated_key" {
    key_name   = "generated-key-${sha256(tls_private_key.state_ssh_key.public_key_openssh)}"
    public_key = tls_private_key.state_ssh_key.public_key_openssh
}

resource "aws_instance" "machine" {
    ami             = module.nixos_image.ami
    instance_type   = "t3.micro"
    security_groups = [ aws_security_group.ssh_and_egress.name ]
    key_name        = aws_key_pair.generated_key.key_name

    root_block_device {
        volume_size = 50 # GiB
    }
}

output "public_dns" {
    value = aws_instance.machine.public_dns
}
```

NixOS에 특화된 부분은 다음 코드 조각뿐입니다:

```terraform
module "nixos_image" {
  source = "git::https://github.com/tweag/terraform-nixos.git/aws_image_nixos?ref=5f5a0408b299874d6a29d1271e9bffeee4c9ca71"
  release = "20.09"
}
```

:::{note}
`aws_image_nixos` 모듈은 [NixOS 릴리스 번호](https://status.nixos.org)가 주어지면 NixOS AMI를 반환하므로, `aws_instance` 리소스가 [instance_type](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#instance_type) 인수에서 해당 AMI를 참조할 수 있습니다.
:::

5. [AWS 자격 증명을 설정하십시오](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication).
6. Terraform 설정을 적용하면 실행 중인 NixOS를 얻을 수 있습니다:

```shell-session
$ terraform init
$ terraform apply
```

## NixOS 변경 사항 배포하기

Terraform을 통해 AWS 인스턴스에서 NixOS 이미지가 실행되면, Terraform이 항상 최신 NixOS 설정을 빌드하고 그 변경 사항을 인스턴스에 적용하도록 만들 수 있습니다.

1. 다음 내용으로 `configuration.nix`를 생성하십시오:

```nix
{ config, lib, pkgs, ... }: {
  imports = [ <nixpkgs/nixos/modules/virtualisation/amazon-image.nix> ];

  # Open https://search.nixos.org/options for all options
}
```

2. 다음 코드 조각을 `main.tf`에 추가하십시오:

```terraform
module "deploy_nixos" {
    source = "git::https://github.com/tweag/terraform-nixos.git//deploy_nixos?ref=5f5a0408b299874d6a29d1271e9bffeee4c9ca71"
    nixos_config = "${path.module}/configuration.nix"
    target_host = aws_instance.machine.public_ip
    ssh_private_key_file = local_file.machine_ssh_key.filename
    ssh_agent = false
}
```

3. 배포하십시오:

```shell-session
$ terraform init
$ terraform apply
```

## 주의 사항

- `deploy_nixos` 모듈을 사용하려면 대상 머신에 NixOS가, 호스트 머신에 Nix가 설치되어 있어야 합니다.
- `deploy_nixos` 모듈은 클라이언트와 대상의 아키텍처가 다르면 작동하지 않습니다([분산 빌드](https://nix.dev/manual/nix/stable/advanced-topics/distributed-builds.html)를 사용하는 경우는 예외입니다).
- Nix에 값을 주입해야 하는 경우, 깔끔한 해결책이 없습니다.
- 각 머신은 개별적으로 평가되므로, 필요한 메모리가 머신 수에 비례하여 선형적으로 증가한다는 점에 유의하십시오.

## 다음 단계

- [Google Compute Engine으로 전환하는 것](https://github.com/tweag/terraform-nixos/tree/master/google_image_nixos#readme)도 가능합니다.
- [`deploy_nixos` 모듈](https://github.com/tweag/terraform-nixos/tree/master/deploy_nixos#readme)은 키 업로드 등을 위한 여러 인수를 지원합니다.
