Setting Up SSL on AWS Elastic Beanstalk Single Instances

Photo by Taylor Vick on Unsplash Deploying applications on AWS Elastic Beanstalk simplifies many aspects of running your web applications, but setting up SSL/TLS on single-instance environments can get a bit tricky. In this article, we’ll explore two practical approaches to implementing SSL for your Elastic Beanstalk single instances. Why SSL on Single Instances Is Challenging AWS Elastic Beanstalk single instances don’t come with built-in SSL termination like their load-balanced counterparts. When you deploy a web application in a single-instance environment, you’re essentially working with a standalone EC2 instance without the benefits of an Application Load Balancer to handle SSL termination. However, there are compelling reasons to use single instances: Cost efficiency : Avoiding load balancer costs for smaller applications Simplified architecture : Reduced complexity for development or test environments Direct instance access : Easier debugging and monitoring Lower traffic needs : Many applications don’t require the scalability of multiple instances Let’s dive into two effective solutions for enabling SSL on your Elastic Beanstalk single instances. Solution 1: Using .ebextensions with Let’s Encrypt This approach involves configuring your Elastic Beanstalk environment with custom .ebextensions scripts to automatically set up and renew SSL certificates using Let's Encrypt. Step 1: Create the .ebextensions Directory In your application’s root directory, create a .ebextensions folder if it doesn't already exist: mkdir -p .ebextensions Step 2: Create the Let’s Encrypt Configuration Script Create a configuration file that will handle the installation and setup of Let’s Encrypt: # .ebextensions/01_ssl_setup.config packages: yum: mod24_ssl: [] epel-release: [] container_commands: 10_install_certbot: command: "sudo yum install -y certbot python-certbot-apache" 20_get_certificate: command: "sudo certbot certonly --standalone --debug --non-interactive --email ${EMAIL} --agree-tos --domains ${DOMAIN} --keep-until-expiring --pre-hook \"service httpd stop\" --post-hook \"service httpd start\"" env: EMAIL: "your-email@example.com" DOMAIN: "yourdomain.com" 30_link_cert: command: "ln -sf /etc/letsencrypt/live/${DOMAIN}/cert.pem /etc/pki/tls/certs/server.crt" env: DOMAIN: "yourdomain.com" 40_link_key: command: "ln -sf /etc/letsencrypt/live/${DOMAIN}/privkey.pem /etc/pki/tls/certs/server.key" env: DOMAIN: "yourdomain.com" 50_enable_ssl_conf: command: "sed -i 's/#LoadModule ssl_module/LoadModule ssl_module/' /etc/httpd/conf.modules.d/00-ssl.conf" 60_create_ssl_conf: command: | cat > /etc/httpd/conf.d/ssl.conf Load Balancers Select your environment’s load balancer Add a listener for HTTPS (port 443) Add your SSL certificate (you can use AWS Certificate Manager for free public certificates) { "Listeners": [ { "Protocol": "HTTPS", "Port": 443, "DefaultActions": [ { "Type": "forward", "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/awseb-AWSEB-ABCDEFGHIJ/0123456789abcdef" } ], "SslPolicy": "ELBSecurityPolicy-2016-08", "Certificates": [ { "CertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012" } ] } ] } Step 3: Set Up CNAME Records In your DNS provider: Create a CNAME record pointing your domain to your Elastic Beanstalk environment URL For example: yourdomain.com → my-environment.elasticbeanstalk.com Step 4: Configure HTTP to HTTPS Redirect (Optional) Create a listener rule for port 80 that redirects to HTTPS: In the EC2 Console, go to the Load Balancer Add a listener for HTTP (port 80) Add a redirect action to HTTPS (port 443) How This Solution Works The load balancer handles SSL termination Traffic is encrypted between clients and the load balancer The load balancer forwards traffic to your single EC2 instance You benefit from AWS Certificate Manager’s free certificates and automatic renewals The architecture remains simple with just one instance Considerations for This Approach Cost implications : This approach adds the cost of a load balancer (approximately $16–20/month) Advantage : AWS manages certificate renewal automatically Simplified management : No need to manage SSL configuration on the instance itself Comparing the Two Approaches Which Solution Should You Choose? Choose Solution 1 (.ebextensions with Let’s Encrypt) if: Cost is a primary concern You’re comfortable managing Linux configurations You want to maintain a truly single-instance architecture Choose Solution 2 (Load Balancer with CNAME) if: You prefer managed services with less operational overhead Budget allows

May 10, 2025 - 19:30
 0
Setting Up SSL on AWS Elastic Beanstalk Single Instances


Photo by Taylor Vick on Unsplash

Deploying applications on AWS Elastic Beanstalk simplifies many aspects of running your web applications, but setting up SSL/TLS on single-instance environments can get a bit tricky. In this article, we’ll explore two practical approaches to implementing SSL for your Elastic Beanstalk single instances.

Why SSL on Single Instances Is Challenging

AWS Elastic Beanstalk single instances don’t come with built-in SSL termination like their load-balanced counterparts. When you deploy a web application in a single-instance environment, you’re essentially working with a standalone EC2 instance without the benefits of an Application Load Balancer to handle SSL termination.

However, there are compelling reasons to use single instances:

  • Cost efficiency : Avoiding load balancer costs for smaller applications
  • Simplified architecture : Reduced complexity for development or test environments
  • Direct instance access : Easier debugging and monitoring
  • Lower traffic needs : Many applications don’t require the scalability of multiple instances

Let’s dive into two effective solutions for enabling SSL on your Elastic Beanstalk single instances.

Solution 1: Using .ebextensions with Let’s Encrypt

This approach involves configuring your Elastic Beanstalk environment with custom .ebextensions scripts to automatically set up and renew SSL certificates using Let's Encrypt.

Step 1: Create the .ebextensions Directory

In your application’s root directory, create a .ebextensions folder if it doesn't already exist:

mkdir -p .ebextensions

Step 2: Create the Let’s Encrypt Configuration Script

Create a configuration file that will handle the installation and setup of Let’s Encrypt:

# .ebextensions/01_ssl_setup.config
packages:
  yum:
    mod24_ssl: []
    epel-release: []

container_commands:
  10_install_certbot:
    command: "sudo yum install -y certbot python-certbot-apache"
  20_get_certificate:
    command: "sudo certbot certonly --standalone --debug --non-interactive --email ${EMAIL} --agree-tos --domains ${DOMAIN} --keep-until-expiring --pre-hook \"service httpd stop\" --post-hook \"service httpd start\""
    env:
      EMAIL: "your-email@example.com"
      DOMAIN: "yourdomain.com"
  30_link_cert:
    command: "ln -sf /etc/letsencrypt/live/${DOMAIN}/cert.pem /etc/pki/tls/certs/server.crt"
    env:
      DOMAIN: "yourdomain.com"
  40_link_key:
    command: "ln -sf /etc/letsencrypt/live/${DOMAIN}/privkey.pem /etc/pki/tls/certs/server.key"
    env:
      DOMAIN: "yourdomain.com"
  50_enable_ssl_conf:
    command: "sed -i 's/#LoadModule ssl_module/LoadModule ssl_module/' /etc/httpd/conf.modules.d/00-ssl.conf"
  60_create_ssl_conf:
    command: |
      cat > /etc/httpd/conf.d/ssl.conf << 'EOL'
      Listen 443
      
        ServerName ${DOMAIN}
        DocumentRoot /var/www/html
        SSLEngine on
        SSLCertificateFile /etc/pki/tls/certs/server.crt
        SSLCertificateKeyFile /etc/pki/tls/certs/server.key
        SSLCertificateChainFile /etc/letsencrypt/live/${DOMAIN}/chain.pem
        
          AllowOverride All
          Require all granted
        
      
      EOL
    env:
      DOMAIN: "yourdomain.com"
files:
  "/etc/cron.d/certbot-renew":
    mode: "000644"
    owner: root
    group: root
    content: |
      0 0,12 * * * root certbot renew --standalone --pre-hook "service httpd stop" --post-hook "service httpd start" --quiet

Make sure to replace your-email@example.com and yourdomain.com with your actual email and domain.

Step 3: Create a Configuration to Handle HTTP to HTTPS Redirect

# .ebextensions/02_ssl_redirect.config
files:
  "/etc/httpd/conf.d/http_redirect.conf":
    mode: "000644"
    owner: root
    group: root
    content: |
      
        ServerName yourdomain.com
        Redirect permanent / https://yourdomain.com/
      

Again, replace yourdomain.com with your actual domain.

Step 4: Deploy Your Application

Deploy your application with these .ebextensions files:

eb deploy

How This Solution Works

  1. The configuration installs the necessary SSL packages and Let’s Encrypt certbot
  2. It requests a certificate from Let’s Encrypt for your domain
  3. The Apache web server is configured to use the certificate
  4. A cron job is set up to automatically renew the certificate before expiration
  5. HTTP traffic is redirected to HTTPS

Potential Issues and Solutions

Port 80/443 accessibility : Ensure your security group allows inbound traffic on ports 80 and 443.

Certificate renewal failures : The pre-hook and post-hook in the cron job temporarily stop Apache during renewal to free up port 80. Monitor renewal logs at /var/log/letsencrypt/ if you encounter issues.

DNS configuration : Your domain must be correctly pointing to your Elastic Beanstalk instance’s IP address for Let’s Encrypt validation to succeed.

Solution 2: Using a Load Balancer with CNAME

This approach involves creating a single-instance environment but fronting it with a load balancer specifically for SSL termination.

Step 1: Create a Load Balanced Environment

Instead of creating a single-instance environment, create a load-balanced environment with a minimum and maximum of 1 instance:

eb create my-environment --elb-type application --single

Or through the AWS Management Console:

  1. Create a new environment
  2. Choose “Web server environment”
  3. Under “Platform”, select your platform of choice
  4. Under “Configuration presets”, select “Custom configuration”
  5. In the “Capacity” section, select “Load balanced”
  6. Set both “Min instances” and “Max instances” to 1

Step 2: Configure SSL on the Load Balancer

  1. Navigate to the EC2 Console > Load Balancers
  2. Select your environment’s load balancer
  3. Add a listener for HTTPS (port 443)
  4. Add your SSL certificate (you can use AWS Certificate Manager for free public certificates)
{
  "Listeners": [
    {
      "Protocol": "HTTPS",
      "Port": 443,
      "DefaultActions": [
        {
          "Type": "forward",
          "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/awseb-AWSEB-ABCDEFGHIJ/0123456789abcdef"
        }
      ],
      "SslPolicy": "ELBSecurityPolicy-2016-08",
      "Certificates": [
        {
          "CertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012"
        }
      ]
    }
  ]
}

Step 3: Set Up CNAME Records

In your DNS provider:

  1. Create a CNAME record pointing your domain to your Elastic Beanstalk environment URL
  2. For example: yourdomain.com → my-environment.elasticbeanstalk.com

Step 4: Configure HTTP to HTTPS Redirect (Optional)

Create a listener rule for port 80 that redirects to HTTPS:

  1. In the EC2 Console, go to the Load Balancer
  2. Add a listener for HTTP (port 80)
  3. Add a redirect action to HTTPS (port 443)

How This Solution Works

  1. The load balancer handles SSL termination
  2. Traffic is encrypted between clients and the load balancer
  3. The load balancer forwards traffic to your single EC2 instance
  4. You benefit from AWS Certificate Manager’s free certificates and automatic renewals
  5. The architecture remains simple with just one instance

Considerations for This Approach

Cost implications : This approach adds the cost of a load balancer (approximately $16–20/month)

Advantage : AWS manages certificate renewal automatically

Simplified management : No need to manage SSL configuration on the instance itself

Comparing the Two Approaches

Which Solution Should You Choose?

Choose Solution 1 (.ebextensions with Let’s Encrypt) if:

  • Cost is a primary concern
  • You’re comfortable managing Linux configurations
  • You want to maintain a truly single-instance architecture

Choose Solution 2 (Load Balancer with CNAME) if:

  • You prefer managed services with less operational overhead
  • Budget allows for an additional ~$20/month
  • You might need to scale in the future
  • You want automatic certificate renewal without custom scripts

Implementation Best Practices

Regardless of which solution you choose, follow these best practices:

Security Considerations

  • Keep your Elastic Beanstalk platform updated
  • Use strong SSL/TLS protocols (TLS 1.2 or higher)
  • Configure security headers in your application
  • Set appropriate security groups to limit access

Monitoring

  • Set up CloudWatch alarms for certificate expiration (for Solution 1)
  • Monitor HTTP status codes to ensure redirects are working properly
  • Set up alerts for SSL/TLS failures

Documentation

Document your SSL setup thoroughly, including:

  • Certificate renewal dates and processes
  • DNS configuration
  • Load balancer or instance configuration details
  • Troubleshooting steps for common issues

Conclusion

Setting up SSL on AWS Elastic Beanstalk single instances doesn’t have to be complicated. Both approaches outlined in this article provide secure ways to serve your application over HTTPS.

The .ebextensions approach with Let’s Encrypt offers a cost-effective solution with more hands-on management, while the load balancer approach provides a more managed experience at a higher cost.

Choose the approach that best aligns with your technical comfort level, budget constraints, and operational preferences. Either way, you’ll be providing your users with the secure experience they expect and deserve.

See you in the next article!