Práctica Final del módulo AWS de KeepCoding
Despliegue de un website estático en Amazon S3 usando Terraform como Infrastructure as Code (IaC)
- Descripción
- Arquitectura
- Requisitos Previos
- Instalación
- Despliegue
- Verificación
- Limpieza
- Personalización
- Estructura del Proyecto
- Troubleshooting
- FAQs
Este proyecto despliega automáticamente una web estática en Amazon S3 utilizando Terraform. La infraestructura se crea en la región de Irlanda (eu-west-1) y está configurada para servir contenido HTML públicamente a través de HTTP.
- ✅ Infraestructura como Código con Terraform
- ✅ Despliegue automatizado en AWS S3
- ✅ Web estática funcional con páginas personalizadas
- ✅ Acceso público configurado correctamente
- ✅ Página de error 404 personalizada
- ✅ Código modularizado siguiendo best practices
- ✅ Documentación completa
┌────────────────────────────────────────────────┐
│ │
│ REGIÓN: eu-west-1 │
│ (Irlanda) │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ Amazon S3 Bucket │ │
│ │ ┌────────────────────────────────────┐ │ │
│ │ │ Static Website Hosting │ │ │
│ │ │ • index.html (página principal) │ │ │
│ │ │ • error.html (página 404) │ │ │
│ │ │ • Acceso público configurado │ │ │
│ │ └────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────┘ │
│ ▲ │
└────────────────────────┼───────────────────────┘
│
Petición HTTP
│
┌────────┴────────┐
│ Navegador │
│ (Usuario) │
└─────────────────┘
| Componente | Descripción |
|---|---|
| AWS S3 | Bucket configurado como static website hosting |
| Terraform | IaC para automatizar el despliegue |
| HTML/CSS | Páginas web estáticas |
| Región | eu-west-1 (Irlanda) |
| Acceso | Público vía HTTP |
Antes de comenzar, asegúrate de tener instalado y configurado lo siguiente:
Versión requerida: >= 1.0
Linux (Ubuntu/Debian):
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 terraformVerificar instalación:
terraform --version
# Debería mostrar: Terraform v1.x.xVersión requerida: >= 2.0
Linux:
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/installVerificar instalación:
aws --version
# Debería mostrar: aws-cli/2.x.xNecesitas una cuenta de AWS activa con:
- Acceso programático (Access Key ID y Secret Access Key)
- Permisos necesarios:
s3:CreateBuckets3:PutObjects3:PutBucketPolicys3:PutBucketWebsites3:PutBucketPublicAccessBlocks3:DeleteBuckets3:DeleteObject
Para clonar el repositorio:
git --versionaws configureTe pedirá:
AWS Access Key ID [None]: TU_ACCESS_KEY_ID
AWS Secret Access Key [None]: TU_SECRET_ACCESS_KEY
Default region name [None]: eu-west-1
Default output format [None]: json
export AWS_ACCESS_KEY_ID="tu_access_key"
export AWS_SECRET_ACCESS_KEY="tu_secret_key"
export AWS_DEFAULT_REGION="eu-west-1"aws sts get-caller-identityDeberías ver tu Account ID y ARN.
# Clonar el repositorio
git clone https://github.com/jpalenz77/KC_AWS_Practica-Final_Jose-Palenzuela.git
# Entrar al directorio
cd KC_AWS_Practica-Final_Jose-Palenzuela# Listar archivos
ls -la
# Deberías ver:
# provider.tf
# variables.tf
# s3_bucket.tf
# s3_objects.tf
# outputs.tf
# terraform.tfvars.example
# .gitignore
# README.md
# website/
# ├── index.html
# └── error.htmlSi quieres cambiar la configuración por defecto:
# Renombrar el archivo de ejemplo
mv terraform.tfvars.example terraform.tfvars
# Editar con tu editor favorito
nano terraform.tfvarsEjemplo de personalización:
aws_region = "eu-west-1" # Cambiar si quieres otra región
bucket_prefix = "mi-web-personalizada" # Cambiar el prefijo del bucket
project_name = "Mi Proyecto AWS" # Cambiar el nombre del proyecto💡 Nota: Si no creas el archivo
terraform.tfvars, se usarán los valores por defecto devariables.tf
Este comando descarga los providers necesarios (AWS y Random):
terraform initSalida esperada:
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Finding hashicorp/random versions matching "~> 3.5"...
- Installing hashicorp/aws v5.x.x...
- Installing hashicorp/random v3.x.x...
Terraform has been successfully initialized!
Verifica que no haya errores de sintaxis:
terraform validateSalida esperada:
Success! The configuration is valid.
Revisa qué recursos se crearán sin aplicar cambios:
terraform planDeberías ver:
Plan: 7 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ bucket_arn = (known after apply)
+ bucket_name = (known after apply)
+ region = "eu-west-1"
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
Despliega la infraestructura:
terraform applySe te pedirá confirmación:
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
Escribe yes y presiona Enter.
Proceso de despliegue (1-2 minutos):
random_id.bucket_suffix: Creating...
random_id.bucket_suffix: Creation complete after 0s
aws_s3_bucket.static_website: Creating...
aws_s3_bucket.static_website: Creation complete after 2s
aws_s3_bucket_website_configuration.static_website_config: Creating...
aws_s3_bucket_public_access_block.static_website_pab: Creating...
...
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
Al finalizar, verás los outputs:
Outputs:
bucket_arn = "arn:aws:s3:::bucket-practica-final-aws-a1b2c3d4"
bucket_name = "bucket-practica-final-aws-a1b2c3d4"
region = "eu-west-1"
website_domain = "bucket-practica-final-aws-a1b2c3d4.s3-website-eu-west-1.amazonaws.com"
website_endpoint = "http://bucket-practica-final-aws-a1b2c3d4.s3-website-eu-west-1.amazonaws.com"
🎉 ¡Tu website está desplegado!
Copia la URL de website_endpoint y ábrela en tu navegador.
# Abrir automáticamente (macOS)
open $(terraform output -raw website_endpoint)
# Abrir automáticamente (Linux)
xdg-open $(terraform output -raw website_endpoint)
# Abrir automáticamente (Windows - PowerShell)
Start-Process (terraform output -raw website_endpoint)O copia manualmente la URL del output website_endpoint
# Probar página principal
curl $(terraform output -raw website_endpoint)
# Probar página de error 404
curl $(terraform output -raw website_endpoint)/pagina-inexistente- Ve a: https://console.aws.amazon.com/s3/
- Busca el bucket con prefijo
bucket-practica-final-aws- - Ve a la pestaña Properties → Static website hosting
- Verifica que esté Enabled
# Ver todos los outputs
terraform output
# Ver solo el endpoint
terraform output website_endpoint
# Ver sin comillas
terraform output -raw website_endpointAccede a la URL base para ver la página principal con información del despliegue:
http://bucket-practica-final-aws-XXXXXXXX.s3-website-eu-west-1.amazonaws.com
Intenta acceder a cualquier página que no existe para ver el error personalizado:
http://bucket-practica-final-aws-XXXXXXXX.s3-website-eu-west-1.amazonaws.com/no-existe
terraform destroySe te pedirá confirmación:
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value:
Escribe yes y presiona Enter.
terraform destroy -auto-approveProceso de eliminación:
aws_s3_object.error: Destroying...
aws_s3_object.index: Destroying...
aws_s3_object.error: Destruction complete after 1s
aws_s3_object.index: Destruction complete after 1s
aws_s3_bucket_policy.static_website_policy: Destroying...
...
Destroy complete! Resources: 7 destroyed.
# Verificar en AWS CLI
aws s3 ls | grep bucket-practica-final-aws
# No debería mostrar ningún bucket-
Edita los archivos en
website/:nano website/index.html nano website/error.html
-
Aplica los cambios:
terraform apply
Terraform detectará automáticamente los cambios (gracias al etag) y subirá los archivos actualizados.
Edita variables.tf o crea terraform.tfvars:
aws_region = "us-east-1" # Virginia
# o
aws_region = "eu-central-1" # FrankfurtLuego:
terraform apply-
Coloca los archivos en
website/:mkdir website/css website/js website/images cp mi-estilo.css website/css/
-
Añade recursos en
s3_objects.tf:resource "aws_s3_object" "css" { bucket = aws_s3_bucket.static_website.id key = "css/style.css" source = "website/css/style.css" content_type = "text/css" etag = filemd5("website/css/style.css") }
-
Aplica:
terraform apply
Edita terraform.tfvars:
bucket_prefix = "mi-proyecto-web"
⚠️ Esto creará un bucket nuevo. Destruye el anterior primero si ya existe.
practica_final/
│
├── 📄 provider.tf # Configuración de providers (AWS, Random)
├── 📄 variables.tf # Definición de todas las variables
├── 📄 s3_bucket.tf # Bucket S3, configuración y políticas
├── 📄 s3_objects.tf # Objetos a subir al bucket
├── 📄 outputs.tf # Outputs mostrados tras el despliegue
├── 📄 terraform.tfvars.example # Ejemplo de valores de variables
├── 📄 .gitignore # Archivos a ignorar en Git
├── 📄 README.md # Esta documentación
│
└── 📁 website/ # Contenido del sitio web
├── 📄 index.html # Página principal
└── 📄 error.html # Página de error 404
| Archivo | Propósito |
|---|---|
provider.tf |
Define los providers de Terraform (AWS y Random) y sus versiones |
variables.tf |
Declara todas las variables configurables del proyecto |
s3_bucket.tf |
Crea el bucket S3 y configura el website hosting, acceso público y políticas |
s3_objects.tf |
Sube los archivos HTML al bucket |
outputs.tf |
Define qué información se muestra después del despliegue |
terraform.tfvars.example |
Plantilla para personalizar variables (opcional) |
.gitignore |
Excluye archivos sensibles y temporales de Git |
Problema: El nombre del bucket ya existe (los nombres son únicos globalmente).
Solución:
# Cambiar el prefijo en terraform.tfvars
bucket_prefix = "mi-nombre-unico-123"
# Aplicar de nuevo
terraform applyProblema: Credenciales AWS incorrectas o sin permisos.
Solución:
# Verificar credenciales
aws sts get-caller-identity
# Reconfigurar
aws configureProblema: Los archivos HTML no están en la ubicación correcta.
Solución:
# Verificar estructura
ls -R
# Debe existir:
# website/index.html
# website/error.html
# Si no existen, créalos o clona el repo de nuevoPosibles causas:
- Propagación en curso → Espera 1-2 minutos
- Caché del navegador → Usa modo incógnito (Ctrl+Shift+N)
- URL incorrecta → Verifica que copies toda la URL del output
Solución:
# Ver la URL exacta
terraform output website_endpoint
# Probar con curl
curl $(terraform output -raw website_endpoint)Problema: La política del bucket no está aplicada correctamente.
Solución:
# Destruir y recrear
terraform destroy
terraform applyProblema: Proceso interrumpido o lock del estado.
Solución:
# Forzar unlock (solo si estás seguro que no hay otro proceso)
terraform force-unlock LOCK_ID
# Si persiste, elimina archivos de estado local
rm .terraform.lock.hcl
rm -rf .terraform
terraform initCostos estimados (región eu-west-1):
- Almacenamiento: ~$0.023 por GB/mes
- Requests GET: ~$0.0004 por 1,000 requests
- Transferencia: Primeros 100 GB gratis/mes
Para esta práctica: < $0.05/mes (prácticamente gratis)
💡 Tip: Usa la capa gratuita de AWS (primer año).
S3 Static Website Hosting solo soporta HTTP directamente. Para HTTPS necesitas:
- Amazon CloudFront (CDN)
- AWS Certificate Manager (SSL)
Esto está fuera del scope de esta práctica básica.
Sí, pero requiere:
- Registrar un dominio (Route 53 o externo)
- Configurar Route 53 para DNS
- Opcionalmente, CloudFront para HTTPS
Público para lectura (s3:GetObject). Esto es necesario para servir el website. Los usuarios pueden ver el contenido pero no pueden:
- Listar los archivos del bucket
- Subir archivos
- Eliminar archivos
- Modificar configuración
Si no hay cambios, no hará nada:
No changes. Your infrastructure matches the configuration.
Esta es una configuración básica para aprendizaje. Para producción considera:
- ✅ Añadir CloudFront para HTTPS y CDN
- ✅ Configurar logging del bucket
- ✅ Habilitar versioning
- ✅ Añadir backup/replicación
- ✅ Implementar CI/CD
- ✅ Usar Terraform workspaces o remote state
# 1. Edita los archivos HTML
nano website/index.html
# 2. Terraform detecta los cambios automáticamente
terraform apply
# 3. Listo! (limpia la caché del navegador si no ves cambios)