AWS Elastic Beanstalk (EB) is a platform as a service (PaaS) that simplifies application deployment by managing the underlying infrastructure and scaling for you, allowing developers to focus on code rather than infrastructure overhead.
I recently used Elastic Beanstalk to deploy a small Nginx-based web application for a developer who needed a low-maintenance setup without the complexities of managing servers or autoscaling. While EB typically excels at scaling applications with load balancers, our use case only required a single-instance deployment with HTTPS for security. However, enabling HTTPS in EB without a load balancer can be challenging, as SSL isn’t straightforward in single-instance environments.
The goal of this article is to walk you through the steps of configuring SSL on a single-instance Elastic Beanstalk environment. By the end, you’ll know how to make your single-instance EB deployments route securely to HTTPS, without the use of a load balancer. This approach keeps the setup simple and secure, meeting the needs of low-maintenance applications that still require encrypted connections.
Nginx HTTPS Configuration Guide
This guide provides step-by-step instructions for setting up Nginx to handle HTTPS with SSL certificates and configuring HTTP to HTTPS redirection on an AWS EC2 instance. This needs to be done once your environment has been successfully spun up and the ec2 instance is up and running. Ensure that the security group attached to the EC2 instances deployed by EB allows ingress on port 443 only.
1. Install Nginx and Certbot
Connect to Your EC2 Instance
ssh -i your-key.pem ec2-user@your-instance-ip
Install Nginx and Certbot
sudo yum install -y nginx
sudo yum install -y epel-release
sudo yum install -y certbot
2. Obtain SSL Certificate
Here we will use Let’s Encrypt, a free, automated, and open certificate authority (CA) that provides SSL/TLS certificates to enable secure HTTPS connections. Let’s Encrypt simplifies the process of generating and renewing SSL certificates by automating many of the required steps, making it an ideal choice for quickly and easily securing applications — like our single-instance Elastic Beanstalk deployment.
Stop Nginx Temporarily
sudo systemctl stop nginx
Obtain the SSL Certificate
# Replace `yourdomain.com` with your actual domain name.
sudo certbot certonly --standalone -d yourdomain.com
Start Nginx Again
sudo systemctl start nginx
3. Configure Nginx for HTTPS
Edit Nginx Configuration
# Open the main Nginx configuration file:
sudo nano /etc/nginx/nginx.conf
Add or Update Configuration
# Inside the `http` block, add or update the following settings:
http {
# Existing configuration...
types_hash_max_size 4096;
types_hash_bucket_size 128;
server_names_hash_max_size 4096;
server_names_hash_bucket_size 128;
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";
}
}
Configure HTTP to HTTPS Redirect
# Create or edit a file in `/etc/nginx/conf.d/` (e.g., `ssl.conf`):
sudo nano /etc/nginx/conf.d/ssl.conf
# Add the following HTTP to HTTPS redirect configuration
# Ports may vary depending on setup:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
Configure HTTPS Server Block
# Add or edit the HTTPS configuration in the same file (`ssl.conf`):
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:80;
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 $scheme;
}
}
Check for Additional Configuration Files
Ensure there are no conflicting redirects in other configuration files:
sudo grep -r "return 301" /etc/nginx/conf.d/
sudo grep -r "proxy_pass" /etc/nginx/conf.d/
Validate and Restart Nginx
# Test Configuration:
sudo nginx -t
# Restart Nginx:
sudo systemctl restart nginx
Summary
1. Install Nginx and Certbot.
2. Obtain an SSL certificate using Certbot.
3. Configure Nginx to handle HTTP to HTTPS redirection and serve content over HTTPS.
4. Check for conflicting configurations and ensure Nginx is properly set up.
5. Test and restart Nginx to apply the changes.
Renewals
Let’s Encrypt certificates are valid for 90 days from the date they are issued. To ensure continuous HTTPS coverage, it’s best to automate the renewal process so certificates are refreshed well before they expire. This can be done by setting up a cron job that runs the Certbot renewal command at regular intervals. For example, running the following command twice daily — certbot renew — quiet — post-hook “systemctl reload nginx” — will automatically check for certificates due for renewal and update them if needed, reloading Nginx to apply any changes. This setup provides reliable, hands-off certificate management, ensuring your site stays secure without manual intervention.
Automating SSL for Future Source Code Deployments (Optional)
To avoid repeating these steps whenever we need to recreate the instances, we can automate it by adding .ebextensions and .platform folders to the ‘root folder’ of your source code repository.
.ebextensions Folder
Create a .config file in the .ebextensions folder to store the SSL certs in order to reference them in future deployments. Ensure to specify the correct Lets Encrypt installation path:
files:
/etc/letsencrypt/live/yourdomain/server.crt:
mode: "000400"
owner: root
group: root
content: |
-----BEGIN CERTIFICATE-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
/etc/letsencrypt/live/yourdomain/server.key:
mode: "000400"
owner: root
group: root
content: |
-----BEGIN PRIVATE KEY-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END PRIVATE KEY-----
.platform Folder
Within the .platform folder, create nginx/conf.d/ssl.conf and nginx/conf.d/redirect.conf:
ssl.conf
server {
listen 443 ssl;
server_name Mock-service-api.eba-hy378rnj.eu-west-1.elasticbeanstalk.com;
# ssl on;
ssl_certificate /etc/letsencrypt/live/yourdomain/server.crt;
ssl_certificate_key /etc/letsencrypt/live/yourdomain/server.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://nodejs;
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;
}
location /socket.io {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy false;
proxy_pass http://localhost:8081;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
redirect.conf
Ports may vary depending on individual configurations
# redirect
# app should be running on 8081
upstream nodejs {
server 127.0.0.1:8081;
keepalive 256;
}
server {
listen 8080;
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;
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;
}
proxy_pass http://nodejs;
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;
}
}
Conclusion
In this article, we’ve walked through the process of setting up SSL on a single-instance Elastic Beanstalk environment. By using Let’s Encrypt and configuring Nginx to handle SSL termination, we’ve ensured that even a simple, low-maintenance web application can be securely accessed over HTTPS. We also covered how to automate certificate renewals with Certbot and cron jobs, keeping your environment secure with minimal manual intervention.
Elastic Beanstalk offers a powerful platform for deploying applications with ease, and with just a few additional steps, you can make sure your web app is both simple to maintain and secure.
Should there be any enquiries or recommendations on improvements feel free to reach out to me via LinkedIn.
References
Comments