How to Install AWS ACM SSL Certificate on EC2 Instance Without Load Balancer


2 views

Many developers assume AWS Certificate Manager (ACM) certificates can only be used with Elastic Load Balancers (ELB) or CloudFront. However, when running a single-instance application, adding a load balancer might be unnecessary overhead. The good news is there are alternative approaches.

ACM certificates are designed to be managed by AWS services. They cannot be exported or downloaded for direct installation on EC2 instances. This is a security feature of ACM, not a technical limitation.

Here's a practical approach using Nginx:


server {
    listen 443 ssl;
    server_name yourdomain.com;
    
    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

1. Request a certificate in ACM for your domain

2. Create an IAM role with ACM read permissions

3. Use AWS CLI to temporarily access the certificate:


aws acm export-certificate --certificate-arn your-cert-arn \
--passphrase fileb://passphrase.txt \
--output text > certificate.pem

While this approach works, remember that:

  • The certificate will need to be renewed manually
  • Private keys should never be stored in insecure locations
  • Consider using AWS Systems Manager Parameter Store for secure storage

For production environments, even with a single instance, using an Application Load Balancer provides:

  • Built-in certificate management
  • Better availability
  • Simpler scaling when needed

AWS Certificate Manager (ACM) has a fundamental restriction: certificates issued through ACM can only be used with AWS services that integrate with ACM, such as Elastic Load Balancers (ELB), CloudFront, or API Gateway. This means you cannot directly install an ACM certificate on an EC2 instance running a web server like Apache or Nginx.

For single-instance deployments where load balancers seem excessive, consider these practical approaches:

Option 1: Use Let's Encrypt for Free Certificates

The most straightforward solution is to use Let's Encrypt with Certbot:

sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx  # For Nginx
sudo certbot --nginx -d yourdomain.com

Option 2: Create and Install Self-Signed Certificate

For testing environments:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/nginx-selfsigned.key \
-out /etc/ssl/certs/nginx-selfsigned.crt

Option 3: Use ALB Anyway (Recommended for Production)

Despite being a single instance, an Application Load Balancer provides benefits:

# Sample Terraform configuration for ALB with ACM:
resource "aws_lb" "example" {
  name               = "example-lb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.lb_sg.id]
  subnets            = aws_subnet.public.*.id
}

resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.example.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = aws_acm_certificate.example.arn
}

The ACM restriction exists because:

  • Certificates never expose private keys to users
  • Automatic renewal handled by AWS
  • Better security through key management

For Let's Encrypt certificates:

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:3000;
        proxy_set_header Host $host;
    }
}

While ALB adds cost (~$16/month), it provides:

  • Built-in DDoS protection
  • Zonal failover
  • SSL termination offloading
  • Better security isolation