Terraform полезен не только в облаке. Домашняя лаборатория из Proxmox, libvirt или десятка LXC-контейнеров быстро обрастает ручными настройками, которые невозможно повторить. Описание инфраструктуры кодом превращает создание виртуальных машин в предсказуемый процесс: план, проверка, применение. Ниже — установка, структура проекта, первый план для Proxmox и правила, которые уберегут от потери состояния.
Зачем это дома
Скрипт на bash тоже создаёт виртуальные машины, но у него нет плана изменений и учёта уже существующих ресурсов. Terraform хранит состояние, сравнивает желаемое с фактическим и показывает, что именно будет создано, изменено или удалено. Это дисциплинирует: вы видите последствия до нажатия Enter. Кроме того, конфигурация становится документацией — по ней понятно, сколько ядер, памяти и дисков должно быть у каждой машины.
Terraform не заменяет Ansible. Первый создаёт инфраструктуру, второй настраивает внутри неё пакеты и сервисы. Разумная связка для дома: Terraform поднимает ВМ из шаблона, Ansible ставит на них роли. Если важна лицензионная чистота, присмотритесь к OpenTofu — форку с совместимым синтаксисом и CLI; остальные команды работают и там, только бинарник называется tofu.
Установка
В Debian и Ubuntu удобно подключить репозиторий HashiCorp. Команды ниже добавляют ключ и список пакетов, после чего terraform ставится через apt и обновляется вместе с системой.
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
sudo apt update
sudo apt install terraform
terraform -version
Если lsb_release не установлен, добавьте пакет lsb-release. На Fedora и RHEL есть аналогичный репозиторий, а на Arch пакет лежит в официальных репозиториях. Главное — проверить версию: в проекте ниже указана 1.6, этого достаточно для всех конструкций из статьи.
Структура проекта
Не складывайте всё в один main.tf. Минимальный набор файлов разделяет провайдер, переменные, ресурсы и выходные значения. Каталог .terraform и файлы состояния не коммитятся, а файл блокировки .terraform.lock.hcl — коммитится, чтобы версии провайдера были одинаковыми на всех машинах.
terraform-proxmox/
├── versions.tf
├── variables.tf
├── main.tf
├── outputs.tf
├── terraform.tfvars
└── .gitignore
.terraform/
*.tfstate
*.tfstate.*
*.tfplan
terraform.tfvars
*.auto.tfvars
Секреты в terraform.tfvars хранить нельзя, если каталог попадает в git. Для токена используйте переменную окружения TF_VAR_имя_переменной: Terraform подхватит её автоматически и не запишет в файл. Если в tfvars остаются только несекретные значения, держите рядом terraform.tfvars.example и коммитьте его.
Провайдер и подключение к Proxmox
Создайте в Proxmox API-токен с правами на управление виртуальными машинами в нужном пуле. Токен состоит из идентификатора и секрета; в конфигурации он передаётся одной строкой. Для самоподписанного сертификата PVE допускается insecure = true, но в постоянной лаборатории лучше поставить нормальный сертификат.
terraform {
required_version = ">= 1.6"
required_providers {
proxmox = {
source = "bpg/proxmox"
}
}
}
provider "proxmox" {
endpoint = "https://192.168.1.10:8006/"
api_token = var.proxmox_token
insecure = true
ssh {
agent = true
username = "root"
}
}
В ssh-блоке username должен совпадать с пользователем, от имени которого выпущен токен. Токен задайте переменной с пометкой sensitive. Считайте его без эха и экспортируйте: так он не попадёт в вывод plan и не сохранится в истории shell.
read -s -p "API token: " TF_VAR_proxmox_token
export TF_VAR_proxmox_token
variable "proxmox_token" {
type = string
sensitive = true
}
variable "template_vm_id" {
type = number
default = 9000
}
Первый план: две машины из шаблона
Подготовьте в Proxmox шаблон с cloud-init и запомните его VMID. Ресурс ниже клонирует шаблон дважды, задаёт имена, ядра, память и сетевой мост. Карта for_each фиксирует соответствие имени и VMID, поэтому порядок перебора предсказуем.
resource "proxmox_virtual_environment_vm" "lab" {
for_each = {
lab-1 = 201
lab-2 = 202
}
name = each.key
node_name = "pve"
vm_id = each.value
clone {
vm_id = var.template_vm_id
}
cpu {
cores = 2
}
memory {
dedicated = 2048
}
agent {
enabled = true
}
network_device {
bridge = "vmbr0"
}
}
Добавьте output, чтобы после применения видеть идентификаторы.
output "vm_ids" {
value = { for name, vm in proxmox_virtual_environment_vm.lab : name => vm.vm_id }
}
Теперь выполните инициализацию, форматирование, проверку и план. План сохраняется в файл: применять нужно именно его, а не заново пересчитанную конфигурацию.
terraform init
terraform fmt -recursive
terraform validate
terraform plan -out=tfplan
terraform apply tfplan
Если план пустой, значит ресурсы уже существуют и совпадают с описанием. Если Terraform предлагает пересоздать машину из-за смены неизменяемого поля, остановитесь и прочитайте причину: у некоторых атрибутов изменение требует замены, и данные на диске будут потеряны.
Состояние, дрейф и импорт
Файл terraform.tfstate — это не кэш, а источник истины о созданных ресурсах. Потеря состояния означает, что Terraform больше не знает о машинах и попытается создать их заново. Для дома достаточно локального состояния, но его нужно включать в резервное копирование. В команде из нескольких человек используйте удалённый backend с блокировкой.
terraform state list
terraform plan -refresh-only
terraform apply -refresh-only
terraform import 'proxmox_virtual_environment_vm.lab["lab-1"]' pve/201
Команда refresh-only сверяет состояние с реальностью, не меняя ресурсы. Импорт позволяет взять под управление машину, созданную вручную; формат идентификатора зависит от провайдера, поэтому сверьтесь с его документацией. Удаление через terraform destroy необратимо: сначала проверьте план с ключом -destroy и убедитесь, что в нём нет лишних ресурсов.
Чек-лист безопасности
- Не коммитьте state, tfvars с секретами и каталог .terraform.
- Коммитьте .terraform.lock.hcl и фиксируйте версию провайдера после первого init.
- Передавайте токены через переменные окружения или хранилище секретов.
- Читайте план до применения и не используйте -auto-approve вслепую.
- Храните резервную копию состояния вне рабочей машины.
- Разделяйте проекты по каталогам, а не только по workspaces: так меньше шансов перепутать окружения.
Итог
Terraform превращает домашнюю лабораторию в описанный и повторяемый набор ресурсов. Начните с одного проекта и двух ВМ: подключите провайдер, вынесите переменные, сохраните план и примените его. Дальше добавьте резервное копирование состояния и проверку дрейфа. Главные правила просты: состояние — это ценность, секреты — не в git, а план нужно читать до применения. Этого достаточно, чтобы перестать собирать инфраструктуру вручную и начать её версионировать.