# Terraform — полный текст документации > Полный текст раздела «Terraform» документации Timeweb Cloud в markdown. Каждая статья начинается с заголовка первого уровня и ссылки на свою каноническую страницу. Индекс: https://timeweb.cloud/docs/terraform/llms.txt Статей: 5 Последнее обновление: 2026-07-03 # Terraform Source: https://timeweb.cloud/docs/terraform?utm_source=llms_txt&utm_medium=ai Вы можете управлять своей облачной инфраструктурой, развернутой в Timeweb Cloud, с помощью утилиты Terraform. Terraform позволяет автоматизированно управлять ресурсами в Timeweb Cloud с помощью удобных файлов конфигурации формата HCL (HashiCorp Configuration Language) и детальных планов вносимых изменений. Дополнительную информацию о ресурсах провайдера можно получить в документации на [сайте Terraform](https://developer.hashicorp.com/terraform/docs). > [!NOTE] > Подробная документация по работе с Terraform доступна в [нашем профиле GitHub](https://github.com/timeweb-cloud/terraform-provider-timeweb-cloud). **Управление сервисами через Terraform** - [Создание кластера баз данных](https://timeweb.cloud/docs/dbaas/dbaas-create) - [Управление Firewall](https://timeweb.cloud/docs/firewall/upravlenie-fajrvolom#sozdanie-fajrvola) # Начало работы с Terraform Source: https://timeweb.cloud/docs/terraform/nachalo-raboty-s-terraform?utm_source=llms_txt&utm_medium=ai Terraform — очень удобный инструмент для быстрого создания облачной инфраструктуры и управления ей при помощи конфигурационных файлов. Когда конфигурационные файлы изменяются, Terraform автоматически реагирует на это и отдает соответствующие команды на добавление или удаление нужных администратору ресурсов. В статье мы расскажем, как при помощи Terraform (также будем использовать сокращение TF) создать виртуальную инфраструктуру в Timeweb Cloud. > [!NOTE] > Подробная документация по работе с Terraform доступна в [нашем профиле GitHub](https://github.com/timeweb-cloud/terraform-provider-timeweb-cloud). ## **Шаг 1. Устанавливаем Terraform** Terraform можно установить на Linux, macOS и Windows. Установка возможна двумя способами: - через пакетный менеджер; - вручную — загрузкой и распаковкой готового бинарного файла. Рассмотрим второй способ — установку вручную, с использованием предварительно собранного бинарного файла. HashiCorp, разработчик Terraform, ограничил доступ к своим репозиториям с IP-адресов из России. Для вашего удобства мы развернули зеркало: [http://terraform-mirror.timeweb.cloud/index.html](http://terraform-mirror.timeweb.cloud/index.html). Далее для установки клиента Terraform мы будем использовать именно это зеркало. Актуальную версию Terraform можно посмотреть на странице [http://terraform-mirror.timeweb.cloud/current/index.html](http://terraform-mirror.timeweb.cloud/current/index.html). Для примера рассмотрим установку версии `1.14.0`. Linux Скачайте архив с бинарным файлом: ```bash wget http://terraform-mirror.timeweb.cloud/1.14.0/terraform_1.14.0_linux_amd64.zip ``` Распакуйте архив: ```bash unzip ./terraform_1.14.0_linux_amd64.zip ``` Переместите файл в директорию `/usr/local/bin`: ```bash sudo mv ./terraform /usr/local/bin ``` Убедитесь, что Terraform установлен: ```bash terraform -v ``` macOS Скачайте архив с бинарным файлом: ```bash wget http://terraform-mirror.timeweb.cloud/1.14.0/terraform_1.14.0_darwin_arm64.zip ``` Распакуйте архив: ```bash unzip ./terraform_1.14.0_darwin_arm64.zip ``` Переместите файл в директорию `/usr/local/bin`: ```bash sudo mv ./terraform /usr/local/bin ``` Убедитесь, что Terraform установлен: ```bash terraform -v ``` Windows Перейдите на страницу релиза: [http://terraform-mirror.timeweb.cloud/current/index.html](http://terraform-mirror.timeweb.cloud/current/index.html). Скачайте версию `terraform_1.14.0_windows_amd64.zip`. Распакуйте архив. Внутри будет файл `terraform.exe`. Чтобы запускать Terraform из командной строки, добавьте путь к папке с `terraform.exe` в переменную окружения `PATH`. Для этого: 1. В строке поиска Windows введите «Переменные среды» и откройте соответствующий пункт. 2. В разделе «Системные переменные» найдите переменную `Path` и нажмите «Изменить». 3. Нажмите «Создать» и укажите путь к директории, куда вы распаковали Terraform. 4. Нажмите «ОК» во всех окнах, чтоб применить настройки. Теперь проверьте установку в командной строке: ```bash terraform -v ``` ## **Шаг 2. Создаем конфигурационный файл .tf** Файлы конфигураций в Terraform имеют расширение `.tf`. При этом их название может быть произвольным — программа всё равно сможет извлечь из них нужную информацию. Теперь давайте создадим новый каталог (назовем его `timeweb_project`), а затем добавим туда файл конфигураций, к примеру, `twcproject.tf`. Чтобы получить файл с таким расширением, можно сначала создать обычный текстовый файл, а затем изменить его расширение на `.tf`. Отметим, что в одном каталоге может быть несколько конфигурационных файлов, связанных с одним проектом. Например, можно создать файл `vars.tf` для описания переменных, `nginx.tf` для настройки веб-сервера Nginx и так далее. В дальнейшем при выполнении команды `terraform plan` все `.tf`\-файлы будут «склеены» в один.  Однако в рамках данной статьи мы будем использовать один общий конфигурационный файл `twcproject.tf`. ## **Шаг 3. Настраиваем провайдера** Настройка провайдера через конфигурационный файл выполняется следующим образом. В начало нашего файла `twcproject.tf` добавляем следующие строки: ```shell terraform {   required_providers {     twc = {       source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"     }   }   required_version = ">= 1.4.4" } ``` В `source` указывается адрес провайдера (в примере указан адрес Timeweb Cloud), а номер версии Terraform вы можете узнать при скачивании (мы указали самую свежую на момент написания инструкции). Также учитывайте, что провайдер поддерживает только версии Terraform 0.13 и выше. Теперь введите в папке с конфигурационным файлом следующую команду, которая установит провайдера: ```shell terraform init ``` Можно приступать к следующему шагу. Если же у вас возникла проблема с установкой провайдера, вы всегда можете обратиться к специалистам нашей службы поддержки прямо в чате. ## **Шаг 4. Создаем и указываем токен** Чтобы появилась возможность работать с установленным провайдером, нам понадобится API-токен, который можно получить в [разделе «API и Terraform»](https://timeweb.cloud/my/api-keys) панели Timeweb Cloud (вы должны быть залогинены, чтобы попасть в этот раздел). Допустим мы получили токен `fb246030216d5g30b1g6228e3071037g` (это значение здесь только в качестве примера, вам необходимо будет вводить свой токен, который будет сгенерирован для вас). Добавляем его в файл `twcproject.tf` следующим образом: ```shell provider "twc" {   token = "fb246030216d5g30b1g6228e3071037g" } ``` Если нужна возможность удаления сервисов, необходимо [отключить Telegram-подтверждения](https://timeweb.cloud/docs/account-management/notifications#otkluchenie-uvedomlenij-pri-udalenii-servisov-cherez-api) их удаления, отметив соответсвующий чекбокс в настройках токена: ![8a2b7af7 A5c2 4b7f B41b 657b869f4e74](https://content.timeweb.com/assets/1bca3811-2b63-4fc5-b65d-fa80221b55e4?width=1458&height=884) ## **Шаг 5. Готовим конфигурацию** С помощью Terraform вы сможете управлять разнообразными типами ресурсов в своем облаке Timeweb Cloud. Рассмотрим пример создания виртуальной машины (далее ВМ) с диском SSD емкостью 100 ГБ, 2 ядрами и 4 ГБ оперативной памяти. В качестве операционной системы будем использовать Ubuntu 20.04, а наш сервер назовем, допустим, `my-timeweb-server` (вы можете заменить на свое имя). Сервер мы будем создавать в локации `ru-1`. Весь список локаций и соответствующих им зон доступности можно найти [здесь](https://timeweb.cloud/docs/zony-dostupnosti/servisy-i-zony-dostupnosti). Для этого в конфигурационном файле `twcproject.tf` прописываем следующее: ```shell terraform {   required_providers {     twc = {       source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"     }   }   required_version = ">= 1.4.4" } provider "twc" {   token = "fb246030216d5g30b1g6228e3071037g" } data "twc_configurator" "configurator" {   location = "ru-1"  preset_type = "premium" } data "twc_os" "os" {   name = "ubuntu" version = "20.04" } resource "twc_server" "my-timeweb-server" {   name = "My Timeweb Server"   os_id = data.twc_os.os.id   configuration {     configurator_id = data.twc_configurator.configurator.id     disk = 102400     cpu = 2     ram = 1024 * 4   } } ``` Также для дальнейшей работы вам понадобится пароль, он будет выслан вам на электронную почту сразу после создания ресурса. Важно: если ВМ не создалась, проверьте, корректно ли указан токен (см. Шаг 4). Также стоит обратить внимание на ошибку, которую вывел Terraform: зачастую из нее понятна причина, по которой ВМ не создалась. Кроме того, можно настроить доступ через SSH-ключи. Если вы не знаете, как генерировать SSH-ключи, воспользуйтесь [этой инструкцией](https://timeweb.cloud/docs/cloud-servers/manage-servers/ssh-keys). Для загрузки SSH-ключа добавьте следующий блок в конфигурационный файл `twcproject.tf`: ```shell resource "twc_ssh_key" "your-key" {   name = "Your key"   body = file("~/.ssh/your-key.pub") } ``` А в этом блоке `resource` пропишите строку `ssh_keys_ids`: ```shell resource "twc_server" "my-timeweb-server" {  name = "My Timeweb Server"   os_id = data.twc_os.os.id  ssh_keys_ids = [twc_ssh_key.your-key.id] } ``` Обратите внимание, что указывать нужно **только публичный** ключ SSH. В итоге у нас получится следующий файл конфигурации: ```shell terraform {   required_providers {     twc = {       source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"     }   }   required_version = ">= 1.4.4" } provider "twc" {   token = "fb246030216d5g30b1g6228e3071037g" } data "twc_configurator" "configurator" {   location = "ru-1"  preset_type = "premium" } data "twc_os" "os" {   name = "ubuntu"   version = "20.04" } resource "twc_ssh_key" "your-key" {   name = "Your key"   body = file("~/.ssh/your-key.pub") } resource "twc_server" "my-timeweb-server" {   name = "My Timeweb Server"   os_id = data.twc_os.os.id   ssh_keys_ids = [twc_ssh_key.your-key.id]   configuration {     configurator_id = data.twc_configurator.configurator.id     disk = 102400     cpu = 2     ram = 1024 * 4   } } ``` На этом подготовка завершена, осталось выполнить пару простейших шагов. ## **Шаг 6. Проверяем конфигурацию** Это делает команда: ```shell terraform validate ``` При правильных настройках вы получите сообщение о том, что конфигурация корректна (_valid_). Если возникла ошибка, проверьте настройки еще раз. Теперь осталось применить конфигурацию. ## **Шаг 7. Применяем конфигурацию** Сначала вводим следующую инструкцию: ```shell terraform plan ``` Она не применяет изменения, а только выводит список ресурсов для проверки настроек. При обнаружении ошибок Terraform не просто выдаст дежурное сообщение, но и укажет, где эти ошибки допущены. Если же всё в порядке, вводим: ```shell terraform apply ``` Эта инструкция применяет созданные конфигурации, так что ваши ресурсы готовы, и с ними уже можно будет работать. Но для применения изменений их сначала нужно будет подтвердить, поэтому в строке: ```shell Enter a value: ``` вводим _yes_ и нажимаем _Enter_. Теперь можно проверить созданные ресурсы через [панель управления](https://timeweb.cloud/my). Если же по каким-то причинам вы решите удалить их, это можно сделать при помощи инструкции: ```shell terraform destroy ``` Операцию также нужно будет подтвердить, введя _yes_ и нажав на клавишу _Enter_, чтобы подтвердить удаление. ## **Заключение** Итак, мы научились создавать конфигурационные файлы Terraform, настраивать провайдера, а также добавлять ресурсы и настраивать их конфигурацию, чтобы можно было работать с ними на своем сервере Timeweb Cloud. Если же вы хотите узнать об инструкциях Terraform больше, ознакомиться с ними можно в [официальной документации](https://developer.hashicorp.com/terraform/cli). # Как добавить правило балансировщика через Terraform Source: https://timeweb.cloud/docs/terraform/dobavit-pravilo-balansirovshchika-cherez-terraform?utm_source=llms_txt&utm_medium=ai Terraform — это инструмент для управления инфраструктурой с помощью кода, созданный компанией HashiCorp. С его помощью можно автоматизировать создание и изменение ресурсов инфраструктуры с использованием декларативного языка конфигурации HCL. Возможности Terraform: - Управление инфраструктурой с помощью единого инструмента - Контроль версий и повторное использование конфигураций - Возможность отслеживать текущее состояние инфраструктуры В инструкции рассмотрим, как управлять правилами балансировщика нагрузки с помощью Terraform. ## Зачем нужен балансировщик? Сетевой балансировщик дает возможность равномерно распределить входящий трафик по нескольким серверам для улучшения доступности и надежности вашего сервиса. Он является незаменимым инструментом при реализации горизонтального масштабирования сервисов. Горизонтальное масштабирование — это процесс добавления дополнительных узлов или машин к существующей инфраструктуре для увеличения её возможностей и обработки большего количества трафика. Основные преимущества, которые предоставляет балансировщик: - Балансировка нагрузки для TCP-сессий, обеспечивающая оптимальное использование ресурсов серверов. - Поддержка различных протоколов HTTP, HTTP2, HTTPS, TCP. - Отказоустойчивость сервера приложений, позволяющая избежать проблем с доступностью и работоспособностью сервиса. - Возможность настраивать правила маршрутизации трафика, чтобы направлять запросы к определенным портам на серверах. - Возможность настройки SSL и переадресации на протокол HTTPS. ## Создаем сетевой балансировщик Для начала определимся с требованиями к балансировщику нагрузки: 1. У нас будет два сервера, у которых на 80-м порту будет развернут сайт. 2. Обращаясь по 80 порту к адресу балансировщика, мы должны будем попадать на наш сайт, на один из серверов. 3. Алгоритм — Round robin. 4. Дополнительных параметров нет. Чтобы добавить правило к нашему балансировщику, нам нужно создать его и настроить балансировку серверов. Мы добавили два сервера для того, чтобы настроить для них балансировку нагрузки. ![Image5](https://content.timeweb.com/assets/6bb8b154-adf1-432c-910c-705a29ad0b86?width=325&height=213) Теперь добавим проект на terraform. Подробнее об установке и настройке провайдера можно прочитать [тут](https://timeweb.cloud/docs/terraform/nachalo-raboty-s-terraform).  Сначала необходимо создать папку, где будут находиться конфигурации: ```shell mkdir timeweb-lb cd timeweb-lb ``` Общая структура файлов получилась следующей: ```shell ├── timeweb-lb │   ├── main.tf │   ├── variables.tf ``` В файле `variables.tf` укажем переменные для токена провайдера и IP-адресов для балансировки: ```shell variable "tw_token" {   type = string   sensitive = true } variable "lb-ips" {     type = set(string) } ``` В файле `main.tf` добавим информацию о провайдере: ```shell terraform {   required_providers {     twc = {         source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"     }   }   required_version = ">= 1.5.3" } provider "twc" {   token = var.tw_token } ``` Когда мы описываем конфигурацию Terraform, мы используем два основных типа сущностей — это источники данных (`data`) и ресурсы (`resources`). - Источники данных предназначены для того, чтобы определять различные переменные и настройки, которые доступны в рамках выбранного провайдера. К таким источникам данных могут относиться, например, пресеты, проекты и другие параметры. - Ресурсы — это те элементы инфраструктуры, которые мы хотим создать с помощью Terraform — например, серверы, базы данных, балансировщики нагрузки и другие компоненты. В файле `main.tf` укажем пресет для настройки: ```shell data "twc_lb_preset" "lb-preset" {   requests_per_second = "10K"   price_filter {     from = 100     to = 200   } } ``` Если в [панели управления](https://timeweb.cloud/my/projects/) вы используете проекты, то можно указать конкретный проект, в котором будут созданы ресурсы. Например, добавим проект с названием «Articles»: ```shell data "twc_projects" "articles" {   name = "Articles" } ``` Ресурс, который мы будем создавать, называется `twc_lb`. При его создании мы можем указать множество опциональных параметров, например настройки healthcheck, выбор алгоритма балансировки. Возьмем самую простую настройку: ```shell resource "twc_lb" "load-balancer" {     name = "load-balancer"     algo = "roundrobin"     project_id = data.twc_projects.articles.id     preset_id = data.twc_lb_preset.lb-preset.id ``` Вот какие параметры мы можем еще указать: - `ips` — список IP-адресов для балансировки - `is_keepalive` — флаг, который указывает на поддержание TCP-соединения с сервером - `is_ssl` — автоматический редирект на протокол HTTPS - `is_sticky` — сохранять пользовательскую сессию для одного бэкэнд-сервера Также в проект мы добавили файл `.tfvars`, где указали значения переменных из `variables.tf`: ```shell tw_token = "<тут api key для провайдера>" lb-ips = [ "<тут ip-адрес для первого сервера>", "<тут — для второго>" ] ``` Далее выполним команду: ```shell terraform validate ``` Если всё хорошо, вы должны увидеть сообщение, как на скриншоте.  ![Image1](https://content.timeweb.com/assets/f2d5fb45-1a13-4e7f-84f3-7e84aeacc43c?width=616&height=73) Теперь можно выполнить следующую команду, чтобы посмотреть, какие ресурсы будут созданы: ```shell terraform plan -var-file=.tfvars ``` Флаг `-var-file=.tfvars` позволяет нам указать на файл с переменными, которые необходимо будет подставить при применении этого кода. ![Image8](https://content.timeweb.com/assets/43ccbb4f-623f-48f4-b596-799da0fd9447?width=678&height=537) Помимо определения переменных в файле, указать их можно следующими способами: 1. С помощью параметра `-var`, например `-var="tw_token=243453452345235456643"` 2. C помощью переменных окружения — `export TF_VAR_tw_token=243453452345235456643` ## Добавляем правила к балансировщику Правилом в балансировщике будем называть настройку перенаправления портов. В правиле, независимо от способа создания, необходимо указать: 1. Порт, на который мы будем обращаться по адресу балансировщика. 2. Порт, на который мы будем перенаправляться на конкретных серверах. Добавим новый ресурс в нашу конфигурацию, в файл `main.tf`: ```shell resource "twc_lb_rule" "lb-rule" {   lb_id = resource.twc_lb.load-balancer.id   balancer_proto = "http"   balancer_port = 80   server_proto = "http"   server_port = 80 } ``` Снова выполним команды: ```shell terraform validate ``` ```shell terraform plan -var-file=.tfvars ``` ```shell terraform apply -var-file=.tfvars ``` Подтвердим применение команды, введя `yes`. ![Image2](https://content.timeweb.com/assets/dc074089-d13c-4097-883a-394de0855215?width=543&height=281) В панели управления видим созданные ресурсы: - Балансировщик ![830daf03 83ea 443c 939b 0187dd70a249](https://content.timeweb.com/assets/0dde03ae-3805-42c0-9182-9e71ff8bd6eb?width=958&height=242) - Правило ![Image10](https://content.timeweb.com/assets/3a20d7ff-c654-4451-bc4d-4e065686fbee?width=626&height=460) Перейдем по адресу нашего балансировщика (два раза, чтобы попасть на разные серверы): - Первый сервер, указанный в переменных: ![Image3](https://content.timeweb.com/assets/622d9eee-c700-4a65-83f4-242d9c51a991?width=472&height=226) - Второй сервер, указанный в переменных: ![Image6](https://content.timeweb.com/assets/1271de9b-f5b9-40f8-81df-34877b5d2ec4?width=475&height=260) Что делать, если нам потребовалось добавить второе правило? Например, на серверах мы развернули новое приложение на порту 81. Просто добавим еще один блок `resource` для правила: ```shell resource "twc_lb_rule" "lb-second-rule" {   # таким образом мы укажем идентификатор балансировщика, созданного ранее   lb_id = resource.twc_lb.load-balancer.id   balancer_proto = "http"   balancer_port = 81   server_proto = "http"   server_port = 81 } ``` Снова выполним команду ниже, чтобы посмотреть на изменения: ```shell terraform plan -var-file=.tfvars ``` ![Image4](https://content.timeweb.com/assets/ed6b1c07-70f1-40fa-9ef4-bdf30db7c027?width=993&height=469) Мы видим информацию о том, что один балансировщик и одно правило уже созданы, а новое правило будет добавлено.  Выполним команду: ```shell terraform apply -var-file=.tfvars ``` При запросе согласимся на применение конфигурации: ![Image9](https://content.timeweb.com/assets/86398b87-cace-496b-95d0-a70e12baa2f7?width=506&height=211) Теперь заглянем в панель управления — у нас настроены два правила: ![Image11](https://content.timeweb.com/assets/269094ad-2a56-426d-bb60-e12883b2ec20?width=602&height=662) Обратимся по адресу балансировщика, чтобы проверить, что всё работает корректно: ![Image12](https://content.timeweb.com/assets/2a4bbf30-813b-4144-99b7-b14089217e48?width=438&height=214) ## Заключение В этой статье мы научились создавать сетевые балансировщики и правила с помощью Terraform. Помимо использования этого инструмента, балансировщиками можно управлять с помощью [CLI](https://github.com/timeweb-cloud/twc/blob/master/docs/ru/CLI_REFERENCE.md) и [API](https://timeweb.cloud/api-docs#tag/Balansirovshiki). Все примеры из статьи доступны на [Гитхабе](https://github.com/DmitryBahtenkov/timeweb-load-balancer). Полезные ссылки: - [Документация терраформ-провайдера Timeweb Cloud](https://github.com/timeweb-cloud/terraform-provider-timeweb-cloud) - [Документация Terraform CLI](https://developer.hashicorp.com/terraform/cli/run) - [Синтаксис Terraform](https://developer.hashicorp.com/terraform/language/syntax/configuration) # Загрузка состояний Terraform в Object Storage Source: https://timeweb.cloud/docs/terraform/zagruzka-sostoyanij-v-object-storage?utm_source=llms_txt&utm_medium=ai Terraform — это средство для создания и управления инфраструктурой в коде, которое дает возможность развертывать, модифицировать и удалять разнообразные ресурсы в облачных сервисах, такие как виртуальные сервера, сетевые элементы, хранилища данных и т.д. Он применяет язык настроек HCL (HashiCorp Configuration Language), который имеет декларативный и понятный человеку синтаксис. HCL позволяет задавать требуемое состояние инфраструктуры с помощью секций, параметров и формул. Преимущества использования:  - Вы можете запустить одинаковый код Terraform на различных платформах и получать одинаковые результаты.  - Вы можете разделять свою инфраструктуру на отдельные модули и использовать их в разных задачах.  - Вы можете работать с разными облачными провайдерами и услугами с помощью единого интерфейса.  - Вы можете сохранять свой код настроек в системе управления версиями и отслеживать изменения по времени.  - Вы можете работать над своей инфраструктурой в команде и согласовывать свои действия с помощью удаленного хранилища состояний. ## Remote State По умолчанию Terraform сохраняет своё состояние в локальном файле `.tfstate`. Однако при работе в команде использование локального файла усложняет работу с этим инструментом — каждый пользователь должен убедиться, что у него наиболее свежая версия файла с состоянием и что никто другой в данный момент времени не запускает создание ресурсов с аналогичным провайдером. Механизм Remote State позволяет хранить файлы состояния в удалённом хранилище, что позволяет пользователям работать с самой свежей версией состояния и не думать о синхронизации. Terraform поддерживает следующие хранилища: - Terraform Cloud - HashiCorp Consul - Amason S3 (или другое S3-совместимое хранилище) - Google Cloud Storage - Azure Blob Storage - многие другие Хранение состояния настраивается в конфигурации в блоке `backend`, например: ```shell backend "s3" {      endpoint   = ""      bucket     = ""     …   } ``` Подробнее о конфигурации бэкэнда можно прочитать на сайте Terraform: [Backend Configuration](https://developer.hashicorp.com/terraform/language/settings/backends/configuration). > [!NOTE] > На данный момент Timeweb Cloud не поддерживает загрузку состояний в S3 для версий Terraform 1.6.0 и выше из-за [изменений в структуре конфигурации](https://github.com/hashicorp/terraform/releases/tag/v1.6.0). ## Подготовка Предварительные шаги для создания инфраструктуры. ### Необходимые платные ресурсы В этой статье будут созданы: - Две виртуальные машины ([тарифы](https://timeweb.cloud/services/vds-vps)) - Один бакет Object Storage ([тарифы](https://timeweb.cloud/services/s3-storage)) - Одна локальная сеть ### Создаём бакет Чтобы использовать S3 в качестве хранилища состояния, нам необходимо создать бакет. Для этого перейдём в панель управления, в раздел «Хранилище S3». ![Image6](https://content.timeweb.com/assets/ee140d2b-b93a-431e-9151-5824dab1db79?width=1264&height=376) Нажмём на кнопку «Заказать». Для примера возьмём минимальную конфигурацию: ![Screenshot 04 17 25 16:47:13](https://content.timeweb.com/assets/f3b37b0b-4fb4-4e58-b171-abc23994d714.png?width=1019&height=955) На вкладке «Дашборд» бакета, который мы только что создали, отображаются настройки, которые позже укажем в файле `.tf`: ![Selection 255](https://content.timeweb.com/assets/3258ff3a-733e-4d6d-97ee-d5900f99bf2d.png?width=1008&height=941) ### Пишем конфигурацию Теперь приступим к написанию конфигурации.  1. Добавляем папку `terraform_s3`, в которой будет наш проект. 2. Создаём там файл `main.tf`. 3. По [инструкции](https://timeweb.cloud/docs/terraform/nachalo-raboty-s-terraform) заполняем информацию о провайдере. Должна получиться следующая структура файлов: ```shell ├── terraform_s3 │   ├── main.tf ``` И следующее содержимое файла `main.tf`: ```shell terraform {   required_providers {     twc = {       source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"     }   }   required_version = ">= 1.5.3" } provider "twc" {   token = "" } ``` Теперь добавим настройки бэкенда в блок `terraform`. ```shell backend "s3" {      endpoint = "https://s3.twcstorage.ru"      region = "ru-1"      bucket = ""      key = "states/terraform.tfstate"      access_key = ""      secret_key = ""      skip_region_validation = true      skip_credentials_validation = true      skip_metadata_api_check = true      skip_requesting_account_id = true      skip_s3_checksum = true    } ``` Параметры: 1. `endpoint` — адрес S3-хранилища из панели управления. 2. `region` — регион из панели управления. 3. `bucket` — название бакета, где буду храниться наши конфигурации. 4. `key` — путь к файлу в бакете вместе с названием файла. Например, `states/<название файла>.tfstate`. 5. `access_key` и `secret_key` — ключи для доступа к бакету. Их можно получить в панели управления, на странице созданного ранее бакета 6. `skip_region_validation` и `skip_credentials_validation` — флаги, с помощью которых мы пропускаем валидацию региона и ключей доступа на стороне AWS. Они нужны, так как мы используем не оригинальный AWS S3, а другое облако. Вот пример, как должен выглядеть полный код файла `main.tf`: ```shell terraform {   required_providers {     twc = {       source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"     }   }   required_version = ">= 1.5.3"   backend "s3" {   endpoint = "s3.twcstorage.ru"     region = "ru-1"     bucket = ""     key  = "states/terraform.tfstate"     access_key = ""     secret_key = ""     skip_region_validation = true     skip_credentials_validation = true     } } provider "twc" {   token = "" } ``` После всех настроек выполним команду `terraform init`: ![Image1](https://content.timeweb.com/assets/d025f014-2cf3-4ff9-93ad-7d9a12c2363a?width=767&height=395) ### Защита данных В конфигурации бэкэнда параметры `access_key` и `secret_key` содержат чувствительные данные, которые не должны быть доступны посторонним лицам. Их не рекомендуется хранить в явном виде в файле конфигурации. 1. Можно установить переменные окружения `AWS_ACCESS_KEY_ID` и `AWS_SECRET_ACCESS_KEY` с соответствующими значениями ключей доступа к бакету. Тогда Terraform будет автоматически читать эти переменные при работе с бэкэндом. 2. Использование параметров командной строки. Можно использовать параметр `-backend-config` при выполнении команды `init`: ```shell terraform init -backend-config="access_key=1234" -backend-config="secret_key=1234" ``` ## Создаём инфраструктуру В файле `main.tf` опишем создание виртуальной машины и локальной сети: 1. Укажем ОС. ```shell data "twc_os" "example-os" {   name = "ubuntu"  version = "22.04" } ``` 2. Укажем пресет. ```shell data "twc_presets" "example-preset" {   price_filter {     from = 300     to = 400   } } ``` 3. Добавим VPC. ```shell resource "twc_vpc" "example-vpc" {   name = "Example VPC"   description = "Some example VPC"   subnet_v4 = "192.168.0.0/24"   location = "ru-1" } ``` 4. Опишем конфигурацию сервера. ```shell resource "twc_server" "example-server-with-local-network" {   name = "Example server with local network"   os_id = data.twc_os.example-os.id   preset_id = data.twc_presets.example-preset.id   local_network {     id = twc_vpc.example-vpc.id   } } ``` 5. Добавим идентификатор приватной сети в выходные параметры, чтобы мы могли использовать его в других конфигурациях ```shell output "tw-vpc" {     value = twc_vpc.example-vpc.id } ``` Содержимое конфигурации `main.tf` будет выглядеть так: ```shell terraform {   required_providers {     twc = {       source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"     }   }   required_version = ">= 1.5.3"   backend "s3" {   endpoint = "s3.twcstorage.ru"     region = "ru-1"     bucket = ""     key  = "states/terraform.tfstate"     access_key = ""     secret_key = ""     skip_region_validation = true     skip_credentials_validation = true     } } provider "twc" {   token = "" } data "twc_os" "example-os" {   name = "ubuntu"   version = "22.04" } data "twc_presets" "example-preset" {   price_filter {     from = 300     to = 400   } } resource "twc_vpc" "example-vpc" {   name = "Example VPC"   description = "Some example VPC"   subnet_v4 = "192.168.0.0/24"   location = "ru-1" } resource "twc_server" "example-server-with-local-network" {   name = "Example server with local network"   os_id = data.twc_os.example-os.id   preset_id = data.twc_presets.example-preset.id   local_network {     id = twc_vpc.example-vpc.id   } } output "tw-vpc" {     value = twc_vpc.example-vpc.id } ``` Выполним команду `terraform validate`: ![D067189e 35ec 4bc3 8060 765d5f9ffb79](https://content.timeweb.com/assets/ec95b966-f322-4472-9cf0-6a5ba9d22337?width=565&height=49) Затем `terraform plan`: ![A8ecc713 91cf 44ab 9110 E1fd97806e32](https://content.timeweb.com/assets/4b070049-6849-490b-922f-6cc9e6b6bff8?width=436&height=58) И `terraform apply`: ![41ef13cf F6e3 42c9 B98b 0ceacdb3b9dd](https://content.timeweb.com/assets/a846d8b4-d34f-4af0-ab69-cf7166d5b15b?width=576&height=169) После применения конфигурации в бакете автоматически будет создан файл состояния. ## Проверка и использование состояния В панели управления можно проверить наличие файла состояния в бакете: ![Image7](https://content.timeweb.com/assets/b503b873-4ae5-4ca4-a468-65fd64cd4b3d?width=877&height=130) Теперь попробуем использовать сохранённое состояние в другой конфигурации.  Добавим новую папку `remote-state`: ```shell mkdir remote-state cd remote-state ``` Добавим файл `remote-state.tf` и заполним его следующим образом: ```shell terraform {   required_providers {     twc = {       source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"     }   }   required_version = ">= 1.5.3" } provider "twc" {   token = "" } data "terraform_remote_state" "vpc" {   backend = "s3"     config = {   endpoint = "s3.twcstorage.ru"     region = "ru-1"     bucket = ""     key  = "states/terraform.tfstate"     skip_region_validation = true     skip_credentials_validation = true     access_key = ""     secret_key = ""     } } data "twc_os" "example-os" {   name = "ubuntu"   version = "22.04" } data "twc_presets" "example-preset" {   price_filter {     from = 300     to = 400   } } resource "twc_server" "example-server-with-local-network" {   name = "Example server with local network"   os_id = data.twc_os.example-os.id   preset_id = data.twc_presets.example-preset.id   local_network {     id = data.terraform_remote_state.vpc.outputs.tw-vpc   } } ``` В этом примере мы используем outputs из предыдущего файла `main.tf` для получения идентификатора локальной сети, и добавляем в эту сеть новый VPS. Выполним команды: - `terraform init` - `terraform validate` - `terraform plan`  - `terraform apply` Будет создан второй сервер в нужной локальной сети: ![Image4](https://content.timeweb.com/assets/a3146efa-f83b-4cf9-abe0-ec783b383cc8?width=307&height=187) Чтобы удалить созданные ресурсы, выполните команду `terraform destroy` сначала во второй конфигурации, а затем в первой. ## Полезные ссылки - [Документация терраформ-провайдера Timeweb](https://github.com/timeweb-cloud/terraform-provider-timeweb-cloud) - [Документация Terraform CLI](https://developer.hashicorp.com/terraform/cli/run) - [Remote State](https://developer.hashicorp.com/terraform/language/state) # Шифрование секретов в Hashicorp Terraform Source: https://timeweb.cloud/docs/terraform/shifrovanie-sekretov-v-hashicorp-terraform?utm_source=llms_txt&utm_medium=ai Шифрование приватных данных в HashiCorp Terraform является важным аспектом работы в этом инструменте. И существует методы, которые позволяют безопасно хранить конфиденциальные данные в зашифрованном виде и передавать их в безопасном режиме при необходимости. В этой статье рассмотрим, как безопасно хранить секреты в Terraform, и методы их шифрования, которые помогут улучшить безопасность при работе с инфраструктурой в облаке. ## Почему нельзя хранить чувствительную информацию в виде текста Пользователи Terraform иногда сталкиваются с необходимостью обработать чувствительную информацию. Например, API-ключи или логин и пароль пользователя для БД. Вот пример кода для создания базы данных в Timeweb Cloud (более подробный гайд о работе с Terraform и Timeweb Cloud размещен [на GitHub](https://github.com/timeweb-cloud/terraform-provider-timeweb-cloud)): ```shell resource "twc_db_mysql_8" 'my_db' { name = "mysql_8_database'      # Имя пользователя и пароль      login =      password =      preset_id = data.twc_db_preset.example-db-preset.id } ``` Чтобы код работал, в переменных `username` и `password` необходимо указать имя пользователя и пароль. Также наша задача — надежно обработать эти учетные данные и предотвратить их случайное раскрытие.  Самый простой вариант — сразу присвоить переменным текстовые значения: ```shell resource "twc_db_mysql_8" 'my_db' {      name = "mysql_8_database'      # Имя пользователя и пароль      login = "root"      password = "admin"      preset_id = data.twc_db_preset.example-db-preset.id } ``` Но это плохой путь, который вредит информационной безопасности всей системы, даже если вы используете частный репозиторий Git для хранения проекта. Дело в том, что любой пользователь с доступом к системе контроля версий также будет иметь доступ к секретам.  Кроме этого, многие инструменты, имеющие доступ к репозиторию, такие как Jenkins, CircleCI или GitLab, сохраняют копию репозитория перед сборкой кода. Также, храня чувствительную информацию в виде обычного текста, вы рискуете, что одна из программ на вашем компьютере получит доступ к этим файлам, а значит и к секретам .  В общем, хранение конфиденциальной информации в виде обычного текста сильно упрощает доступ к ним, чем, например, могут воспользоваться злоумышленники. Что, в целом, актуально для любых инструментов, а не только Terraform. Поэтому главное правило шифрования секретов в инфраструктуре как код — это хранение конфиденциальной информации не в виде открытого текста. К чему могут привести незащищенная информация: - **Нарушения комплаенса**. Многие отрасли работают с чувствительной информацией, например персональными данными, которые регулируются законодательством. Несоблюдение надлежащего процесса работы с конфиденциальной информацией может привести к крупным штрафам, а также к репутационному ущербу. - **Несанкционированный доступ к данным.** Из-за незащищенной должным образом информации, лица без соответствующего допуска могут получить доступ к конфиденциальной информации. - **Нарушения информационной безопасности.** Раскрытые данные могут быть использованы злоумышленниками для кражи, изменения информации или даже для полной компрометации целых систем. ## Файл состояния terraform.tfstate У Terraform есть один изъян, который снижает безопасность системы. Каждый раз, когда пользователь использует Terraform для развертывания своей инфраструктуры, он сохраняет большое количество информации о ней, в том числе и предоставленные параметры для подключения к базе данных, в файле состояния `terraform.tfstate` в виде обычного текста. Этот файл сохраняется в той директории, в которой пользователь выполнял команду `apply`.   Это приводит к тому, что даже если использовать любой из методов, приведенных в данной статье, чувствительная информация все равно будет доступна в виде обычного текста в файле состояния.  [Об этой проблеме](https://github.com/hashicorp/terraform/issues/516) известно уже больше девяти лет, но до сих пор нет какого-то общего решения. Существуют временные фиксы, которые удаляют секреты из файлов состояния, но они недостаточно надежно работают и могут перестать быть совместимы после очередного обновления.  Поэтому на текущий момент, вне зависимости от того, какой метод используется для шифрования, самым важным аспектом безопасности данных является безопасность файла состояния. Не рекомендуется хранить его в локальной части системы и репозитории, а использовать для этого хранилища, которые поддерживают шифрование. Например, в объектном хранилище S3 с контролем доступа к нему. ## Переменные окружения для шифрованию ключей Terraform поддерживает чтение переменных окружения, и это можно использовать для шифрования ключей. Для начала создадим несколько переменных в каталоге проекта `variables.tf`: ```shell variable "username" {      description = "Имя пользователя"        type = string      sensitive = true }  variable "password" {      description = "Пароль пользователя"        type = string      sensitive = true } ``` Параметр `type` определяет тип переменных, а параметр `sensitive` помечает, что в переменной хранится конфиденциальная информация. Когда его значение равно `true`, данные переменной не отразятся в логах, в том числе при выполнении команд `plan` и `apply`. Теперь заменим в коде `resources` переменные: ```shell resource "twc_db_mysql_8" 'my_db' {      name = "mysql_8_database'      # Имя пользователя и пароль      login = var.username      password = var.password      preset_id = data.twc_db_preset.example-db-preset.id } ``` И установим значение переменных через терминал. В терминале к их имени необходимо добавлять `TF_VAR_`: `username` → `TF_VAR_username`.  ```shell export TF_VAR_username="root" export TF_VAR_password="admin" ``` Когда пользователь выполнит команду `terraform apply`, Terraform будет использовать значение переменных среды.  **Важно**: после выполнения Bash-команды сохраняются в истории. Чтобы в ней не сохранились конфиденциальные данные, такие как пароль и логин, воспользуйтесь переменной окружения `HISTCONTROL`. Задайте ей значение `ignorespace` — в таком случае команды, которые начинаются с пробела, сохранятся в истории не будут: ```shell export HISTCONTROL=ignorespace ``` ## Шифрование конфиденциальных данных в Terraform с помощью GPG Благодаря переменным окружения в коде Terraform не будет конфиденциальных данных, указанных в виде текста. Однако они не полностью решают проблему шифрования секретов — в некотором смысле переменные окружения «переносят» проблему из области инструмента в область операционной системы, в которой эти конфиденциальные данные также необходимо защитить. Популярный подход к решению этой проблемы — это хранение конфиденциальных данных в виде зашифрованных файлов с помощью GPG. Для этого можно использовать для этого можно использовать «чистый» GPG, а можно воспользоваться менеджером паролей, который реализует такую же логику. Например, Pass.  ### Менеджер паролей Pass В нём данные хранятся в виде GPG-зашифрованных файлов. Они организованы в виде иерархии каталогов, которые могут быть скопированы с одного устройства на другое, а управлять Pass можно с помощью стандартных команд терминала. Руководство по установке инструмента на разные операционные системы размещено [на его официальном сайте](https://www.passwordstore.org/). Вот код для инсталляции на Ubuntu: ```shell sudo apt update sudo apt install pass ``` Для работы с Pass понадобится GPG-ключ. Для его генерации в первую очередь необходимо установить GPG: ```shell sudo apt install gpg ``` После — сгенерировать ключ: ```shell gpg --full-generate-key ``` Выберите размер ключа и его тип (например «RSA and RSA»), а также укажите данные для генерации. После генерации в выводе терминала будет GPG-ключ: ![Image1](https://content.timeweb.com/assets/8d8741e9-3ee5-4704-b80f-57325f6f3198?width=731&height=188) Скопируйте GPG-ключ и используйте его для инициализации Pass: ```shell pass init ``` Зашифруем с помощью Pass уже упомянутые переменные — `username` и `password`: ```shell pass insert username ``` После выполнения дважды введите значение переменной. Аналогичным образом поступаем с `password`: ```shell pass insert password ``` Чтобы получить доступ к секретам из командной строки, используйте команду `pass` и имя секрета: ```shell pass username ``` Введите кодовую фразу, которую указали при генерации GPG-ключа, и секрет будет отображен в консоли в виде обычного текста. Теперь, чтобы использовать зашифрованные данные, установите их в качестве переменных окружения: ```shell export TF_VAR_username=$(pass username) export TF_VAR_password=$(pass password) ``` В чём плюсы и минусы использовать для шифрования секретов переменные окружения: | **Плюсы** | **Минусы** | | --- | --- | | Секреты остаются вне кода, а значит, не отражаются в репозитории. | Инфраструктура не полностью описывается в коде Terraform — это усложняет его поддержку и снижает читаемость. | | Легко использовать: для начала работы не требуется высокой квалификации. | Требуются дополнительные шаги для работы с таким решением. | | Переменные окружения можно интегрировать со многими менеджерами паролей, как в примере с Pass. | Поскольку вся работа с секретами происходит за пределами Terraform, на неё не распространяется средства безопасности, заложенные в коде. | | Подходит для тестовых запусков: в качестве переменных окружения легко установить фиктивные значения. | | ## Шифрование секретов с помощью HashiCorp Vault Vault — это внешнее хранилище с открытым исходным кодом для хранения чувствительной информации. Его также, как и Terraform, разработала компания HashiCorp.  Vault позволяет реализовать централизованное зашифрованное хранилище для секретов. Вот его ключевые функции: - **Хранение чувствительной информации**. Базовая функция Vault — шифрование и хранение секретов: паролей, API-ключей, сертификатов, токенов и других данных. - **Аутентификация пользователей**. Для получения доступа к секретам пользователь или приложение должен аутентифицироваться. В инструменте поддержано несколько методов: от классической связки пароля и логина до интеграции с другими система аутентификации. - **Контроль доступа.** В Vault можно гибко настроить, какие пользователи и приложения могут иметь доступ к тем или иным секретам. Это реализуется через политики доступа, в которых описываются разрешения на просмотр и другие операции с секретами. - **Аудит запросов.** С помощью инструмента можно отслеживать, кто и когда обращался к данным в хранилище. ### Установка Vault — это внешнее хранилище, и взаимодействие с ним осуществляется через сеть. Поэтому его можно установить как на локальное устройство и обращаться к нему через localhost, так и на удаленный сервер. В этом материале расскажем, как установить его на Ubuntu: 1. Обновите индексы пакетов и установите GPG. ```shell sudo apt update && sudo apt install gpg ``` 2. Загрузите GPG-ключ. Для загрузки необходимо воспользоваться нероссийским IP-адресом. ```shell wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list ``` 3. Установите Vault: ```shell sudo apt update && sudo apt install vault ``` 4. Чтобы убедиться, что установка прошла успешно, проверьте версию программного обеспечения: ```shell vault version ``` Если установка завершилась успешно, в терминале будет отображена последняя версия хранилища ключей. ### Настройка После установки инструмент необходимо настроить. Мы будем использовать его в режиме сервера. Запустим его: ```shell vault server -dev ``` **Важно:** здесь мы запускаем сервер в режиме разработки. Это означает, что в таком режиме работы, он будет хранить все данные, в том числе ключи, в оперативной памяти. При перезапуске сервера все данные будут потеряны, поэтому для в продакшене желательно использовать обычный режим работы сервера. Режим разработки подходит для учебных целей, как этот материал. Во время выполнения команды в терминале будет отображаться детали ее прогресса, а после — URL-адрес, на котором работает сервер, и токен для авторизации. К нему можно подключиться даже через браузер, введя в поисковой строке URL-адрес сервера. Для дальнейшей работы с сервером в режиме разработки необходимо создать переменную окружения с его URL-адресом. Если вы устанавливали Vault на локальном компьютере, то команда будет выглядеть так: ```shell export VAULT_ADDR='http://127.0.0.1:8200' ``` Проверить состояние хранилища можно следующим образом: ```shell vault status ``` Команда вернет информацию о нём: дата создания, версию программного обеспечения и другое. Для хранения конфиденциальной информации воспользуемся хранилищем «ключ-значение». Для начала создадим его: ```shell vault secrets enable -path=db_data kv ``` После добавим в хранилище секреты: ```shell vault kv put db_data/secret_tf username=root password=admin ``` Проверить результат можно прямо в браузере. ### Как использовать HashiCorp Vault для хранения секретов в Terraform В Main-файле Terraform укажем Vault как провайдера: ```shell terraform {      required_providers {           vault = {                source = "hashicorp/vault"                version = "3.23.0"           }           twc = {                source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"           }      }      required_version = ">= 0.13" } ``` В конфигурационном файле Terraform также необходимо прописать инструмент как провайдера: ```shell provider "vault" {  address = "http://127.0.0.1:8200"  token   = "Токен Vault" } ``` А также реализовать метод для чтения данных из хранилища: ```shell data "vault_generic_secret" "secret_credentials" {      path = "db_data/secret_tf" } resource "twc_db_mysql_8" 'my_db' {      name = "mysql_8_database'      # Имя пользователя и пароль      login = data.vault_generic_secret.secret_credentials.data["username"]      password = data.vault_generic_secret.secret_credentials.data["password"]      preset_id = data.twc_db_preset.example-db-preset.id } ``` ## Как автоматизировать шифрование секретов в Terraform Шифрование секретов в Terraform можно автоматизировать, чтобы обеспечить масштабируемый и безопасный процесс управления конфиденциальными данными. Ниже — некоторые способы автоматизации: - **Скрипты.** С помощью них можно автоматически передавать секреты Terraform. Это можно реализовать с помощью GPG или OpenSSL. - **CI/CD инструменты.** Во многие CI/CD инструменты, например GitLab CI/CD или Jenkins, встроено шифрование, которое можно использовать в автоматическом режиме вместе с Terraform. ## Заключение В этой статье мы рассмотрели вопрос безопасности чувствительной информации, к чему может привести её хранение в незащищенном виде, обсудили, почему нужно бережно хранить файл состояния, а также привели примеры шифрования секретов в Terraform с помощью Hashicorp Vault, переменных сред и GPG.