¿Qué es el Terraform Registry?

El Terraform Registry (registry.terraform.io) es el repositorio central y oficial del ecosistema Terraform. Funciona como un hub de distribución donde desarrolladores, empresas y la propia HashiCorp publican módulos de Terraform listos para usar.

Puedes pensar en él como el equivalente de npm para Node.js o PyPI para Python, pero especializado en infraestructura como código. En el registry encontrarás:

  • Providers: los plugins que permiten a Terraform interactuar con APIs (AWS, Azure, GCP, Kubernetes, etc.)
  • Módulos: conjuntos de recursos preconfigurados y reutilizables

Cuando visitas el registry, lo primero que notas es que los módulos están organizados por el proveedor de nube con el que trabajan. Esto facilita enormemente la búsqueda cuando sabes qué plataforma estás usando.

Acceso al registry

# El registry es accesible públicamente sin autenticación para módulos públicos
# URL principal:
# https://registry.terraform.io

# Buscar módulos via CLI (necesita Terraform instalado)
# No hay comando CLI directo para buscar, pero sí puedes ver info de un módulo:
terraform providers

# O usar la API del registry:
curl https://registry.terraform.io/v1/modules/terraform-aws-modules/vpc/aws

Módulos oficiales vs módulos de la comunidad

Existe una distinción importante entre los tipos de módulos disponibles:

Módulos verificados por HashiCorp (Verified)

Son módulos creados y mantenidos por socios tecnológicos de HashiCorp (AWS, Google, Microsoft, etc.) o por la propia HashiCorp. Se identifican con un escudo azul de verificación en el registry.

Características:

  • Mantenidos activamente por organizaciones de confianza
  • Siguen las mejores prácticas de Terraform
  • Tienen documentación completa
  • Son revisados por HashiCorp antes de recibir el badge
  • Ejemplo: terraform-aws-modules/vpc/aws (mantenido por Anton Babenko, socio verificado)

Módulos de la comunidad (Community)

Creados y mantenidos por la comunidad open source. No tienen el escudo de verificación pero pueden ser igual de útiles y fiables.

Características:

  • Calidad variable (depende del mantenedor)
  • Pueden no estar actualizados con versiones recientes de Terraform o providers
  • Algunos tienen una comunidad muy activa y muchas estrellas en GitHub
  • Requieren más evaluación por parte del usuario
Criterio Módulos verificados Módulos de la comunidad
Mantenedor Partner de HashiCorp Cualquier desarrollador
Badge en registry Escudo azul No
Confiabilidad Alta Variable
Actualizaciones Frecuentes Depende del autor
Soporte Documentado Issues en GitHub
Cantidad disponible Limitada (alta calidad) Muy amplia
Recomendado para producción Si, como punto de partida Con evaluación previa

Cómo buscar y evaluar módulos en registry.terraform.io

Búsqueda en el registry

El registry ofrece búsqueda por texto libre y filtros:

  1. Ve a registry.terraform.io/browse/modules
  2. Usa la barra de búsqueda con términos como "vpc", "s3", "kubernetes"
  3. Filtra por provider (aws, google, azurerm, kubernetes...)
  4. Filtra por verified para ver solo módulos verificados

Información disponible en cada módulo

Al acceder a la página de un módulo verás:

  • Readme: documentación principal del módulo
  • Inputs: todas las variables de entrada con tipos y descripciones
  • Outputs: todos los valores que el módulo expone
  • Dependencies: providers y versiones requeridas
  • Resources: lista de recursos que el módulo gestiona (muy útil para entender qué crea)
  • Submodules: módulos adicionales dentro del mismo repositorio
  • Examples: ejemplos de uso

Criterios para elegir un módulo

Antes de usar un módulo externo en producción, evalúa estos factores:

  1. Actividad de mantenimiento

# Comprueba en GitHub:
# - Último commit: ¿fue hace menos de 6 meses?
# - Issues abiertos: ¿hay muchos sin respuesta?
# - Pull requests: ¿se revisan y fusionan con regularidad?
# - Releases: ¿hay versiones recientes?

  1. Número de descargas y popularidad

En el registry, los módulos más populares tienen más ojos encima y los bugs se detectan antes. Un módulo con millones de descargas es señal de confianza.

  1. Versiones publicadas y semver

Un módulo que sigue el versionado semántico correctamente indica madurez. Desconfía de módulos que solo tienen versión 0.x.x o que nunca han publicado releases.

  1. Documentación

¿Tiene README? ¿Están documentadas todas las variables? ¿Hay ejemplos? La calidad de la documentación refleja la calidad del módulo.

  1. Compatibilidad con tu versión de Terraform

# Verifica el bloque terraform en el módulo:
terraform {
  required_version = ">= 1.3"  # ¿Es compatible con tu versión?
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.0"       # ¿Es compatible con tu versión del provider?
    }
  }
}

  1. Licencia

La mayoría de módulos usan MIT o Apache 2.0, que permiten uso comercial. Verifica que la licencia es compatible con tu uso.

Checklist de evaluación

Criterio Cómo verificar Señal positiva
Ultimo commit GitHub → commits Menos de 6 meses
Issues sin respuesta GitHub → Issues Menos del 20% sin respuesta
Estrellas en GitHub GitHub → Stars Más de 100 para módulos relevantes
Versiones publicadas Registry → Versions Versión >= 1.0.0 con historial
Badge verificado Registry → Verified Presente
Documentación completa Registry → Readme Readme + Inputs + Outputs documentados
Tests automatizados GitHub → .github/workflows CI/CD configurado
Ejemplos Registry → Examples Al menos 1 ejemplo funcional
Licencia permisiva GitHub → LICENSE MIT, Apache 2.0, MPL 2.0

Módulos verificados de HashiCorp

Los módulos verificados son la primera opción a considerar. Aquí tienes los más usados:

Módulo Proveedor Fuente en registry
VPC (Virtual Private Cloud) AWS terraform-aws-modules/vpc/aws
EC2 Instance AWS terraform-aws-modules/ec2-instance/aws
RDS (Base de datos) AWS terraform-aws-modules/rds/aws
EKS (Kubernetes) AWS terraform-aws-modules/eks/aws
S3 Bucket AWS terraform-aws-modules/s3-bucket/aws
Lambda Function AWS terraform-aws-modules/lambda/aws
Virtual Network Azure Azure/vnet/azurerm
AKS (Kubernetes) Azure Azure/aks/azurerm
VPC Network GCP terraform-google-modules/network/google
GKE (Kubernetes) GCP terraform-google-modules/kubernetes-engine/google

Requisitos para publicar un módulo en el registry

Para publicar un módulo en el Terraform Registry público, debes cumplir estos requisitos:

Requisitos técnicos

  1. Repositorio en GitHub: el código debe estar en un repositorio público de GitHub.

  2. Nombre del repositorio: debe seguir el formato terraform-<provider>-<nombre>:

    terraform-aws-vpc
    terraform-google-network
    terraform-azurerm-compute
    
  3. Estructura de archivos mínima:

    terraform-aws-mi-modulo/
    ├── main.tf        # Obligatorio
    ├── variables.tf   # Obligatorio
    ├── outputs.tf     # Obligatorio
    └── README.md      # Obligatorio (con descripción y uso)
    
  4. Releases con tags de GitHub: las versiones se detectan automáticamente a partir de los tags de GitHub que sigan el formato semver (con v opcional):

    git tag v1.0.0
    git push origin v1.0.0
    
  5. Provider declarado: el main.tf debe incluir el bloque terraform con required_providers.

Proceso de publicación

El proceso es automático una vez conectas tu cuenta de GitHub al registry:

# Pasos para publicar:

# 1. Crea el repositorio con el nombre correcto
# terraform-aws-mi-servidor (ejemplo)

# 2. Desarrolla el módulo con la estructura correcta

# 3. Crea una cuenta en registry.terraform.io y conecta GitHub

# 4. El registry detecta automáticamente el repositorio por el nombre

# 5. Publica el módulo desde la interfaz del registry

# 6. Crea tags para las versiones:
git tag v1.0.0
git push origin v1.0.0
# El registry detecta el tag y publica la versión automáticamente

# Para versiones posteriores:
git tag v1.1.0
git push origin v1.1.0

Estructura de nomenclatura: terraform-provider-nombre

La convención de nombres terraform-<provider>-<nombre> no es solo un requisito del registry; comunica información importante sobre el módulo:

terraform-aws-vpc
│        │   │
│        │   └── Función/componente: qué hace el módulo
│        └────── Provider: con qué cloud/tecnología trabaja
└─────────────── Prefijo: siempre "terraform" para módulos publicables

Ejemplos de buenos nombres

terraform-aws-vpc              # VPC en Amazon Web Services
terraform-google-gke           # Google Kubernetes Engine en GCP
terraform-azurerm-aks          # Azure Kubernetes Service en Azure
terraform-kubernetes-nginx     # NGINX en Kubernetes
terraform-github-repository    # Repositorios en GitHub

Nombres para módulos internos (no publicados)

Para módulos internos de empresa que no se publicarán en el registry, la convención es más flexible:

modules/
├── networking/        # Kebab-case o snake_case
├── compute-web/
├── database_rds/
└── security-groups/

Publicar tu propio módulo: proceso paso a paso

Vamos a ver el proceso completo para publicar un módulo real:

Paso 1: Preparar el repositorio

# Crear el repositorio con el nombre correcto
# En GitHub: New repository → nombre: terraform-local-proyecto

# Clonar el repositorio
git clone https://github.com/tu-usuario/terraform-local-proyecto.git
cd terraform-local-proyecto

Paso 2: Crear la estructura del módulo

# Crear los archivos necesarios
touch main.tf variables.tf outputs.tf README.md
mkdir -p examples/basico
touch examples/basico/main.tf examples/basico/README.md

Paso 3: Implementar el módulo

# main.tf
terraform {
  required_version = ">= 1.0"
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
}

resource "local_file" "proyecto" {
  filename        = "${var.directorio}/${var.nombre}.conf"
  content         = var.contenido
  file_permission = var.permisos
}
# variables.tf
variable "nombre" {
  description = "Nombre del archivo de configuración del proyecto."
  type        = string
}

variable "directorio" {
  description = "Directorio destino donde se creará el archivo."
  type        = string
}

variable "contenido" {
  description = "Contenido del archivo de configuración."
  type        = string
  default     = "# Configuración generada por Terraform"
}

variable "permisos" {
  description = "Permisos del archivo en formato octal."
  type        = string
  default     = "0644"
}
# outputs.tf
output "ruta_archivo" {
  description = "Ruta completa del archivo de configuración creado."
  value       = local_file.proyecto.filename
}

output "contenido_guardado" {
  description = "Contenido guardado en el archivo."
  value       = local_file.proyecto.content
}
# examples/basico/main.tf
module "mi_proyecto" {
  source = "../.."   # Apunta al módulo raíz del repositorio

  nombre     = "mi-aplicacion"
  directorio = "/tmp/configs"
  contenido  = "servidor=localhost\npuerto=8080"
}

output "config_creada" {
  value = module.mi_proyecto.ruta_archivo
}

Paso 4: Documentar con README.md

# terraform-local-proyecto

Módulo de Terraform para gestionar archivos de configuración de proyectos.

## Uso

module "config" { source = "tu-usuario/proyecto/local" version = "~> 1.0"

nombre = "mi-app" directorio = "/etc/mi-app" contenido = "puerto=8080\ndebug=false" }

## Variables de entrada

| Variable | Tipo | Obligatoria | Default | Descripción |
|---|---|---|---|---|
| nombre | string | Sí | - | Nombre del archivo |
| directorio | string | Sí | - | Directorio destino |
| contenido | string | No | Comentario | Contenido del archivo |
| permisos | string | No | "0644" | Permisos del archivo |

## Outputs

| Output | Descripción |
|---|---|
| ruta_archivo | Ruta completa del archivo creado |
| contenido_guardado | Contenido guardado |

Paso 5: Publicar la primera versión

# Commitear todos los cambios
git add .
git commit -m "feat: implementación inicial del módulo"
git push origin main

# Crear el primer tag de versión
git tag v1.0.0
git push origin v1.0.0

# Ahora en registry.terraform.io:
# 1. Sign in with GitHub
# 2. Publish → Module
# 3. Seleccionar el repositorio "terraform-local-proyecto"
# 4. ¡El registry lo detecta automáticamente!

Paso 6: Publicar actualizaciones

# Desarrollar el cambio
# ... modificar archivos ...

# Commitear con mensaje descriptivo siguiendo convenciones
git add .
git commit -m "feat: añadir soporte para permisos de directorio"
git push origin main

# Crear nuevo tag (versión MENOR porque es nueva funcionalidad)
git tag v1.1.0
git push origin v1.1.0
# El registry detecta el tag y publica la nueva versión automáticamente

Módulos privados en Terraform Cloud/Enterprise

Si tu organización necesita módulos privados (que no sean públicos), Terraform Cloud y Terraform Enterprise ofrecen un Private Registry:

Características del Private Registry

  • Los módulos solo son accesibles para miembros de tu organización en Terraform Cloud
  • Mismo flujo de publicación que el registry público pero con autenticación
  • Integración con VCS privados (GitHub Enterprise, GitLab, Bitbucket Server)
  • Control de acceso por equipo (RBAC)

Configurar acceso al Private Registry

# Para usar módulos del registry privado, configura las credenciales
# en el CLI de Terraform:

# 1. Obtener un token de API de Terraform Cloud
# app.terraform.io → User Settings → Tokens

# 2. Configurar el token localmente
terraform login app.terraform.io
# Abre el navegador para autenticación

# 3. Usar el módulo privado en tu configuración
module "mi_modulo_privado" {
  source  = "app.terraform.io/mi-organizacion/nombre-modulo/provider"
  version = "~> 1.0"

  # Variables del módulo
  variable_1 = "valor"
}

Flujo de trabajo con módulos privados

# Los módulos privados se publican desde VCS (GitHub Enterprise, GitLab, etc.)
# Proceso en Terraform Cloud:

# 1. Navega a: app.terraform.io → Registry → Publish Module
# 2. Conecta tu VCS provider
# 3. Selecciona el repositorio del módulo
# 4. El naming sigue la misma convención: terraform-<provider>-<nombre>
# 5. Los tags de git crean versiones automáticamente

# Para equipos que no pueden usar git tags directamente,
# Terraform Cloud Enterprise permite publicar via API:
curl \
  --header "Authorization: Bearer $TOKEN" \
  --header "Content-Type: application/vnd.api+json" \
  --request POST \
  --data @module.json \
  "https://app.terraform.io/api/v2/organizations/mi-org/registry-modules"

Tabla de módulos populares por proveedor

Amazon Web Services (AWS)

Módulo Descripción Fuente
VPC Red privada virtual completa terraform-aws-modules/vpc/aws
EC2 Instance Instancias de servidor terraform-aws-modules/ec2-instance/aws
RDS Bases de datos relacionales terraform-aws-modules/rds/aws
S3 Bucket Almacenamiento de objetos terraform-aws-modules/s3-bucket/aws
EKS Kubernetes gestionado terraform-aws-modules/eks/aws
Lambda Funciones serverless terraform-aws-modules/lambda/aws
ALB Load balancer de aplicación terraform-aws-modules/alb/aws
IAM Gestión de identidad terraform-aws-modules/iam/aws
CloudFront CDN y distribución de contenido terraform-aws-modules/cloudfront/aws

Microsoft Azure

Módulo Descripción Fuente
Virtual Network Red virtual de Azure Azure/vnet/azurerm
AKS Kubernetes gestionado Azure/aks/azurerm
Compute Máquinas virtuales Azure/compute/azurerm
Storage Account Almacenamiento Azure/storage/azurerm

Google Cloud Platform (GCP)

Módulo Descripción Fuente
Network VPC y subredes terraform-google-modules/network/google
GKE Kubernetes gestionado terraform-google-modules/kubernetes-engine/google
Cloud SQL Bases de datos GoogleCloudPlatform/sql-db/google
IAM Permisos y roles terraform-google-modules/iam/google

Kubernetes y contenedores

Módulo Descripción Fuente
Helm Release Deployar charts de Helm registry.terraform.io/modules/...
Kubernetes Manifests Aplicar manifiestos Múltiples autores

Ejemplo: usar el módulo terraform-aws-modules/vpc/aws

Este es el módulo de VPC más utilizado en el ecosistema Terraform para AWS. Vamos a ver un ejemplo completo y explicado:

# main.tf

terraform {
  required_version = ">= 1.3"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# Configuración del provider AWS
provider "aws" {
  region = "eu-west-1"   # Irlanda

  # En producción, las credenciales se gestionan via:
  # - Variables de entorno: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
  # - IAM Role (en EC2 o ECS)
  # - AWS SSO / Identity Center
  # NUNCA las hardcodees en el código
}

# ============================================================
# Datos de contexto: obtenemos información de la cuenta AWS
# ============================================================

# data sources obtienen información existente (no crean recursos)
data "aws_availability_zones" "disponibles" {
  # Filtra por estado: solo zonas "available" (activas)
  state = "available"
}

# ============================================================
# Módulo VPC: crea la red completa
# ============================================================

module "vpc_produccion" {
  # source: identificador único del módulo en el registry
  # Formato: <namespace>/<nombre>/<provider>
  source = "terraform-aws-modules/vpc/aws"

  # version: SIEMPRE especificar. ~> 5.0 acepta 5.x.x pero no 6.x.x
  version = "~> 5.0"

  # --- Configuración básica ---

  # Nombre de la VPC (se usa para nombrar todos los recursos internos)
  name = "vpc-produccion"

  # Bloque CIDR de la VPC: rango de IPs de toda la red
  cidr = "10.0.0.0/16"   # 65,536 IPs disponibles

  # --- Zonas de disponibilidad y subredes ---

  # Usamos las 3 primeras AZs disponibles en la región
  # slice() toma los primeros N elementos de una lista
  azs = slice(data.aws_availability_zones.disponibles.names, 0, 3)

  # Subredes privadas: recursos internos (bases de datos, workers)
  # No tienen acceso directo desde internet
  # Una subred por AZ = alta disponibilidad
  private_subnets = [
    "10.0.1.0/24",   # 256 IPs en AZ-a
    "10.0.2.0/24",   # 256 IPs en AZ-b
    "10.0.3.0/24",   # 256 IPs en AZ-c
  ]

  # Subredes públicas: recursos accesibles desde internet (load balancers, bastiones)
  public_subnets = [
    "10.0.101.0/24",  # 256 IPs en AZ-a
    "10.0.102.0/24",  # 256 IPs en AZ-b
    "10.0.103.0/24",  # 256 IPs en AZ-c
  ]

  # Subredes de base de datos: aisladas, sin acceso a internet
  # (Buena práctica de seguridad: bases de datos en su propia subred)
  database_subnets = [
    "10.0.201.0/24",
    "10.0.202.0/24",
    "10.0.203.0/24",
  ]

  # --- Conectividad a internet ---

  # Internet Gateway: permite a las subredes PÚBLICAS acceder a internet
  # Se crea automáticamente cuando hay public_subnets
  # (No es necesario configurarlo explícitamente)

  # NAT Gateway: permite a las subredes PRIVADAS acceder a internet (salida)
  # pero el tráfico entrante desde internet no puede llegar a ellas
  enable_nat_gateway = true

  # single_nat_gateway = true: UN SOLO NAT para todas las AZs
  # Ventaja: más económico (~$32/mes vs ~$96/mes por 3 NATs)
  # Desventaja: punto único de fallo (si esa AZ falla, las privadas pierden internet)
  # En PRODUCCIÓN real: usa one_nat_gateway_per_az = true
  single_nat_gateway = true

  # --- DNS ---

  # Habilitar resolución DNS en la VPC (necesario para muchos servicios AWS)
  enable_dns_hostnames = true
  enable_dns_support   = true

  # --- Configuración de base de datos ---

  # Crea un "DB subnet group": agrupación de subredes para RDS
  # Necesario si vas a usar el módulo RDS posteriormente
  create_database_subnet_group = true

  # --- Etiquetas ---

  # Tags aplicados a TODOS los recursos que crea el módulo
  tags = {
    Entorno    = "produccion"
    Proyecto   = "tienda-online"
    GestionPor = "terraform"
    Equipo     = "infraestructura"
  }

  # Tags adicionales solo para las subredes públicas
  public_subnet_tags = {
    "kubernetes.io/role/elb" = "1"  # Necesario para AWS Load Balancer Controller en EKS
  }

  # Tags adicionales solo para las subredes privadas
  private_subnet_tags = {
    "kubernetes.io/role/internal-elb" = "1"  # Para load balancers internos en EKS
  }
}

# ============================================================
# Outputs: exponemos información de la VPC para otros módulos
# ============================================================

output "vpc_id" {
  description = "ID de la VPC creada"
  value       = module.vpc_produccion.vpc_id
}

output "subredes_privadas" {
  description = "IDs de las subredes privadas"
  value       = module.vpc_produccion.private_subnets
}

output "subredes_publicas" {
  description = "IDs de las subredes públicas"
  value       = module.vpc_produccion.public_subnets
}

output "subredes_base_datos" {
  description = "IDs de las subredes de base de datos"
  value       = module.vpc_produccion.database_subnets
}

output "cidr_vpc" {
  description = "Bloque CIDR de la VPC"
  value       = module.vpc_produccion.vpc_cidr_block
}

Verificar qué recursos crea este módulo:

# Inicializar
terraform init

# Ver el plan (sin aplicar)
terraform plan

# El módulo vpc crea aproximadamente:
# - 1 VPC
# - 9 subredes (3 privadas + 3 públicas + 3 de BD)
# - 1 Internet Gateway
# - 1 NAT Gateway + 1 Elastic IP
# - 3 Route tables (1 pública, 1 privada, 1 de BD)
# - 1 DB Subnet Group
# - Varias asociaciones de route tables
# Total: ~25-30 recursos con una sola llamada al módulo

Ejercicio: Encontrar, evaluar y usar un módulo del registry

Objetivo: Aplicar los criterios de evaluación aprendidos para seleccionar un módulo del registry.

Contexto: Tu equipo necesita gestionar múltiples repositorios de GitHub usando Terraform. Debes:

  1. Buscar en registry.terraform.io módulos para gestionar repositorios de GitHub.
  2. Evaluar los resultados según los criterios vistos.
  3. Usar el módulo seleccionado para crear una configuración que gestione 2 repositorios.

Criterios de evaluación que debes documentar:

  • ¿Tiene badge verificado?
  • ¿Cuándo fue el último commit?
  • ¿Cuántas versiones tiene publicadas?
  • ¿La documentación es completa?
  • ¿Tiene ejemplos?

Solución y criterios de evaluación

Evaluación del módulo

Buscando "github repository" en el registry, encontramos el provider oficial de GitHub que incluye recursos directos (sin módulo de terceros necesario). Para repositorios GitHub, lo habitual es usar el provider integrations/github directamente:

# Buscar en el registry:
# 1. Ve a registry.terraform.io
# 2. Busca "github"
# 3. Selecciona el provider "integrations/github"

Para este ejercicio, crearemos un módulo local que encapsula la creación de repositorios GitHub:

Configuración con el provider de GitHub

# main.tf

terraform {
  required_version = ">= 1.0"

  required_providers {
    # Provider oficial de GitHub (mantenido por Integrations, socio de HashiCorp)
    github = {
      source  = "integrations/github"
      version = "~> 6.0"
    }
  }
}

# Configuración del provider de GitHub
provider "github" {
  # El token se pasa via variable de entorno: GITHUB_TOKEN
  # Nunca lo pongas aquí en el código
  # export GITHUB_TOKEN="ghp_tu_token_aqui"

  owner = "tu-organizacion"  # o tu usuario de GitHub
}

# ============================================================
# Crear repositorios usando el provider directamente
# (sin módulo del registry porque no hay uno verificado ampliamente)
# ============================================================

locals {
  # Definir los repositorios como mapa para usar for_each
  repositorios = {
    "api-backend" = {
      descripcion  = "API REST del backend de la aplicación"
      privado      = true
      auto_init    = true
      topics       = ["api", "backend", "rest"]
    }
    "frontend-web" = {
      descripcion  = "Aplicación web del frontend"
      privado      = false
      auto_init    = true
      topics       = ["frontend", "web", "react"]
    }
  }
}

# Crear los repositorios con for_each
resource "github_repository" "repos" {
  for_each = local.repositorios

  # Nombre del repositorio
  name = each.key

  # Descripción visible en GitHub
  description = each.value.descripcion

  # Visibilidad del repositorio
  visibility = each.value.privado ? "private" : "public"

  # Inicializar con README.md automáticamente
  auto_init = each.value.auto_init

  # Topics (etiquetas) del repositorio
  topics = each.value.topics

  # Configuración de branches
  has_issues   = true
  has_wiki     = false
  has_projects = false

  # Configuración de merge: solo squash y merge commits, no merge commits directos
  allow_squash_merge     = true
  allow_merge_commit     = false
  allow_rebase_merge     = true
  delete_branch_on_merge = true  # eliminar rama al hacer merge de PR
}

# Proteger la rama main en todos los repositorios
resource "github_branch_protection" "main" {
  for_each = local.repositorios

  repository_id = github_repository.repos[each.key].node_id
  pattern       = "main"

  # Requerir pull requests antes de hacer merge
  required_pull_request_reviews {
    dismiss_stale_reviews           = true
    required_approving_review_count = 1
  }

  # Requerir que los checks de CI pasen
  required_status_checks {
    strict = true  # los checks deben ejecutarse sobre la versión más reciente
  }

  # No permitir forzar push a main
  force_push_bypassers  = []
}

# Outputs
output "urls_repositorios" {
  description = "URLs de los repositorios creados en GitHub"
  value = {
    for k, v in github_repository.repos : k => v.html_url
  }
}

output "ssh_clone_urls" {
  description = "URLs SSH para clonar los repositorios"
  value = {
    for k, v in github_repository.repos : k => v.ssh_clone_url
  }
}

Criterios de evaluación aplicados (guía de puntuación)

Criterio Puntuación máxima Descripción
Mantenimiento activo 25 pts Commits en los últimos 3 meses: 25pts; 6 meses: 15pts; más: 5pts
Versiones publicadas 20 pts v1.0+ con historial: 20pts; solo v0.x: 10pts; sin releases: 0pts
Documentación 20 pts README + inputs + outputs documentados: 20pts; parcial: 10pts
Badge verificado 15 pts Verificado: 15pts; no verificado: 0pts
Ejemplos funcionales 10 pts Al menos 1 ejemplo: 10pts; ninguno: 0pts
Tests automatizados 10 pts CI/CD visible: 10pts; ninguno: 0pts

Un módulo con más de 70/100 puntos es una opción razonable para producción.


Errores comunes al trabajar con el registry

Error 1: No bloquear la versión del módulo

# PELIGROSO: sin versión
module "vpc" {
  source = "terraform-aws-modules/vpc/aws"
  # Si sale una versión 6.0 con breaking changes, terraform init la usará
}

# CORRECTO: versión bloqueada
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"
}

Error 2: Confiar ciegamente en módulos no verificados

Siempre verifica el código fuente de un módulo antes de usarlo en producción. Los módulos pueden crear recursos costosos o con configuraciones inseguras. Usa el enlace "Source Code" en el registry para ver el repositorio GitHub.

Error 3: Usar la misma versión de módulo en todos los entornos

En algunos casos puede ser útil probar una nueva versión en staging antes de actualizarla en producción:

# staging/main.tf
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.1"   # Probando nueva versión menor
}

# produccion/main.tf
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"   # Versión probada y estable
}

Error 4: No leer el CHANGELOG antes de actualizar

Antes de ejecutar terraform get -update, revisa el CHANGELOG del módulo en GitHub para identificar breaking changes o cambios de comportamiento importantes.

Error 5: Publicar módulos con información sensible

Si publicas un módulo en el registry público, asegúrate de que no contiene:

  • Credenciales hardcodeadas
  • IDs de recursos específicos de tu cuenta
  • Configuraciones internas de tu empresa
  • Variables con valores por defecto que sean secretos

Resumen del módulo 4

Has completado el módulo 4 del curso, que cubre todo el ciclo de vida de los módulos de Terraform. Hagamos un repaso de lo aprendido:

Tema 4-01: Introducción a los módulos

  • Un módulo es un directorio de archivos .tf que encapsula infraestructura reutilizable.
  • El módulo raíz vs módulos secundarios y cómo se relacionan.
  • Los tipos de fuentes de módulos: local, registry, Git, S3.
  • La regla de los 3 para decidir cuándo extraer código en un módulo.

Tema 4-02: Creando módulos

  • La estructura estándar: main.tf, variables.tf, outputs.tf, versions.tf, README.md.
  • Cómo declarar variables con tipos, descripciones, validaciones y valores sensitive.
  • Cómo definir outputs y agruparlos en objetos.
  • Principios de diseño: responsabilidad única, interfaz mínima.
  • Versionado semántico para módulos.

Tema 4-03: Usando módulos

  • La sintaxis del bloque module y sus argumentos especiales.
  • Todos los formatos del argumento source.
  • Cómo pasar variables y acceder a outputs.
  • Uso de count y for_each con módulos.
  • Los operadores de versión: ~>, >=, !=, etc.
  • Diferencia entre terraform init y terraform get.

Tema 4-04: El Terraform Registry

  • Qué es el registry y la diferencia entre módulos verificados y de comunidad.
  • Criterios para evaluar módulos externos antes de usarlos en producción.
  • Los módulos más populares por proveedor de cloud.
  • Requisitos y proceso para publicar un módulo propio.
  • Módulos privados en Terraform Cloud/Enterprise.

Próximos pasos

Con el conocimiento de módulos bien consolidado, estás listo para abordar el Módulo 5: Provisionamiento de Infraestructura, donde aprenderás a crear recursos reales en AWS, Azure y GCP, y cómo combinar todos los conceptos vistos (variables, state, módulos) en proyectos de infraestructura completos y listos para producción.

Los módulos son el corazón de Terraform a escala. A medida que tu experiencia crezca, desarrollar una biblioteca de módulos internos de alta calidad se convertirá en una de tus tareas más valiosas como ingeniero de infraestructura.

© Copyright 2026. Todos los derechos reservados