7년 쓴 테라폼 클라우드를 떠나 OpenTofu로: 상태 암호화부터 GitHub environment 승인까지

.

안녕하세요, 페미위키 개발팀 낙엽1124입니다. 테라폼을 써 보셨다면 OpenTofu라는 이름도 한 번쯤 들어 보셨을 것 같은데요, 2023년 테라폼의 라이선스가 바뀐 뒤 커뮤니티가 리눅스 재단 아래에서 이어 가는 오픈 소스 포크입니다.[1] 페미위키는 최근 7년 가까이 쓰던 테라폼 클라우드(HCP Terraform)를 모두 걷어내고 OpenTofu와 GitHub Actions로 옮겼습니다. 이번 글에서는 옮기는 과정과 소회를 적어 보려고 합니다.

테라폼 클라우드와 함께한 7년

이 글에서는 테라폼에 대해서는 이미 아실 거로 가정하겠습니다. 테라폼은 혼자 쓸 때는 터미널에서 plan과 apply를 실행하면 그만이지만 여럿이 함께 쓰기 시작하면 상태 파일을 어디에 둘지, 두 사람이 동시에 apply하지 않게 어떻게 막을지, 누가 언제 무엇을 바꿨는지 어떻게 남길지가 고민거리가 되는 툴입니다. 이런 일을 대신 맡아 주는 서비스를 흔히 TACOS(Terraform Automation and Collaboration Software)라고 하는데,[2] 테라폼 클라우드는 HashiCorp가 직접 만든 TACOS입니다. 상태를 보관하고 락을 잡아 주며, 저장소에 PR이 올라오면 plan을 돌리고, 웹 화면에서 확인 버튼을 누르면 apply해 주며 웹훅 등 노티까지 대신 발송해줍니다.

페미위키는 2019년부터 인프라를 femiwiki/infra 저장소에 테라폼 코드로 적고, 테라폼 클라우드로 plan과 apply를 돌려 왔습니다.[3] 테라폼을 만든 회사가 직접 내놓은, IaC의 최첨단에 있는 도구인 데다 무료로 쓸 수 있었기 때문입니다. OpenTofu 이전을 시작할 무렵 페미위키의 테라폼 클라우드에는 워크스페이스(이 글에서는 테라폼 클라우드의 용어를 따라, 상태 파일 하나를 쓰는 디렉터리 하나를 이렇게 부르겠습니다)가 셋 있었습니다(VPC, EC2 인스턴스, IAM, Route 53 같은 AWS 자원을 다루는 aws, GitHub 조직의 저장소와 라벨을 다루는 github, 앱 서버에서 도는 Docker 컨테이너를 다루는 docker).

많이 쓰다보니 편리함도 컸지만 다음은 제가 느낀 불편함들입니다.

  • 비밀번호 같은 값은 테라폼 클라우드의 웹 화면에서 민감한 변수로 넣었는데, 민감한 변수는 한 번 넣으면 넣은 사람조차 값을 다시 볼 수 없습니다.[4] 당연히 필요한 조치이긴 하지만 코드에도 남지 않고 화면에서도 보이지 않으니 몇 년이 지나자 어떤 변수가 왜 들어 있는지, 지금 값이 맞는지 확인할 길이 없었습니다. 일례로 aws 워크스페이스에는 코드 어디에도 선언되지 않은 db_user_password가 값을 가진 채 남아 있었고, 이게 아마 DB 루트 계정 비밀번호 같긴 했는데 확인을 할 수가 없었습니다(이전 글에서 루트 계정 비밀번호를 잃어버려서 새로 만든 이야기를 해드렸습니다).[5]
  • 테라폼 클라우드의 설정까지 코드로 관리하면 좋지 않을까 싶어, 2020년 3월에 tfe 프로바이더로 워크스페이스들을 선언하는 terraform-cloud 워크스페이스를 만들었습니다. 그런데[6] 7월에 저장소 연결을 GitHub 앱 방식으로 바꾸자 tfe 프로바이더가 그 연결을 설정하지 못했습니다.[7] 결국 연결 설정을 코드에서 빼고, 같은 날 그 워크스페이스를 지웠습니다.[8][9]
  • 테라폼 클라우드 무료 플랜은 관리하는 리소스가 500개까지인데,[10] 인프라가 늘면서 Organization femiwiki Has Exceeded its Managed Resource Limit라는 살벌한 이메일을 받은 적이 있습니다.
  • 반복문으로 프로바이더 설정을 여러 벌 만드는 provider for_each는 2019년 1월 테라폼에 피처 요청이 올라왔지만 아직도 열려만 있고,[11] HCP Terraform 위에서 도는 Stacks에서 지원이 추가됐다는 소식만 들려왔습니다.[12][13] 즉 Terraform이 점점 오픈 코어가 되어 가는 모양새였습니다. 그사이 OpenTofu는 2024년 1.7에서 상태 암호화를,[14] 2025년 1.9에서 provider for_each와 -exclude를 내놓았습니다.[15]

먼저 써 본 Digger

테라폼 클라우드의 원격 실행은 테라폼만 돌립니다. 그러니 OpenTofu로 가려면 plan과 apply를 돌릴 곳도 따로 찾아야 했습니다.[16]

그때 눈에 들어온 것이 Digger(지금은 이름을 OpenTaco로 바꿨습니다)였습니다. 계기는 OpenTofu 사이트가 처음 생겼을 때부터 후원사로 이름이 있었어서 관심을 갖게 된 것입니다.[17] Digger는 동명의 스타트업 Digger가 MIT 라이선스로 공개한 TACOS로,[주 1] 스스로를 테라폼 클라우드나 Atlantis의 대안으로 소개합니다. GitHub Actions 안에서 plan을 돌려 PR 댓글로 남기고, 사람이 댓글로 apply를 요청할 수 있습니다(같은 일을 하는 도구로는 리눅스 재단 산하의 Atlantis가 더 유명한데, 다만 제가 당시에는 Atlantis를 미처 몰랐습니다)

2025년 8월 24일, docker 워크스페이스에 Digger를 붙여 PoC를 해 봤습니다.[20] 당시 이 워크스페이스는 SSH 키를 local_file로 써 두고 Docker 데몬에 SSH로 접속했는데, 이 부분을 Digger 워크플로 안에서 풀어내지 못해 다음 날 걷어냈습니다.[21] Digger 탓이라기보다 제 설정이 모자랐던 것 같긴 합니다만....

또 Digger의 PR 자동화를 제대로 쓰려면 오케스트레이터 서버가 있어야 합니다.[22] 직접 운영하려면 Postgres와 웹훅을 받을 공개 주소까지 갖춰야 합니다.[23][24] 인프라를 관리하는 도구를 위해 서버를 하나 더 켜 두고, 그 서버를 다시 인프라로 관리해야 하는 셈입니다. 오케스트레이터 없이 GitHub Actions만으로 쓰는 방식도 있는데, 그러면 plan과 apply가 동시에 돌지 못해 PR이 여러 워크스페이스를 바꿀 때마다 차례를 기다려야 하고, 두 PR이 같은 프로젝트를 동시에 plan하지 않도록 잡는 PR 단위 잠금을 기록할 DynamoDB 테이블도 따로 마련해 두어야 합니다.[22] 따라서 페미위키에서 당장 쓰기에는 부담이 컸습니다..

그렇게 1년 넘게 테라폼 클라우드를 그대로 썼습니다.

Docker 데몬 포트를 닫은 날

일이 다시 움직인 것은 2026년 9월입니다. 보안을 위해 앱 서버의 Docker 대몬 포트(2376, 참고로 막 열려있던 건 아니고 자체 발급 인증서 인증 과정이 있었습니다)를 인터넷에서 닫자, 테라폼 클라우드의 원격 러너가 docker 워크스페이스를 apply할 방법이 없어졌습니다. 대몬에 닿으려면 SSM 포트 포워딩으로 터널을 먼저 열어야 했고, 테라폼 클라우드 러너에서는 그 터널을 열 수 없었습니다. 그래서 9월 20일 오후, docker의 상태부터 S3로 옮기고 한동안 터미널에서 직접 테라폼을 실행했습니다.[25]

새 워크스페이스부터 OpenTofu로

접시에 담긴 노릇한 두부부침
OpenTofu의 Tofu는 두부의 일본식 발음입니다.[26] 처음 이름은 OpenTF였는데, TF가 Terraform과 너무 가깝다는 상표 걱정에 이름을 바꾸면서 포크(fork) 끝에 꽂아 먹을 만한 것이라는 농담을 담아 골랐다고 합니다.[27][28]

같은 날 저녁, Grafana Cloud의 경보를 코드로 관리하려고 grafana 워크스페이스를 결국 OpenTofu로 새로 만들었습니다. 저는 오래전부터 언젠가는 OpenTofu로 가자고 벼르고 있었고, 참고로 페미위키 개발팀은 팀이라기보다 느슨한 모임에 가까워서 이런 실무 결정은 제가 비교적 자유롭게 내릴 수 있었습니다. 2024년 3월에 개인 저장소에서 제 GitHub와 GitLab 저장소를 OpenTofu로 관리해 본 적도 있었고,[29] 그때 써 보니 생각보다 쓸 만했던 인상도 남아 있었습니다. 그래서 OpenTofu와 GitHub Actions로 시작했고 상태 파일은 S3 버킷에 워크스페이스별 경로(grafana/terraform.tfstate)로 두었습니다.[30]

plan과 apply는 한편 dflook/terraform-github-actions에 맡겼습니다. 이건 개인 개발자 dflook이 만든 테라폼·OpenTofu용 GitHub Actions 모음인데 tofu-plan은 plan을 PR 댓글로 남기고, tofu-apply는 apply하기 전에 plan을 다시 만들어 댓글의 plan과 다르면 멈춰 사람이 검토한 plan만 적용되게 도와 줍니다.[31] 여기에 더해 Digger의 기본 순서인 "머지하기 전에 apply하기"를 빌려 왔습니다.[32]

공개 저장소에서 plan을 돌리기 전에

Grafana에서의 실험이 잘 돌았기에 차례로 나머지 워크스페이스도 옮기게 되었습니다. 다만 infra 저장소는 공개 저장소라 테라폼 클라우드에서는 로그인해야 보이던 plan 출력과 Actions 로그를 이제 아무나 볼 수 있어집니다. 이를 막기 위해 비밀값에 sensitive 표시를 해 두면 plan 출력에서는 가려지겠지만 PR에서 그 값을 nonsensitive()로 감싸기만 해도 표시가 사라지고, local-exec나 URL에 값을 넣은 http 데이터 소스는 표시와 상관없이 값을 밖으로 내보낼 수 있습니다. 결국 저장소에 쓰기 권한이 있는 사람이면 상태에 든 비밀값을 모두 읽을 수 있으니, plan 자체를 막지 않으면 안심할 수 없었습니다.[33]

일단 처음엔 docker를 Actions로 올리기 전에 모든 비밀값을 OpenTofu 손이 닿지 않는 곳으로 옮겼습니다. 컨테이너는 비밀번호를 환경 변수로 받는 대신 시작할 때 인스턴스 역할로 AWS Parameter Store에서 직접 읽게 했습니다. 위키 이미지에서는 chamber를 쓰게 했고요. chamber는 Parameter Store에 둔 비밀값을 읽어 환경 변수로 넣은 뒤 프로그램을 실행해 주는 CLI입니다.[34]

-WG_DB_PASSWORD   = local.ssm_parameters_mysql["/mysql/users/mediawiki/password"]
-WG_SECRET_KEY    = local.ssm_parameters_mediawiki["/mediawiki/site_key"]
-WG_SMTP_PASSWORD = local.ssm_parameters_mediawiki["/mediawiki/smtp/password"]
+WG_DB_USER       = "mediawiki"
+
+SSM_SECRETS = "1"
+AWS_REGION  = "ap-northeast-1"

또 권한도, aws plan은 읽기 전용 역할 infra-aws-plan을 쓰게 하고 apply 역할은 아래 조건으로 후술할 GitHub environment aws에서 도는 작업만 맡을 수 있게 했습니다.[5]

condition {
  test     = "StringEquals"
  variable = "token.actions.githubusercontent.com:sub"
  # use_immutable_subject를 켜서 조직과 저장소의 숫자 ID가 들어갑니다
  values   = ["repo:femiwiki@21275875/infra@188597503:environment:aws"]
}

하나씩 옮기기

차곡차곡 쌓인 이삿짐 상자
이사는 한 상자씩.

docker는 비밀값을 빼낸 날 Actions에서 plan과 apply를 돌리기 시작했습니다.[35] 망가지면 사이트가 바로 멈추는 워크스페이스라 가장 위험했고 SSM으로 들어가 계속 손으로 고치는 방법도 있었지만,[36] AWS와 GitHub를 선언적으로 관리하며 누린 장점이 많았고 예전에 Nomad를 쓸 때도 컨테이너를 선언적으로 다뤘던 터라 어떻게든 docker도 코드로 관리하고 싶은 욕심이 있었습니다. 자체 발급 인증서 대신 SSM 터널을 여는 단계도 워크플로에 넣어 docker는 일단락했고, 남은 둘 가운데에서는 상태에 비밀값이 없는 github를 다음으로 옮겼습니다.

마지막 aws는 상태에 비밀값이 남아 있고 다른 워크스페이스가 쓰는 역할까지 가진 워크스페이스라 가장 준비과정이 복잡했습니다.

상태 암호화

aws에는 모니터링에 쓰는 prometheus_password, loki_password가 남아 있었고, 이 값은 상태 파일에 평문으로 들어가 있었습니다.

테라폼 CLI는 상태를 평문으로만 쓰기에 암호화는 S3 서버 측 암호화처럼 백엔드에 맡기거나 테라폼 클라우드에 맡기는 게 선택 가능한 지원 범위였습니다(2016년에 올라온 상태 암호화 제안은 2024년 5월 계획 없음으로 닫혔습니다[37]).[38] 반면 OpenTofu는 1.7부터 상태와 plan 파일을 직접 암호화한 뒤 백엔드에 쓰기에, 버킷을 읽을 수 있는 사람이라도 키가 없으면 내용을 볼 수 없게 할 수 있었습니다.[14]

다만 암호화에는 키가 필요한데, 키를 만드는 방법 중 aws/s3 같은 AWS 관리형 키는 자기 서비스에서만 쓸 수 있고, 직접 쓸 수 있는 고객 관리형 키는 한 달에 1달러가 드는 문제가 있었습니다(페미위키는 수익 구조가 없고 기부금과 정해진 양의 AWS 크레딧으로 서버비를 내고 있기에 이런 선택가능한 지출은 가능한 피했으면 했습니다). 그래서 passphrase에서 키를 만드는 pbkdf2를 골랐고 이를 1패스워드에 잘 저장하는 걸로 했습니다.[5]

잠금

과거 Digger 문서를 읽을 때에는 잠금에 DynamoDB 테이블이 반드시 따로 있어야 하는 줄 알았는데, 사실 OpenTofu 1.10부터 S3 백엔드는 DynamoDB 없이 스스로 잠글 수 있었습니다.[39] S3의 조건부 쓰기(If-None-Match)를 이용해 상태 파일 옆에 잠금 파일을 만드는 방식입니다.[40] 페미위키는 docker를 옮길 때부터 이 설정을 써서 DynamoDB 테이블을 만든 적이 없습니다(사실 Digger의 DynamoDB는 PR 단위 잠금용이라 이것과는 다른 이야기입니다). 테라폼도 같은 설정을 지원하는데, 테라폼 쪽은 기본값이 꺼져 있고 DynamoDB 잠금을 지원 중단 예정으로 고시해 놨습니다.[41]

빈 상태의 apply 차단

빈 백엔드에서 plan을 돌리면 228개 리소스가 모두 create로 나오고 이걸 그대로 승인하면 VPC와 서버 등을 한 벌 더 만들려다 실패할 수 있습니다. 그래서 plan에 필요한 시크릿(AWS_STATE_PASSPHRASE 등)은 의도적으로 맨 마지막에 설정해 plan이 init에서 실패하게 뒀습니다. 스테이트는 아래같이 손으로 옮겼습니다.[5]

# 아직 테라폼 클라우드 백엔드인 브랜치에서
terraform init
terraform state pull > aws-tfc.tfstate  # 비밀번호가 평문으로 들어 있음!!!
terraform state list | wc -l  # 228

# S3 백엔드와 암호화를 넣은 브랜치에서
rm -rf .terraform
TF_VAR_state_passphrase=… tofu init
tofu state push aws-tfc.tfstate
tofu state list | wc -l   # 228
tofu plan  # No changes.

rm aws-tfc.tfstate

락 파일 재생성

OpenTofu에서는 프로바이더 주소가 registry.opentofu.org로 바뀌고, OpenTofu 레지스트리의 hashicorp/aws는 HashiCorp가 빌드한 것과 다른 파일이라 zh: 해시도 모두 달라집니다.[42] 그래서 테라폼 때 만든 .terraform.lock.hcl은 그대로 쓸 수 없으므로 손으로 고치지 않고 tofu로 새로 만들어야 합니다.[43]

-# This file is maintained automatically by "terraform init".
+# This file is maintained automatically by "tofu init".
 # Manual edits may be lost in future updates.

-provider "registry.terraform.io/hashicorp/aws" {
+provider "registry.opentofu.org/hashicorp/aws" {
   version     = "6.66.0"
   constraints = "~> 6.7"

터미널에서 apply를 바로 실행할 때는 plan과 apply가 한 번에 이어지니 plan 파일을 신경 쓸 일이 거의 없었지만 Actions에서는 여러 이유로 plan을 파일로 만들어 두고 apply가 그 파일을 적용하게 해야 했는데, plan을 만들 때의 tofu init이 락 파일에 빠진 해시나 제약을 채워 넣으면 그 plan 파일은 채워진 락 파일을 기준으로 만들어지고 apply 쪽은 커밋된 락 파일로 다시 init하기 때문에, 둘이 다르면 plan이 거부될 수 있습니다. 그러니 새로 만든 락 파일은 빠진 것 없이 커밋해야 했는데 이전을 마친 뒤에 github에서 이렇게 한 번 실패했고, 빠진 h1: 해시를 커밋하고 plan을 다시 돌려서 해결했습니다.[44]

Error: Inconsistent dependency lock file

The given plan file was created with a different set of external dependency
selections than the current configuration. A saved plan can be applied only
to the same configuration it was created from.

승인은 GitHub environment로

테라폼 클라우드에서는 plan을 보고 확인 버튼을 누르면 apply가 됐습니다. 이 확인 단계는 GitHub environment를 써서 Actions로 옮겼습니다.

GitHub environment는 원래 production, staging 같은 배포 대상을 나타내는 이름입니다. 워크플로의 작업에 environment:를 적으면 그 environment에 걸린 보호 규칙을 통과해야 작업이 러너에 올라갑니다.[45] 보호 규칙으로 required reviewers를 걸어 두면 지정한 사람이 승인해야만 작업이 도는 안전 장치가 되어줍니다. 무료 플랜에서는 공개 저장소에서만 쓸 수 있는데, 페미위키 infra는 공개 저장소라 그대로 쓸 수 있었습니다.[46]

따라서 워크스페이스마다 같은 이름의 environment를 두고 apply 작업이 그 environment에서 승인을 기다리게 해서, 승인 버튼을 누르는 것이 곧 배포가 되게 했습니다. 또 environment를 쓰는 작업은 OIDC 토큰의 sub에 environment:aws가 들어가므로,[47] 앞에서 본 IAM 조건과 맞물려 승인을 거친 작업만 apply 역할을 받는 이중 안전 장치가 되어줍니다. 지금 워크플로의 apply 작업은 이렇게 생겼습니다.

  apply:
    name: ${{ matrix.workspace }} apply
    needs: pending
    environment: ${{ matrix.workspace }}
    steps:
      - uses: femiwiki/terraform-github-tacos@7a2c2a88035e6e07e6a72c08ad44ea82381a6daf  # v0.8.0
        with:
          step: apply
          apply-before-merge: "true"
          workspace: ${{ matrix.workspace }}

참고로 tofu-plan과 tofu-apply는 워크스페이스 하나의 plan과 apply만 맡기 때문에 그 앞뒤의 일, 곧 PR이 바꾼 워크스페이스를 식별하고, environment에 승인자가 걸려 있는지 확인하고, 승인을 기다리던 오래된 실행을 취소하고, apply가 끝나면 PR을 머지하고, 이 모든 작업이 성공해야 통과하는 필수 검사를 두고 하는 일은 워크플로에 직접 적어야 했습니다. 처음에는 infra의 워크플로에 직접 적었다가 나중에 이 부분은 terraform-github-tacos라는 액션으로 따로 떼어 냈습니다.[48] 위의 tacos 단계가 그것이고, dflook의 액션은 그 사이에서 그대로 plan과 apply를 합니다.[49]

맺음말

이제 페미위키의 워크스페이스는 모두 OpenTofu로 돌고, 그사이 gcp와 mariadb, 백업 확인을 맡는 healthchecks가 더해져 숫자만 일곱이 됐습니다. 무엇이 언제 누구의 승인으로 바뀌었는지는 공개 저장소의 PR과 Actions 기록에 그대로 남아 누구나 볼 수 있게 됐고요, 손으로 넣어 두고 다시 볼 수 없던 비밀값은 Parameter Store와 1Password에서 코드로 선언하는 GitHub 시크릿으로 옮겨 갔으며 리소스 한도를 걱정할 일도 없어졌습니다.

정리하자면, 테라폼 클라우드는 저장소만 연결하면 plan과 apply가 바로 보이고 실행 기록과 지난 스테이트도 웹 화면에서 볼 수 있어 많은 편리함을 주었습니다. 그러나 당연하게도 오직 테라폼만 자원하고, SSM 터널 너머의 Docker 데몬처럼 원격 러너가 닿지 못하는 곳은 다룰 수 없었으며, 비밀값을 다시 확인할 수 없었습니다. 반대로 OpenTofu는 일부 기능을 유료 플랫폼에만 내놓는 오픈 코어가 아니어서 상태 암호화나 provider for_each 같은 기능이 잠길까 걱정할 일도 없고, GitHub Actions에서는 터널을 여는 것처럼 필요한 것을 자유롭게 끼워 넣을 수 있으며, (공개 저장소라면) environment 승인까지 무료로 쓸 수 있습니다. 물론 그만큼 승인 흐름을 직접 만들고 관리해야 하고, plan 출력이 공개되니 비밀값에 늘 신경 써야 하며, Actions 로그는 일정 기간이 지나면 사라지기 때문에 apply 출력을 PR 댓글로 따로 남겨 두는 조치가 필요하긴 했습니다.

개인적으로는 지금 상태에 만족하는 편입니다. 다만 승인 흐름을 새로 만들다 보니 어딘가에 보안 취약점이 숨어 있지 않을까, 또 새로 만든 코드가 엄청나게 많은데 대부분 AI 에이전트가 쓴 것이라 이걸 어떻게 관리하나 하는 부담이 있습니다. 그래서 다른 분들이나 팀에서 페미위키가 한 방식을 그대로 따라하셔도 된다고 말씀드리기는 어렵습니다. 각자의 판단과 책임 아래, 믿을 만한 거인의 어깨에 올라탈 기회가 생기시길 바라며, 이 글이 그 판단에 조금이나마 도움이 되었으면 좋겠습니다.

부연 설명

  1. ↑ Digger는 2021년 런던의 창업 육성 프로그램 Entrepreneur First에서 시작했고, 지금은 미국 샌프란시스코에 주소를 두고 있습니다(설립 연도를 2020년으로 적은 자료도 있습니다).[18][19]

출처

  1. ↑ “Announcing OpenTofu”. 《Linux Foundation》 (영어). 2026년 10월 22일에 확인함. 
  2. ↑ “TACOS: Terraform Automation and COllaboration Software”. 《Scalr》 (영어). 2026년 10월 22일에 확인함. 
  3. ↑ “README.md: Add a badge for the Terraform cloud”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  4. ↑ “Manage variables and variable sets in HCP Terraform”. 《HashiCorp Developer》 (영어). 2026년 10월 22일에 확인함. 
  5. ↑ 5.0 5.1 5.2 5.3 “Move the aws root off Terraform Cloud · Issue #608 · femiwiki/femiwiki”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  6. ↑ “Add workspace terraform-cloud”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  7. ↑ “tfe_workspace is unable to set github-app-installation-id · Issue #147 · hashicorp/terraform-provider-tfe”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  8. ↑ “terraform-cloud: Remove vcs_repo configs from terraform codes”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  9. ↑ “Remove 'terraform-cloud' workspace”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  10. ↑ “HCP Terraform subscription plans”. 《HashiCorp Developer》 (영어). 2026년 10월 22일에 확인함. 
  11. ↑ “Instantiating Multiple Providers with a loop · Issue #19932 · hashicorp/terraform”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  12. ↑ “provider block reference for Terraform component configurations”. 《HashiCorp Developer》 (영어). 2026년 10월 22일에 확인함. 
  13. ↑ “Stacks overview”. 《HashiCorp Developer》 (영어). 2026년 10월 22일에 확인함. 
  14. ↑ 14.0 14.1 “State and Plan Encryption”. 《OpenTofu》 (영어). 2026년 10월 22일에 확인함. 
  15. ↑ “OpenTofu 1.9.0 is available now with provider for_each”. 《OpenTofu》 (영어). 2026년 10월 22일에 확인함. 
  16. ↑ “Move Terraform state from Terraform Cloud to S3 · Issue #500 · femiwiki/femiwiki”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  17. ↑ “diggerhq/digger: Digger is an open source IaC orchestration tool. Digger allows you to run IaC in your existing CI pipeline”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  18. ↑ “Digger”. 《Entrepreneurs First》 (영어). 2026년 10월 22일에 확인함. 
  19. ↑ “Digger - Products, Competitors, Financials, Employees, Headquarters Locations”. 《CB Insights》 (영어). 2026년 10월 22일에 확인함. 
  20. ↑ “Setup Digger · Pull Request #412 · femiwiki/infra”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  21. ↑ “Remove Digger · Pull Request #414 · femiwiki/infra”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  22. ↑ 22.0 22.1 “Backendless mode”. 《OpenTaco Docs》 (영어). 2026년 10월 22일에 확인함. 
  23. ↑ “Configuration”. 《OpenTaco Docs》 (영어). 2026년 10월 22일에 확인함. 
  24. ↑ “GitHub App Setup”. 《OpenTaco Docs》 (영어). 2026년 10월 22일에 확인함. 
  25. ↑ “docker: Keep state in S3 instead of Terraform Cloud · Pull Request #508 · femiwiki/infra”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  26. ↑ “Tofu Definition & Meaning”. 《Merriam-Webster》 (영어). 2026년 10월 22일에 확인함. 
  27. ↑ “Terraform fork OpenTF renamed and relocated as OpenTofu”. 《The Register》 (영어). 2026년 10월 22일에 확인함. 
  28. ↑ “OpenTF Joins The Linux Foundation as OpenTofu!”. 《env zero》 (영어). 2026년 10월 22일에 확인함. 
  29. ↑ “Setup github mirrors (b60cec07) · Commits · lens0021 / iac”. 《GitLab》 (영어). 2026년 10월 22일에 확인함. 
  30. ↑ “feat(grafana): alert on disk and memory from the metrics Alloy already ships · Pull Request #525 · femiwiki/infra”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  31. ↑ “terraform-github-actions/tofu-apply at main · dflook/terraform-github-actions”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  32. ↑ “fix(grafana): retry the read after a create, and apply from the PR · Pull Request #528 · femiwiki/infra”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  33. ↑ “Run plan and apply through dflook/terraform-github-actions · Issue #506 · femiwiki/femiwiki”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  34. ↑ “docker: read the secrets from SSM at start instead of passing them as env · Pull Request #536 · femiwiki/infra”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  35. ↑ “ci: plan and apply the docker workspace from Actions · Pull Request #541 · femiwiki/infra”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  36. ↑ “Reach the Docker daemon over SSM and bind it to loopback · Issue #545 · femiwiki/femiwiki”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  37. ↑ “Proposal: State Encryption · Issue #9556 · hashicorp/terraform”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  38. ↑ “Manage sensitive data in your configuration”. 《HashiCorp Developer》 (영어). 2026년 10월 22일에 확인함. 
  39. ↑ “OpenTofu 1.10.0: A Well-Seasoned Release”. 《OpenTofu》 (영어). 2026년 10월 22일에 확인함. 
  40. ↑ “Backend Type: s3”. 《OpenTofu》 (영어). 2026년 10월 22일에 확인함. 
  41. ↑ “Backend Type: s3”. 《HashiCorp Developer》 (영어). 2026년 10월 22일에 확인함. 
  42. ↑ “feat(aws): apply the aws root from Actions, with its state encrypted · Pull Request #960 · femiwiki/infra”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  43. ↑ “Switch from Terraform to OpenTofu · Issue #504 · femiwiki/femiwiki”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  44. ↑ “github: hand the Grafana metrics reader to femiwiki.github.io · Pull Request #1423 · femiwiki/infra”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  45. ↑ “Deployment environments”. 《GitHub Docs》 (영어). 2026년 10월 22일에 확인함. 
  46. ↑ “Deployments and environments”. 《GitHub Docs》 (영어). 2026년 10월 22일에 확인함. 
  47. ↑ “OpenID Connect reference”. 《GitHub Docs》 (영어). 2026년 10월 22일에 확인함. 
  48. ↑ “Add the action, the module and their CI · Pull Request #1 · femiwiki/terraform-github-tacos”. 《GitHub》 (영어). 2026년 10월 22일에 확인함. 
  49. ↑ “Runs”. 《terraform-github-tacos》 (영어). 2026년 10월 22일에 확인함.