|

Terraform Azure VM Linux: guía con estado remoto 2026

En pocas palabras: Con Terraform y el provider azurerm se despliega una VM Linux en Microsoft Azure definiendo ocho recursos (grupo de recursos, red virtual, subnet, IP pública, NSG, interfaz de red, storage account y la VM) en archivos HCL, ejecutando init, plan y apply, sin usar el portal.

Un ingeniero armó una VM Linux completa en Azure sin tocar el portal: red virtual, subnet, IP pública, grupo de seguridad y storage account para el estado remoto, todo con Terraform y el provider azurerm. El proyecto, publicado el 24 de septiembre de 2026 en dev.to, documenta ocho recursos y un error de nomenclatura que le costó un ciclo completo de apply.

Terraform es la herramienta de HashiCorp para definir infraestructura como código usando sintaxis HCL. En Azure, el provider azurerm traduce esas definiciones en llamadas a la API de Microsoft para crear VMs, redes y storage accounts. La combinación terraform azure vm linux permite versionar, revisar y reproducir un entorno completo sin clickear el portal, algo clave cuando el equipo crece.

En 30 segundos

  • El proyecto de dev.to arma 8 recursos de Azure con Terraform: resource group, VNet, subnet, IP pública, NSG, interfaz de red, VM y storage account.
  • El backend remoto usa Azure Storage con SKU Standard_LRS y un container llamado “tfstate” para evitar el riesgo del estado local en equipos.
  • La VM usa tamaño Standard_B2ats_v2 con imagen Canonical ubuntu-24_04-lts y acceso SSH por clave pública, sin password.
  • El NSG define dos reglas: Allow-SSH en puerto 22 (prioridad 100) y Allow-HTTP en puerto 80 (prioridad 101).
  • El error más común: nombres de storage account solo en minúsculas y números, globalmente únicos en toda Azure.

¿Por qué usar Terraform en lugar del portal de Azure para crear una VM?

Con Terraform escribís la infraestructura en archivos de texto que podés versionar en Git, revisar en un pull request y reaplicar exactamente igual las veces que quieras. El portal de Azure no te da eso: cada VM que armás a mano depende de que alguien recuerde los mismos clicks, en el mismo orden, sin errores.

Ponele que tenés que replicar un entorno de staging en otra región. Con el portal, arrancás de cero: red, subnet, NSG, VM, todo de nuevo. Con Terraform, cambiás una variable de ubicación y corrés terraform apply otra vez.

El proyecto de dev.to lo plantea así: la idea no es solo levantar una máquina, es desarrollar el criterio para ingeniar infraestructura en vez de configurarla a mano. Eso incluye gestionar el estado en Azure Storage, controlar el acceso SSH con reglas de red y trackear todo con GitHub. Nada de esto escala si lo hacés clickeando.

¿Qué recursos de Azure se necesitan para desplegar una VM Linux con Terraform?

El proyecto usa ocho recursos de Azure para levantar una VM Linux funcional con acceso remoto seguro. No hay atajos: cada uno cumple un rol específico en la cadena de red y seguridad. Complementá con conectarte por SSH a tu máquina virtual.

  • Resource Group: el contenedor lógico que agrupa todos los recursos del proyecto (en el ejemplo, “september-rg”).
  • Virtual Network y Subnet: la red 10.0.0.0/16 con una subnet 10.0.1.0/24 donde vive la VM.
  • Public IP: con asignación estática, para tener siempre la misma dirección al reiniciar la máquina.
  • Network Security Group: el firewall a nivel de subnet/NIC con las reglas de entrada.
  • Network Interface: conecta la VM con la subnet y la IP pública.
  • Linux Virtual Machine: el recurso central, con tamaño Standard_B2ats_v2 e imagen Canonical ubuntu-24_04-lts.
  • Storage Account: no para la VM en sí, sino para guardar el archivo de estado de Terraform.

Ocho piezas que, armadas a mano, son media hora de clicks propensos a error. Con Terraform, son un terraform apply.

¿Cómo configurar el backend remoto de Terraform en Azure Storage?

El estado remoto de Terraform en Azure se configura con un bloque backend "azurerm" que apunta a un storage account, un resource group y un container de blobs. Ahí queda guardado el archivo .tfstate en lugar de en tu disco local.

¿Por qué importa esto? Porque el estado local no funciona bien en equipo: contiene información sensible (IPs, IDs de recursos, a veces secretos) y corre riesgo de borrarse por accidente. Según la documentación oficial de HashiCorp, el backend azurerm soporta bloqueo de estado (state locking) y verificación de consistencia usando las capacidades nativas de Azure Blob Storage, lo que evita que dos personas apliquen cambios en simultáneo y se pisen el estado.

El script bash del proyecto crea tres cosas en orden: un resource group llamado “tfstatebackend-rg”, un storage account con SKU Standard_LRS y encriptación de blob habilitada, y un container llamado “tfstate”. Después, el bloque en backend.tf queda así:

  • resource_group_name: “tfstatebackend-rg”, donde vive el storage account del backend.
  • storage_account_name: el nombre único del storage account (solo minúsculas, ojo con esto más abajo).
  • container_name: “tfstate”, el container de blobs donde se guarda el archivo.
  • key: el nombre del blob específico, por ejemplo “terraform-azurexxxxxxxxxxxxx.tfstate”.

Vale una aclaración sobre autenticación: la documentación de HashiCorp recomienda usar Microsoft Entra ID (antes Azure AD) con OpenID Connect para pipelines de CI/CD en vez de access keys hardcodeadas, justamente porque las claves de acceso quedan expuestas en el directorio .terraform y en los archivos de plan si no las manejás con variables de entorno.

¿Cómo se estructuran variables.tf y main.tf en este proyecto?

El archivo variables.tf centraliza todos los valores configurables (nombres, tamaños, rangos de red) y main.tf encadena los recursos usando referencias entre ellos, como azurerm_resource_group.september-rg.name. Es el patrón estándar de Terraform: separar qué valores cambian de cómo se arma la infraestructura. Más contexto en certificarte según tu rol en Azure.

Entre las variables clave del proyecto: subscription_id marcada como sensitive = true (para que no aparezca en logs), el resource group por defecto “september-rg” en la región SouthAfricaNorth, la VNet con rango 10.0.0.0/16, la subnet en 10.0.1.0/24, el tamaño de VM Standard_B2ats_v2, y la imagen Canonical con offer “ubuntu-24_04-lts”. El usuario admin se llama “septemberuser” y la clave SSH se lee desde ~/.ssh/id_rsa.pub.

En main.tf, el provider queda fijado en la versión 5.1.0 del provider azurerm, según el bloque required_providers del proyecto. Acordate que fijar versión no es un capricho: cambios entre versiones mayores del provider rompen sintaxis sin previo aviso.

¿Cómo configurar las reglas de seguridad SSH y HTTP en el Network Security Group?

El NSG del proyecto define dos reglas de entrada (Inbound), ambas con acceso Allow y protocolo Tcp. La regla Allow-SSH abre el puerto 22 con prioridad 100, y la regla Allow-HTTP abre el puerto 80 con prioridad 101. En Azure, prioridad más baja significa que se evalúa primero.

Ojo con esto: en el ejemplo, tanto source_address_prefix como destination_address_prefix quedan en “*”, es decir, abierto a cualquier IP de origen. Funciona para un proyecto de práctica, pero en un entorno real conviene restringir el origen del SSH a tu IP o a una VPN, porque dejar el puerto 22 abierto a internet es una invitación a bots de fuerza bruta.

El NSG no hace nada solo: hay que asociarlo explícitamente a la interfaz de red con el recurso azurerm_network_interface_security_group_association. Si te olvidás de ese paso, las reglas quedan definidas pero no aplicadas, y te vas a preguntar por qué no podés conectarte. Te puede servir nuestra cobertura de diferencias entre Microsoft y GitHub.

¿Cuál es el flujo de comandos para inicializar y aplicar la configuración?

El flujo real usado en el proyecto sigue cinco pasos: terraform init, terraform validate, terraform plan, terraform apply y terraform state list. Cada uno cumple una función distinta y saltearse alguno es la forma más común de romper un deploy sin darte cuenta.

  • terraform init: descarga el provider azurerm y configura la conexión con el backend remoto.
  • terraform validate: chequea sintaxis sin tocar Azure.
  • terraform plan: previsualiza qué se va a crear, modificar o destruir, sin aplicar nada todavía.
  • terraform apply: ejecuta el plan y crea los recursos reales.
  • terraform state list: lista todos los recursos que Terraform está trackeando en el estado.

Al final, el proyecto expone un output llamado vm_public_ip que devuelve la IP pública de la VM directamente en la terminal, sin tener que ir a buscarla al portal. Con esa IP y el usuario “septemberuser”, la conexión SSH queda lista.

¿Qué error real aparece al nombrar el storage account en Terraform Azure?

Azure rechaza cualquier nombre de storage account que tenga mayúsculas, guiones o caracteres especiales, y Terraform devuelve el mensaje “can only contain lowercase letters and numbers” cuando eso pasa. El autor del proyecto lo cuenta como la lección concreta que le dejó todo el ejercicio: quemó un ciclo entero de apply por este detalle.

¿Por qué es tan quisquilloso Azure con esto? Porque el nombre del storage account forma parte de la URL pública del endpoint (algo como nombrecuenta.blob.core.windows.net), y tiene que ser único en toda la nube de Azure, no solo dentro de tu suscripción. Nada de mayúsculas, nada de puntos, nada de guiones bajos.

La solución práctica es simple: generar el nombre con una combinación de letras minúsculas y números, y validar unicidad antes de correr el apply. El ejemplo de la documentación oficial de Microsoft Learn resuelve esto con el recurso random_id, que genera un sufijo aleatorio y lo concatena al nombre base, evitando el problema por completo en vez de andar probando nombres a mano.

Proyecto de dev.to vs quickstart oficial de Microsoft: qué cambia

Son dos formas válidas de resolver lo mismo, pero con decisiones distintas en puntos clave. Comparar ambas te sirve para elegir según si estás practicando o armando algo para producción. Ya lo cubrimos antes en repos de GitHub comprometidos con malware.

AspectoProyecto dev.toQuickstart Microsoft Learn
Versión del provider azurerm5.1.0 (fijada)~>3.0 (rango flexible)
Generación de clave SSHArchivo local (~/.ssh/id_rsa.pub)Recurso azapi_resource_action que la genera en Azure
Nombre único de storage accountManual, causó el error de nomenclaturaAutomático con random_id
Estado de TerraformRemoto en Azure Storage desde el arranqueLocal por defecto en el quickstart
Tamaño de VMStandard_B2ats_v2Standard_DS1_v2
terraform azure vm linux diagrama explicativo

El quickstart de Microsoft prioriza que el ejemplo funcione sin depender de que vos ya tengas una clave SSH generada. El proyecto de dev.to prioriza mostrar un flujo de trabajo en equipo real, con estado remoto desde el primer día. Ninguno es “el correcto”: dependen del contexto.

Qué significa esto para equipos en Latinoamérica

Si tu equipo ya labura con Azure para cómputo pero necesita dominios o hosting complementario en Argentina, con soporte en español y facturación local, vale la pena mirar opciones como donweb.com para esa parte, mientras Azure sigue siendo la nube de cómputo. No son excluyentes: una VM Linux en Azure puede convivir perfectamente con un dominio .com.ar gestionado en otro proveedor.

Errores comunes al desplegar una VM Linux con Terraform en Azure

  • Dejar el estado en local en un equipo de más de una persona: alguien va a aplicar sobre un estado desactualizado y va a duplicar o borrar recursos sin querer. Usá backend azurerm desde el arranque.
  • Usar mayúsculas o guiones en el nombre del storage account: Terraform lo rechaza directo con el error de nomenclatura. Generá el nombre con minúsculas y un sufijo aleatorio.
  • Dejar el NSG con source_address_prefix en “*” para SSH en producción: funciona para practicar, pero es exponer el puerto 22 a todo internet. Restringilo a tu rango de IP.
  • Olvidar la asociación entre NSG y Network Interface: las reglas quedan definidas pero no aplicadas si falta el recurso azurerm_network_interface_security_group_association.
  • No fijar la versión del provider azurerm: un cambio de versión mayor puede romper sintaxis entre aplicaciones sin aviso previo.

Preguntas Frecuentes

¿Qué es Terraform y para qué sirve en Azure?

Terraform es una herramienta de HashiCorp que define infraestructura como código en archivos HCL, permitiendo crear, modificar y destruir recursos de nube de forma reproducible. En Azure, el provider azurerm traduce esas definiciones en llamadas reales a la API de Microsoft para levantar VMs, redes y storage accounts sin usar el portal.

Si vas a levantar infraestructura en la nube, esto se conecta con desplegar VM Linux en Azure con Terraform, donde repasamos el proceso paso a paso.

¿Cómo creo una VM Linux en Azure con Terraform?

Necesitás definir un resource group, red virtual, subnet, IP pública, NSG, interfaz de red y el recurso azurerm_linux_virtual_machine en tu archivo main.tf, y correr terraform init, terraform plan y terraform apply en ese orden. El proyecto de dev.to documenta los ocho recursos completos con código de ejemplo.

¿Qué es el estado remoto (remote state) de Terraform en Azure?

El estado remoto es guardar el archivo .tfstate en un storage account de Azure en vez de en tu disco local, usando el backend “azurerm”. Esto permite trabajo en equipo con bloqueo de estado, según confirma la documentación oficial de HashiCorp, evitando que dos personas apliquen cambios en simultáneo.

¿Cómo me conecto por SSH a una VM de Azure creada con Terraform?

Usás el output de la IP pública que expone Terraform (como vm_public_ip) junto con el usuario admin definido en la variable admin_username y tu clave SSH privada correspondiente a la pública que subiste en ssh_public_key_path. El comando queda: ssh usuario@ip-publica.

¿Por qué falla la creación del storage account en Terraform Azure?

Falla cuando el nombre elegido tiene mayúsculas, guiones o ya está en uso en cualquier parte de Azure, no solo en tu suscripción. El mensaje de error es explícito: “can only contain lowercase letters and numbers”. La solución es usar solo minúsculas y números, y agregar un sufijo aleatorio para garantizar unicidad global.

Conclusión

El caso de dev.to no trae ninguna funcionalidad nueva de Azure ni de Terraform: lo que aporta es un flujo completo y documentado, con el error real incluido, algo que la documentación oficial suele pulir hasta dejarlo invisible. Si estás por armar tu primer entorno con terraform azure vm linux, el punto de partida no es copiar el código tal cual, es entender por qué cada recurso está ahí y qué pasa si te olvidás de uno.

Antes de aplicar en un entorno real, chequeá tres cosas: que el estado esté en un backend remoto desde el día uno, que el NSG no tenga el SSH abierto a “*” en producción, y que el nombre del storage account use un sufijo aleatorio en vez de un texto fijo. Son los tres puntos donde este proyecto (y la mayoría de los que arrancan con Terraform en Azure) se trastabillan primero.

Fuentes

Te puede interesar...