Primeros pasos con Terraform¶
En este artículo
- Qué necesitas para trabajar con Terraform
- Paso 1. Instalar Terraform
- Paso 2. Crear una API key
- Paso 3. Preparar la configuración
- Paso 4. Inicializar el provider
- Paso 5. Validar la configuración
- Paso 6. Pedir el servidor
- Paso 7. Cambiar la configuración
- Paso 8. Destruir los recursos
- Importar servidores existentes
- Resolución de problemas
Información
Terraform es una herramienta de infraestructura como código desarrollada por HashiCorp. El estado deseado de la infraestructura se describe en archivos de configuración escritos en HCL, y Terraform alinea los recursos reales con esa descripción mediante la llamada a la API del proveedor de servicios a través de un módulo dedicado conocido como provider. Cada operación que realiza se registra en un archivo de estado, por lo que la herramienta sabe qué existe ya y aplica solo los cambios faltantes en la siguiente ejecución. Terraform permite previsualizar los cambios antes de aplicarlos, mantener la configuración en un control de versiones y reproducir entornos idénticos, lo que lo convierte en una forma conveniente de gestionar servidores, redes y servicios, independientemente de quién los aloje.
Cuando solo ejecutas un servidor, pedirlo manualmente es más rápido. Una vez que hay quince, creados en diferentes momentos por diferentes administradores, nadie recuerda por qué uno ejecuta Ubuntu 20.04 mientras que la máquina de al lado ejecuta 22.04. Un archivo de configuración mantiene ese historial por sí mismo, y también te permite levantar el mismo entorno sin tener que reconstruir una secuencia de clics de memoria.
Con nuestro provider el flujo de trabajo es el siguiente. El archivo enumera el preset, la ubicación, el sistema operativo y el plan de tráfico, tras lo cual terraform apply realiza el pedido y espera a que la implementación finalice. Ejecutarlo de nuevo no duplica nada, ya que Terraform recuerda los recursos que creó. El comando terraform plan muestra los próximos cambios sin realizar ninguno de ellos.
El provider funciona con todo el catálogo, incluyendo VPS, VDS, servidores dedicados y GPU, direcciones IP adicionales, claves SSH y zonas DNS. La referencia completa de los recursos y fuentes de datos está disponible en el Terraform Registry y en el repositorio hostkey-cloud/terraform-provider-hostkey-com. Lo que sigue es el escenario básico: pedir un servidor virtual.
Qué necesitas para trabajar con Terraform¶
- Una cuenta en el panel de control Invapi con fondos en el saldo, ya que pedir un servidor es una operación de pago;
- una API key;
- una clave SSH;
- Terraform 1.0 o superior.
Atención
La cuenta debe tener al menos un servidor. Invapi no emite una sesión para una cuenta sin servicios, y la autenticación fallará con No appropriate servers found. Si la cuenta es nueva, pide el primer servidor a través del panel de control y crea el resto con Terraform.
Paso 1. Instalar Terraform¶
Terraform se ejecuta en Linux, macOS y Windows, y puedes instalarlo de dos maneras: mediante un gestor de paquetes o manualmente, descargando y descomprimiendo el binario precompilado.
Windows¶
Descarga el archivo, descomprime terraform.exe en una carpeta dedicada como C:\terraform y añade esa carpeta a la variable de entorno Path.
Cierra y vuelve a abrir la terminal después, ya que el nuevo valor de Path no se aplica hasta que lo hagas. Para verificar la instalación:
Linux¶
wget https://releases.hashicorp.com/terraform/1.15.8/terraform_1.15.8_linux_amd64.zip
unzip ./terraform_1.15.8_linux_amd64.zip
sudo mv ./terraform /usr/local/bin
terraform -v
macOS¶
Paso 2. Crear una API key¶
La clave se crea en el panel de control Invapi. Haz clic en tu nombre de usuario en la esquina superior derecha y selecciona API keys:

Haz clic en Add new y rellena el formulario.

| Campo | Valor |
|---|---|
| Name | Solo letras latinas, dígitos, _ y - (5-30 caracteres) |
| Restrict a new API key only for the server | Any |
| IP ACL | Deja vacío para permitir el acceso desde cualquier dirección |
| Set login notification method | None |
| Active | Selected |
El campo Restrict a new API key only for the server vincula la clave a un único servicio, y el provider necesita pedir nuevos servidores, por lo que el valor debe ser Any.
El campo IP ACL limita el acceso a las direcciones listadas. Mejora la seguridad; sin embargo, con una dirección IP dinámica, la clave dejará de funcionar en cuanto la dirección cambie, así que deja el campo vacío cuando estés empezando, y para integración continua enumera las direcciones de tus servidores de compilación.
Haz clic en Create. La clave se muestra solo una vez.

Atención
Guarda la clave inmediatamente, ya que solo conservamos su hash y el valor no se puede recuperar. Si la pierdes, tendrás que crear una nueva.
Paso 3. Preparar la configuración¶
Ejemplo de configuración
Hay ejemplos de configuración listos para usar disponibles en el repositorio del provider. Para una configuración básica, consulta el ejemplo examples/basic.
Crea un directorio de proyecto, por ejemplo hostkey-terraform. Los archivos de configuración utilizan la extensión .tf y sus nombres son arbitrarios, ya que Terraform combina cada archivo .tf en el directorio en una única configuración. Nuestro ejemplo utiliza tres archivos.
main.tf¶
El primer bloque fija el provider y la versión requerida de Terraform.
terraform {
required_providers {
hostkey = {
source = "hostkey-cloud/hostkey-com"
version = "~> 0.2"
}
}
required_version = ">= 1.0"
}
provider "hostkey" {}
Nota
A partir de la versión 0.2, el provider se publica por separado para cada sistema de facturación. El paquete hostkey-com funciona con invapi.hostkey.com, por lo que no hay un endpoint de API que elegir y el bloque provider se mantiene vacío.
A continuación viene la comprobación del catálogo. Estos bloques no crean recursos y no se facturan, solo solicitan a la API las listas de presets y planes de tráfico disponibles para pedir:
data "hostkey_presets" "selected" {
location = var.location
name = var.preset_name
}
data "hostkey_traffic_plans" "for_preset" {
location = var.location
instance_id = data.hostkey_presets.selected.presets[0].id
}
output "catalog_preset" {
value = data.hostkey_presets.selected.presets
}
output "catalog_traffic_plans" {
value = data.hostkey_traffic_plans.for_preset.traffic_plans
}
Vale la pena hacer la comprobación por dos razones. El provider requiere una coincidencia exacta del nombre, y el catálogo contiene nombres de planes de tráfico similares, por ejemplo 3 TB / 1 Gbps VM y 3Tb traffic (1Gbps) VM. Además, el contenido del catálogo depende de la ubicación y cambia con el tiempo, por lo que un preset disponible hoy puede no estarlo mañana.
A continuación se describe el servidor:
resource "hostkey_server" "web" {
preset_name = var.preset_name
location_name = var.location
traffic_plan_name = var.traffic_plan_name
deploy_period = "monthly"
os_name = "Ubuntu 22.04"
root_pass = var.root_pass
ssh_key = file(pathexpand(var.ssh_public_key_path))
power_state = "on"
cancellation_type = 1
cancellation_reason = "terraform"
tags = {
env = "demo"
}
timeouts {
create = "90m"
update = "90m"
delete = "30m"
}
}
El bloque timeouts establece cuánto tiempo espera Terraform a que una operación finalice. La implementación suele tardar un par de minutos, pero si la espera se interrumpe por un timeout, el pedido seguirá pagado mientras Terraform pierde el rastro de él.
El argumento cancellation_type establecido en 1 cancela el servicio inmediatamente, mientras que 0 lo deja funcionando hasta el final del periodo pagado.
Nota
El argumento hostname se ha omitido deliberadamente del ejemplo. Cuando se omite, el provider genera un nombre único como tf-44067425, y el servicio aparece con ese nombre en el panel de control. El nombre dentro del sistema operativo puede ser diferente, ya que Invapi no se lo pasa al invitado, por lo que la única forma de comprobarlo es ejecutando hostname en el propio servidor.
La clave SSH en el almacenamiento de la cuenta se crea por separado:
resource "hostkey_ssh_key" "deploy" {
name = "tf-deploy"
key = file(pathexpand(var.ssh_public_key_path))
}
Esto no es lo mismo que el atributo ssh_key de hostkey_server. El atributo del servidor escribe la clave en la máquina durante la instalación del sistema operativo, mientras que el recurso hostkey_ssh_key almacena la clave en la cuenta para su uso posterior.
El archivo termina con bloques output. Después del pedido, Terraform imprime la dirección del servidor, su identificador y el número de factura, y terraform output main_ipv4 devuelve la dirección en cualquier momento posterior, lo cual es útil cuando algo más se ejecuta después:
output "server_id" {
value = hostkey_server.web.id
}
output "main_ipv4" {
value = hostkey_server.web.main_ipv4
}
output "invoice" {
value = hostkey_server.web.invoice
}
variables.tf¶
variable "location" {
type = string
default = "FI"
}
variable "preset_name" {
type = string
default = "vm.v2-pico"
}
variable "traffic_plan_name" {
type = string
default = "3 TB / 1 Gbps VM"
}
variable "root_pass" {
type = string
sensitive = true
}
variable "ssh_public_key_path" {
type = string
default = "~/.ssh/id_ed25519.pub"
}
terraform.tfvars¶
Este archivo contiene la contraseña, por lo que no se incluye en el control de versiones:
root_pass = "StrongPass1%"
# Los valores por defecto pueden sobrescribirse aquí
# location = "NL"
# preset_name = "vm.v3-pico"
# traffic_plan_name = "5 TB / 1 Gbps VM"
Atención
La contraseña de root debe tener entre 8 y 30 caracteres y contener una letra mayúscula, una letra minúscula, un dígito y uno de los caracteres %, -, _, +. Los caracteres @ y # no están permitidos. La contraseña se almacena en el archivo de estado de Terraform y se envía en texto plano en el correo electrónico de preparación del servidor, así que cámbiala una vez que el servidor esté desplegado.
Paso 4. Inicializar el provider¶
La clave se pasa a través de una variable de entorno para que permanezca fuera de los archivos del proyecto:
En el símbolo del sistema de Windows usa set HOSTKEY_API_KEY=your-key, y en Linux y macOS export HOSTKEY_API_KEY="your-key". La variable solo se aplica a la sesión actual de la terminal.
Nota
La clave ya es necesaria en la etapa de planificación, ya que el provider compara los nombres de la configuración con el catálogo y falla sin acceso a la API.
A continuación, hay que descargar el provider:

Terraform descarga el provider y crea un archivo .terraform.lock.hcl con la versión exacta. Este archivo se incluye en el repositorio, ya que garantiza que todos en el proyecto terminen con la misma versión instalada.
Paso 5. Validar la configuración¶
La sintaxis se comprueba sin llamar a la API:
Una comprobación exitosa imprime Success! The configuration is valid.
Luego viene el plan, que muestra los próximos cambios sin realizar ninguno de ellos:
La línea de resumen. Se espera Plan: 2 to add, 0 to change, 0 to destroy, es decir, el servidor y la clave SSH.
Los identificadores resueltos. El provider rellena preset_id, os_id y traffic_plan_id junto a los nombres, y si no se encuentra un nombre en el catálogo, el plan falla antes de que se facture nada.
El catálogo. La sección Changes to Outputs enumera los presets y planes de tráfico, y los valores en la configuración deben escribirse exactamente de la misma manera.
Paso 6. Pedir el servidor¶
Terraform muestra el plan una vez más y pide confirmación; escribe yes y pulsa Enter.

Atención
El pedido se paga a partir de este momento. No cierres la ventana de la terminal ni interrumpas el comando; de lo contrario, el pedido se quedará en el panel de control mientras Terraform pierde el rastro de él.
La clave SSH se crea primero, luego comienza el pedido del servidor, y Terraform determinó ese orden por sí mismo a partir de las dependencias.

Después de eso aparecen las líneas Still creating..., que se actualizan cada diez segundos, mientras el provider consulta la API y espera a que la instalación finalice. Mientras tanto, el servidor es visible en el panel de control:

Una vez terminado, se imprimen los valores. Vale la pena comprobar el acceso SSH utilizando la dirección que recibiste:

La clave especificada en el atributo ssh_key ya está presente en el servidor, por lo que no se solicita contraseña. El nuevo servidor aparece en el panel de control junto a los pedidos realizados manualmente:

Paso 7. Cambiar la configuración¶
Los cambios se dividen en tres categorías:
-
Cambios seguros. Las etiquetas (tags) y el estado de encendido se aplican a un servidor en funcionamiento, y el plan los muestra como
update in-place. -
Reinstalación del sistema operativo. Cambiar
os_name,soft_name,root_passossh_keyreinstala el sistema operativo en el mismo servidor, lo que significa que se perderán todos los datos del disco. -
Un nuevo pedido. Cambiar
preset_name,location_name,traffic_plan_nameodeploy_periodsignifica que el servidor anterior se cancela y se pide uno nuevo, por lo que se te volverá a facturar. El plan marca tales cambios comoforces replacement.
Atención
Los cambios que conllevan una reinstalación aparecen en el plan como update in-place, exactamente de la misma manera que un cambio de etiqueta inofensivo. El provider imprime una advertencia aparte sobre la pérdida de datos, por lo que, antes de confirmar, vale la pena leer no solo el plan, sino también las advertencias.
Paso 8. Destruir los recursos¶
terraform destroy elimina todos los recursos que están en el estado actual de Terraform para esta configuración. Terraform mostrará la lista de recursos a eliminar y pedirá confirmación. Escribe yes y pulsa Enter.
Si necesitas eliminar solo un recurso, puedes especificarlo con -target. Por ejemplo:
Aquí, web es el nombre del recurso del bloque resource "hostkey_server" "web", no el ID del servidor del panel de control.
Otra opción es eliminar el recurso de los archivos .tf y ejecutar:
Terraform verá que el recurso ya no está presente en la configuración y lo eliminará de la infraestructura.
La cancelación del servicio se realiza a través de Invapi, y el método de cancelación se determina mediante el parámetro cancellation_type: 1 cancela el servicio inmediatamente, mientras que 0 lo cancela al final del periodo pagado.
Información
Con la cancelación inmediata (cancellation_type = 1), la parte no utilizada del periodo pagado se acredita de nuevo al saldo de la cuenta proporcionalmente al tiempo real que el servicio estuvo funcionando.
Importar servidores existentes¶
Los servidores pedidos a través del panel de control pueden pasar a estar bajo la gestión de Terraform. El identificador se toma de la columna ID en la lista de servidores:
Después de la importación, el estado contiene los datos reales, es decir, el identificador, la dirección, el estado y el estado de encendido. Los argumentos del momento del pedido no se transfieren desde el panel de control, por lo que se describen en la configuración manualmente. El primer terraform apply después de una importación no conlleva una reinstalación.
Resolución de problemas¶
Nota
No appropriate servers found al ejecutar el plan. Comprueba que la cuenta tenga al menos un servicio, ya que Invapi no emite una sesión para una cuenta sin servicios.
Nota
Catalog name resolve failed. El preset, sistema operativo o nombre del plan de tráfico especificado no está presente en el catálogo para la ubicación seleccionada. Enumera los valores disponibles a través de las fuentes de datos hostkey_presets y hostkey_traffic_plans y ajusta la configuración a ellos.
Nota
Estado pending:<invoice>. El pedido está pagado pero la implementación no ha terminado, normalmente porque se perdió la conexión. Ejecutar terraform apply de nuevo reanuda la espera y no realiza un nuevo pedido. Si la factura no está pagada, pá gala y ejecuta terraform apply de nuevo. El estado en vivo del servicio se muestra en el panel de control.
Información
Puedes encontrar más información sobre Terraform en la documentación oficial de HashiCorp, y los argumentos específicos de los recursos y fuentes de datos están documentados en el Terraform Registry.