Ejecutar Scripts al Iniciar EC2: Guía Completa de User Data para Instalar Nginx Automáticamente

Acabas de lanzar una instancia EC2 y necesitas que Nginx esté instalado y corriendo sin conectarte manualmente por SSH — ese es exactamente el problema que resuelve EC2 User Data. En producción, configurar servidores manualmente es un error que escala muy mal: la automatización del arranque es la diferencia entre infraestructura reproducible y caos operacional.

TL;DR: Instalar Nginx Automáticamente con EC2 User Data

Punto claveDetalle
¿Qué es User Data?Script que EC2 ejecuta una sola vez en el primer arranque, como root
¿Dónde se configura?Consola AWS → 'Advanced Details' al lanzar la instancia, o vía CLI con --user-data
¿Cuándo se ejecuta?Solo en el primer boot (por defecto). Requiere configuración adicional para re-ejecución
¿Quién lo ejecuta?El agente cloud-init, como usuario root
¿Dónde ver los logs?/var/log/cloud-init-output.log en la instancia
Límite de tamaño16 KB para User Data sin codificar — verifica límites actuales en la documentación oficial

Cómo Funciona EC2 User Data por Dentro

Cuando lanzas una instancia EC2, el servicio cloud-init — presente en las AMIs de Amazon Linux 2, Amazon Linux 2023, Ubuntu y otras distribuciones comunes — lee el User Data desde el endpoint de metadatos de la instancia (http://169.254.169.254/latest/user-data) durante el proceso de arranque. Este endpoint es accesible únicamente desde dentro de la instancia.

El script se ejecuta con privilegios de root, una sola vez, durante la fase cloud-init del primer boot. Si el script falla a mitad de ejecución, la instancia arranca de todas formas — cloud-init no bloquea el arranque por errores del script de usuario. Esto significa que puedes tener una instancia 'running' con Nginx sin instalar y sin ninguna alerta visible en la consola.

graph TD A["EC2 Launch Request"] --> B["AWS aprovisiona
hardware virtual"] B --> C["Kernel arranca
sistema operativo"] C --> D["cloud-init se inicia"] D --> E["Lee User Data desde
endpoint de metadatos
169.254.169.254"] E --> F{"¿User Data
presente?"} F -- No --> G["Arranque normal
sin configuración extra"] F -- Sí --> H["Ejecuta script
como root"] H --> I["yum install nginx
systemctl start nginx
systemctl enable nginx"] I --> J["Log escrito en
/var/log/cloud-init-output.log"] J --> K["Instancia en estado
RUNNING con Nginx activo"] G --> K
  1. EC2 Instance Launch: AWS aprovisiona el hardware virtual y arranca el kernel.
  2. cloud-init lee User Data: El agente consulta el endpoint de metadatos para obtener el script.
  3. Ejecución del script: El shell script corre como root. En este caso, instala y habilita Nginx.
  4. Instancia disponible: La instancia pasa a estado 'running'. Si el script terminó correctamente, Nginx ya está activo.
  5. Logs disponibles: Toda la salida del script queda registrada en /var/log/cloud-init-output.log.

Dónde Pegar el Script de User Data en la Consola AWS

Este es el punto donde más gente se pierde la primera vez — el campo de User Data no está en la pantalla principal del asistente de lanzamiento, sino enterrado en la sección de detalles avanzados.

Pasos exactos en la consola EC2 (AWS Console actual):

  1. Ve a EC2 → Instances → Launch instances.
  2. Configura AMI, tipo de instancia, par de claves y configuración de red normalmente.
  3. En la sección 'Advanced details' (al final de la página, antes del resumen), expande el acordeón.
  4. Localiza el campo 'User data'. Verás dos opciones: 'Input is already base64 encoded' y el área de texto.
  5. Asegúrate de que NO está marcada la opción 'Input is already base64 encoded' si vas a pegar texto plano.
  6. Pega tu script directamente en el área de texto. Debe comenzar con #!/bin/bash.
  7. Continúa con el lanzamiento normalmente.

Piensa en User Data como el 'primer día de trabajo' de tu instancia: las instrucciones que le dejas antes de que empiece a atender tráfico. Si no las dejas escritas, tendrás que dárselas manualmente cada vez.

Script de User Data para Instalar Nginx Automáticamente

A continuación, scripts probados para las distribuciones más comunes. Elige el que corresponda a tu AMI.

Amazon Linux 2 y Amazon Linux 2023

#!/bin/bash
yum update -y
yum install -y nginx
systemctl start nginx
systemctl enable nginx

Ubuntu 22.04 / 20.04

#!/bin/bash
apt-get update -y
apt-get install -y nginx
systemctl start nginx
systemctl enable nginx

La línea systemctl enable nginx es crítica si la instancia se reinicia — sin ella, Nginx arranca la primera vez pero no sobrevive a un reboot. systemctl start lo levanta ahora; systemctl enable lo registra para arranques futuros.

Lanzar una Instancia EC2 con User Data desde la CLI

Si tu flujo de trabajo es Infrastructure as Code o simplemente prefieres la CLI, puedes pasar el script directamente con --user-data. La CLI acepta el contenido del archivo y lo codifica automáticamente.

🔽 Ver comando completo de AWS CLI para lanzar EC2 con User Data
# Primero, crea el archivo con el script
cat <<'EOF' > /tmp/user-data-nginx.sh
#!/bin/bash
yum update -y
yum install -y nginx
systemctl start nginx
systemctl enable nginx
EOF

# Lanza la instancia pasando el archivo de User Data
aws ec2 run-instances \
  --image-id ami-0c02fb55956c7d316 \
  --instance-type t3.micro \
  --key-name tu-par-de-claves \
  --security-group-ids sg-0123456789abcdef0 \
  --subnet-id subnet-0123456789abcdef0 \
  --user-data file:///tmp/user-data-nginx.sh \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=nginx-server}]' \
  --region us-east-1

Nota: Reemplaza ami-0c02fb55956c7d316, tu-par-de-claves, sg-0123456789abcdef0 y subnet-0123456789abcdef0 con los valores reales de tu cuenta y región. Los IDs de AMI son específicos por región — verifica el ID correcto para tu región en el catálogo de AMIs de AWS.

Verificar que el Script de User Data se Ejecutó Correctamente

La instancia está en estado 'running' pero Nginx no responde — esto pasa más de lo que parece. El primer lugar donde mirar no es el Security Group (aunque también puede ser el problema), sino el log de cloud-init.

Paso 1: Revisar el log de cloud-init en la instancia

Conéctate por SSH y examina el log de salida — aquí verás exactamente qué ejecutó el script y si hubo errores de paquetes, permisos o red durante la instalación.

sudo cat /var/log/cloud-init-output.log

Paso 2: Verificar el estado de Nginx

Si el log no muestra errores pero Nginx no responde, confirma que el servicio está activo — un script que termina sin error no garantiza que el servicio quedó corriendo.

sudo systemctl status nginx

Paso 3: Consultar el User Data que recibió la instancia

Esto cierra la brecha entre 'lo que creías haber configurado' y 'lo que la instancia realmente recibió' — especialmente útil cuando el script se pasa via CLI o plantillas de CloudFormation.

curl http://169.254.169.254/latest/user-data

Paso 4: Verificar el Security Group permite tráfico HTTP

Nginx puede estar corriendo perfectamente y aun así no ser accesible si el Security Group de la instancia no tiene una regla de entrada para el puerto 80. Este es el error de diagnóstico más común — se asume que el problema es el script cuando en realidad es la capa de red.

aws ec2 describe-security-groups \
  --group-ids sg-0123456789abcdef0 \
  --query 'SecurityGroups[*].IpPermissions' \
  --region us-east-1
graph TD START["Nginx no responde"] --> L1["Revisar
/var/log/cloud-init-output.log"] L1 --> Q1{"¿Errores
en el log?"} Q1 -- Sí --> FIX1["Corregir script:
verificar shebang,
sintaxis, red"] Q1 -- No --> L2["systemctl status nginx"] L2 --> Q2{"¿Servicio
activo?"} Q2 -- No --> FIX2["systemctl start nginx
revisar errores de servicio"] Q2 -- Sí --> L3["Verificar User Data
recibido via IMDS"] L3 --> Q3{"¿Script
correcto?"} Q3 -- No --> FIX3["Detener instancia,
corregir User Data,
relanzar"] Q3 -- Sí --> L4["Verificar Security Group
puerto 80 abierto"] L4 --> Q4{"¿Regla HTTP
presente?"} Q4 -- No --> FIX4["Agregar regla inbound
TCP 80 en Security Group"] Q4 -- Sí --> L5["Revisar logs de Nginx
/var/log/nginx/error.log"]
  1. Nginx no responde: Punto de partida del diagnóstico.
  2. Revisar cloud-init log: Determina si el script se ejecutó y si hubo errores durante la instalación.
  3. Verificar systemctl status: Confirma si el servicio está activo en este momento.
  4. Verificar User Data recibido: Descarta discrepancias entre el script configurado y el que llegó a la instancia.
  5. Verificar Security Group: Confirma que el puerto 80 tiene regla de entrada permitida.

El Error que Nadie Documenta: Script Silencioso sin Efecto

Síntoma: la instancia arranca, el log de cloud-init no muestra errores, pero Nginx no está instalado.

Diagnóstico inicial (incorrecto): 'El script no se ejecutó'. Se revisa el User Data en la consola, parece correcto, se relanza la instancia — mismo resultado.

Causa real: el script comenzaba con un espacio o línea en blanco antes de #!/bin/bash. El shebang debe ser la primera línea, primer carácter del archivo. Si hay cualquier carácter antes — incluyendo un salto de línea invisible — el sistema no lo interpreta como script de shell y cloud-init puede procesarlo como un formato diferente o simplemente ignorarlo sin emitir error explícito.

Corrección: verifica que el script pegado en la consola o en el archivo no tenga espacios ni líneas vacías antes de #!/bin/bash. Si usas un editor con autoformato, esto puede introducirse silenciosamente.

Un shebang con un espacio antes es como una llave con la muesca desplazada un milímetro: entra en la cerradura pero no gira.

Modificar User Data en una Instancia Existente

Si necesitas cambiar el script de User Data en una instancia que ya existe, la instancia debe estar detenida (estado 'stopped') — no es posible modificar User Data en una instancia en ejecución.

# Paso 1: Detener la instancia
aws ec2 stop-instances \
  --instance-ids i-0123456789abcdef0 \
  --region us-east-1

# Paso 2: Esperar a que esté detenida
aws ec2 wait instance-stopped \
  --instance-ids i-0123456789abcdef0 \
  --region us-east-1

# Paso 3: Modificar el User Data
aws ec2 modify-instance-attribute \
  --instance-id i-0123456789abcdef0 \
  --user-data file:///tmp/nuevo-user-data.sh \
  --region us-east-1

# Paso 4: Iniciar la instancia
aws ec2 start-instances \
  --instance-ids i-0123456789abcdef0 \
  --region us-east-1

Importante: modificar User Data en una instancia existente no re-ejecuta el script automáticamente en el siguiente arranque. Por defecto, cloud-init solo ejecuta User Data en el primer boot. Para forzar re-ejecución, es necesario modificar la configuración de cloud-init en la instancia — lo cual está fuera del alcance de este artículo y requiere acceso SSH a la instancia.

IAM: Permisos Necesarios para Gestionar User Data

Si estás trabajando con roles IAM limitados — en un equipo o cuenta corporativa — necesitas los siguientes permisos para lanzar instancias con User Data y modificarlo posteriormente.

🔽 Ver política IAM mínima para gestionar EC2 User Data
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "LaunchInstanceWithUserData",
      "Effect": "Allow",
      "Action": [
        "ec2:RunInstances"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ModifyUserDataStoppedInstance",
      "Effect": "Allow",
      "Action": [
        "ec2:ModifyInstanceAttribute",
        "ec2:StopInstances",
        "ec2:StartInstances",
        "ec2:DescribeInstances"
      ],
      "Resource": "*"
    }
  ]
}

La acción ec2:RunInstances requiere "Resource": "*" porque opera sobre múltiples tipos de recursos (instancias, AMIs, subnets, security groups) simultáneamente. Verifica los requisitos exactos de recursos en el Service Authorization Reference de AWS antes de aplicar restricciones adicionales.

Próximos Pasos y Recursos

Con EC2 User Data tienes automatización básica del arranque cubierta. Para entornos de producción más complejos, el siguiente paso natural es explorar AWS Systems Manager Run Command para ejecutar scripts en instancias ya en ejecución, o AWS CloudFormation cfn-init para configuración declarativa más sofisticada que un script de shell. Si necesitas gestionar configuración a escala en múltiples instancias, considera AWS Systems Manager State Manager.

Para profundizar en los temas de este artículo, consulta la documentación oficial:

Glosario de Términos Clave

TérminoDefinición
User DataScript o datos de configuración que se pasan a una instancia EC2 en el momento del lanzamiento para su ejecución automática durante el primer arranque.
cloud-initHerramienta de inicialización estándar en la industria, presente en la mayoría de AMIs de Linux, que procesa y ejecuta el User Data durante el arranque.
Shebang (#!)Primera línea de un script que indica al sistema operativo qué intérprete usar para ejecutarlo (ej: #!/bin/bash).
IMDSv2Instance Metadata Service versión 2 — método orientado a sesiones para acceder a los metadatos de la instancia, incluyendo el User Data, desde dentro de la instancia.
systemctl enableComando de systemd que registra un servicio para iniciarse automáticamente en cada arranque del sistema operativo.

Related Posts

Comentarios

Entradas populares de este blog

EC2 sin acceso a Internet en VPC personalizada: Internet Gateway y Route Table

Actualizar Contenido en CloudFront: Cómo Crear una Invalidación para Limpiar el Caché del Edge

Aumentar el Timeout de Lambda: Configuración, Límites y Diagnóstico en Producción