Algunas cosas han cambiado en Amazon Web Services recientemente y, para nuestra mala suerte, la forma en la que se podían configurar los certificados SSL en una instancia única (o Single Instance), o bien, una instancia sin un balanceador de cargas, cambió dramáticamente. Por lo tanto, en este post podrás aprender a habilitar SSL en un Single Instance de Elastic Beanstalk con NGINX de una forma bastante amigable.
Antes de empezar te recomiendo que olvides cualquier método anterior para habilitar SSL en un Single Instance de Elastic Beanstalk con NGINX. Por ejemplo:
- Borra cualquier certificado en ACM (Amazon Certificate Manager) relacionado a tu instancia única, pues en el nuevo método, estaremos generando un certificado válido y gratuito a través de Let’s Encrypt 😍
- Si tu aplicación utiliza un archivo
.htaccess
asegúrate de borrar la redirección a HTTPS desde ahí. Más adelante pondré un ejemplo de cómo debería quedar tu.htaccess
. - Si alguna vez seguiste mi tutorial Forzar HTTPS en Elastic Beanstalk con NGINX que publiqué en Septiembre del 2020, también olvídalo 😳.
Para este artículo asumo que:
1. Tienes una instancia de Elastic Beanstalk, si no, checa el artículo “Configurar un servidor con NGINX de instancia única con Elastic Beanstalk“
2. Tienes acceso SSH a tu instancia de Elastic Beanstalk. Te puede interesar el artículo “Configurar un acceso SSH a instancias EC2 en AWS“
3. Tienes comprado un dominio para el cual necesitas el certificado SSL. Si aun no tienes un dominio comprado, te recomiendo lo compres en mydomain.com
4. Tu dominio está configurado en Route 53 en Amazon Web Services. Si no sabes como configurarlo te recomiendo el siguiente artículo sobre “Cómo configurar un dominio en Route 53“
El nuevo método para habilitar SSL en un Single Instance de Elastic Beanstalk con NGINX, el cual bautizaré egolatramente como “El método Andrex para habilitar SSL en un Single Instance de Elastic Beanstalk con NGINX“, consiste en lo siguiente:
- Crear jerarquía de archivos y carpetas que nos permitirán configurar Elastic Beanstalk y NGINX para generar e instalar el certificado SSL gratis en la instancia única
- Agregar el contenido del archivo de configuración para Elastic Beanstalk
01-https_certificate_generation.config
para generar e instalar el certificado SSL gratis - Define el contenido del archivo de configuración de NGINX base
nginx.conf
- Ingresa el contenido al archivo
https_custom.conf
para habilitar el certificado SSL - Configurar apropiadamente el
.htaccess
para evitar redirecciones infinitas - Prepara el
index.php
para probar la configuración
El método Andrex para habilitar SSL en un Single Instance de Elastic Beanstalk con NGINX
Comencemos pues con el procedimiento para habilitar SSL en un Single Instance de Elastic Beanstalk con NGINX. Para la demostración de este proyecto estaré utilizando un proyecto nuevo llamado “metodo-andrex-ssl-eb-nginx”, si quieres acceso al repositorio en gitlab sígueme en Instagram y mándame tu usuario de gitlab por mensaje privado 🤓.
Crear jerarquía de archivos y carpetas que nos permitirán configurar Elastic Beanstalk y NGINX para generar e instalar el certificado SSL gratis en la instancia única
En la raíz de tu proyecto crea la siguiente jerarquía de archivos y carpetas; en estas carpetas vamos a crear los archivos de configuración que vamos a necesitar. Por lo tanto abre una terminal y sigue el siguiente procedimiento de comandos para hacerlo:
# Crea el directorio raíz de tu proyecto
mkdir metodo-andrex-ssl-eb-nginx
# Accede al directorio de tu proyecto
cd metodo-andrex-ssl-eb-nginx
# Crea la carpeta de configuración para las instancias de Elastic Beanstalk
mkdir .ebextensions
# Crea un archivo vacío para el código que generará e instalará el certificado SSL
touch ./.ebextensions/01-https_certificate_generation.config
# Crea las carpetas de configuración para NGINX
mkdir .platform
mkdir ./.platform/nginx
mkdir ./.platform/nginx/conf.d
mkdir ./.platform/nginx/conf.d/elasticbeanstalk
# Crea un archivo vacío para la configuración base de NGINX
touch ./.platform/nginx/nginx.conf
# Crea un archivo vacío para la configuración personalizada de NGINX sobre Elastic Beanstalk
touch ./.platform/nginx/conf.d/elasticbeanstalk/custom.conf
# Crea un archivo vacío para la configuración personalizada de NGINX sobre HTTPS
touch ./.platform/nginx/conf.d/https_custom.conf
# Crea el archivo .htaccess vacío
touch ./.htaccess
# Crea el archivo índex.php vacío
touch ./index.php
El resultado de la ejecución de los comandos anteriores debe resultar en la jerarquía de archivos y carpetas que se muestra en la imagen a continuación:

Si ya comprobaste que tengas esta estructura de archivos y carpetas, continuemos a agregar el contenido a los archivos vacíos que creamos.
Agregar el contenido del archivo de configuración para Elastic Beanstalk 01-https_certificate_generation.config para generar e instalar el certificado SSL gratis
El contenido que vamos a agregar a este archivo llevará acabo el siguiente procedimiento:
- Creará un grupo de seguridad para permitir el trafico entrante a la instancia única por medio del puerto 443
- Instalará en el contenedor de nuestra instancia el modulo de seguridad
mod_ssl
cada vez que se cargue una nueva versión de nuestro proyecto - Creará una tarea programada que renueve automáticamente el certificado SSL gratis cada vez que vaya a expirar
- Solicitará e instalará el certificado de seguridad SSL de forma gratuita
Para este paso vamos a necesitar que tengas listo lo siguiente:
- Un correo electrónico válido, en mi caso pondré el mío
iam[at]andresgtz.com
- La lista de dominios y subdominios que vamos a certificar, en mi caso utilizare los siguientes que compre para un proyecto que publicaré más adelante.
- mostsercurewebsite.com
- www.mostsecurewebsite.com
Abre el archivo 01-https_certificate_generation.config en tu editor de código y pon el siguiente código.
Resources:
sslSecurityGroupIngress:
Properties:
CidrIp: 0.0.0.0/0
FromPort: 443
GroupId: {"Fn::GetAtt" : ["AWSEBSecurityGroup", "GroupId"]}
IpProtocol: tcp
ToPort: 443
Type: "AWS::EC2::SecurityGroupIngress"
packages:
yum:
mod_ssl : []
files:
"/etc/cron.d/certbot_renew":
content: "@weekly root certbot renew\n"
group: root
mode: "000644"
owner: root
container_commands:
10_downloadepel:
command: "sudo wget -r --no-parent -A 'epel-release-*.rpm' https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/"
20_installepel:
command: "sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm --force"
30_enableepl:
command: "sudo yum-config-manager --enable epel*"
40_installcertbot:
command: "sudo yum install -y certbot"
50_getcert:
command: "sudo certbot certonly --debug --non-interactive --email [email protected] --agree-tos --standalone --domain mostsecurewebsite.com --domain www.mostsecurewebsite.com --rsa-key-size 4096 --keep-until-expiring --pre-hook \"sudo service nginx stop\" --post-hook \"sudo service nginx start\""
IMPORTANTE:
ASEGURATE DE CAMBIAR MI CORREO ELECTRÓNICO Y MIS DOMINIOS POR LOS TUYOS ANTES! DE NO HACERLO, NO VAS A PODER CONFIGURAR EL CERTIFICADO SSL.
Define el contenido del archivo de configuración de NGINX base nginx.conf
Ahora, no se puede configurar correctamente una instancia con HTTPS si el servidor que apunta a HTTP no está bien configurado, por lo tanto, agrega el siguiente código al archivo nginx.conf
:
# Elastic Beanstalk Nginx Configuration File
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 32136;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
large_client_header_buffers 8 64k;
client_body_buffer_size 32k;
client_header_buffer_size 8k;
listen 80 default_server;
listen [::]:80 default_server;
# Recuerda cambiar a tu dominio
server_name mostsecurewebsite.com www.mostsecurewebsite.com;
if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
}
access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;
access_log /var/log/nginx/access.log main;
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
log_not_found off;
client_header_timeout 60;
client_body_timeout 60;
keepalive_timeout 600;
gzip on;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload" always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1;mode=block" always;
# Configuration to redirect TO HTTPS
location / {
set $redirect 0;
if ($http_x_forwarded_proto != "https") {
set $redirect 1;
}
if ($http_user_agent ~* "ELB-HealthChecker") {
set $redirect 0;
}
if ($redirect = 1) {
return 301 https://$host$request_uri;
}
}
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/*.conf;
}
}
Ingresa el contenido al archivo https_custom.conf para habilitar el certificado SSL
Ya casi terminamos la configuración necesaria para probar que nuestro certificado SSL funciona, para ello necesitamos agregar el siguiente contenido al archivo https_custom.conf
como se muestra a continuación:
upstream nodejs {
server 127.0.0.1:3030;
keepalive 256;
}
# HTTPS server
server {
listen 443 ssl default_server;
# Asegurate de cambiar mostsecurewebsite.com por tu dominio
server_name mostsecurewebsite.com www.mostsecurewebsite.com;
if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
}
access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;
access_log /var/log/nginx/access.log main;
ssl_prefer_server_ciphers on;
# Asegurate de cambiar mostsecurewebsite.com en la ruta por tu dominio
ssl_certificate /etc/letsencrypt/live/mostsecurewebsite.com/fullchain.pem;
# Asegurate de cambiar mostsecurewebsite.com en la ruta por tu dominio
ssl_certificate_key /etc/letsencrypt/live/mostsecurewebsite.com/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
location ~ ^/(lib/|img/) {
root /var/app/current/public;
access_log off;
}
location / {
proxy_pass http://localhost:80;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
Configurar apropiadamente el .htaccess para evitar redirecciones infinitas
En algunos casos se usa que la redirección de HTTP a HTTPS se maneje desde el .htaccess
, pero en este procedimiento, es MUY IMPORTANTE que no se haga esta redirección de esta forma pues se ocasionaría un bucle infinito de redirecciones. Por lo tanto, yo sugiero que dejemos el .htaccess
con el siguiente contenido:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ ^$1 [N]
# When Elastic Beanstalk instance on AWS + NGINX, redirect should be commented out
# RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# RewriteCond %{HTTPS} !=on
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
</IfModule>
Prepara el index.php para probar la configuración
Lo único que tenemos que hacer en este paso es agregar el siguiente contenido al index.php
<?php
echo "El método Andrex para habilitar SSL en un Single Instance de Elastic Beanstalk con NGINX funciona. 😎";
?>
Vamos a probar que nuestra configuración funcione
Para probar que nuestra configuración funcione debemos comprimir nuestro proyecto y subirlo a Elastic Beanstalk. Vamos, que para estar leyendo El método Andrex para habilitar SSL en un Single Instance de Elastic Beanstalk con NGINX deberías estar familiarizado con este procedimiento.
Para comprimir tu proyecto en un .zip para cargarlo a Elastic Beanstalk usa el siguiente comando:
# Dentro del directorio de tu proyecto ejecuta el siguiente comando
cd metodo-andrex-ssl-eb-nginx # Por si las dudas
# Comando para comprimir
zip ../"${PWD##*/}".zip -r * .[^.]*
Una vez que se termine de subir tu código podrás visualizar la siguiente pantalla, lo que quiere decir que todo funcionó correctamente:

Bonus (Aplicaciones Laravel)
Para aplicaciones Laravel debes agregar una configuración extra al archivo AppServiceProvider.php, la cual es la siguiente:
# Dentro del metodo boot
URL::forceScheme('https');
Y listo.
Hasta la próxima!
Espero que te haya gustado y ayudado este artículo, de ser así, suscríbete para que seas notificad@ siempre que suba artículos sobre automatización y seguridad informática, me lo agradecerás después.También puedes seguirme en Instagram en @andres.gtz y hacerme las preguntas que desees. Así mismo, agradezco tu generosidad si deseas donar criptomonedas a alguna de las siguientes direcciones:
Bitcoin
Ethereum
Tether
Cardano
Xrp
Polkadot
Binance coin
Litecoin
Stellar
Dogecoin

Donate Bitcoin to this address
Scan the QR code or copy the address below into your wallet to send some Bitcoin

Donate Ethereum to this address
Scan the QR code or copy the address below into your wallet to send some Ethereum

Donate Tether to this address
Scan the QR code or copy the address below into your wallet to send some Tether

Donate Cardano to this address
Scan the QR code or copy the address below into your wallet to send some Cardano

Donate Xrp to this address
Scan the QR code or copy the address below into your wallet to send some Xrp

Donate Polkadot to this address
Scan the QR code or copy the address below into your wallet to send some Polkadot

Donate Binance coin to this address
Scan the QR code or copy the address below into your wallet to send some Binance coin

Donate Litecoin to this address
Scan the QR code or copy the address below into your wallet to send some Litecoin

Donate Stellar to this address
Scan the QR code or copy the address below into your wallet to send some Stellar

Donate Dogecoin to this address
Scan the QR code or copy the address below into your wallet to send some Dogecoin
Please Add coin wallet address in plugin settings panel
Si te quedaron dudas, puedes escribirlas aquí en los comentarios, o bien, escríbeme a mi Instagram @andres.gtz.