Facebook Pixel

Adding SSL with Let's Encrypt on EC2 Free HTTPS for Your Node.js App

Learn how to add free SSL certificates with Let's Encrypt and Certbot on AWS EC2, enabling HTTPS for your Node.js application with automatic renewal.

Adding SSL with Let's Encrypt on EC2

SSL (HTTPS) is essential for production web apps. It encrypts traffic, protects user data, and is required for features like HTTP-only cookies with secure: true. Let's Encrypt provides free SSL certificates.

Prerequisites

  1. An EC2 instance with Nginx configured
  2. A domain name pointing to your EC2 public IP (via A record in DNS)
  3. Ports 80 and 443 open in your security group
  4. Nginx running and responding on port 80

Step 1: Install Certbot

sudo apt update sudo apt install -y certbot python3-certbot-nginx

Certbot is the tool that automatically obtains and installs Let's Encrypt certificates.

Step 2: Verify Your Domain

Before getting an SSL certificate, Let's Encrypt verifies that you control the domain. Ensure:

  • Your domain (e.g., api.yourdomain.com) has an A record pointing to your EC2 public IP
  • Nginx is running and responding on port 80
  • Your Nginx server_name matches the domain

Test by visiting http://api.yourdomain.com in a browser you should see your API response.

Step 3: Obtain the SSL Certificate

sudo certbot --nginx -d api.yourdomain.com

Certbot will:

  1. Verify domain ownership
  2. Obtain the SSL certificate
  3. Automatically modify the Nginx configuration to use HTTPS
  4. Set up HTTP to HTTPS redirect

Follow the prompts:

  • Email: Enter your email for expiry notifications
  • Terms of service: Agree
  • Share email: N (optional)
  • Redirect: Choose option 2 (redirect all HTTP to HTTPS)

Step 4: Verify HTTPS

Visit https://api.yourdomain.com in your browser. You should see the padlock icon indicating a secure connection.

Test with curl:

curl -I https://api.yourdomain.com/api/health # HTTP/2 200 # server: nginx # ...

Step 5: Auto-Renewal

Let's Encrypt certificates expire after 90 days. Certbot sets up automatic renewal by default.

Test the renewal process:

sudo certbot renew --dry-run

This simulates the renewal without actually renewing. If it succeeds, auto-renewal is working.

The renewal cron job is at /etc/cron.d/certbot and runs twice daily.

Step 6: Update Your App for HTTPS

Now that you have HTTPS, update your backend:

# .env NODE_ENV=production CLIENT_URL=https://yourdomain.com

Update cookie settings for cross-site HTTPS:

res.cookie("token", token, { httpOnly: true, secure: true, // HTTPS only sameSite: "none", // Allow cross-site cookies (if frontend is on a different domain) maxAge: 7 * 24 * 60 * 60 * 1000 });

Note: sameSite: "none" requires secure: true. If frontend and backend are on the same domain, use sameSite: "lax".

Step 7: Update Frontend Environment

Update the frontend to use HTTPS:

VITE_API_URL=https://api.yourdomain.com/api VITE_SOCKET_URL=https://api.yourdomain.com

The Nginx Configuration After Certbot

Certbot automatically adds these lines to your Nginx config:

server { server_name api.yourdomain.com; # SSL configuration added by Certbot listen 443 ssl; ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_pass http://localhost:3000; # ... proxy headers ... } } # HTTP to HTTPS redirect server { if ($host = api.yourdomain.com) { return 301 https://$host$request_uri; } listen 80; server_name api.yourdomain.com; return 404; }

Troubleshooting

"Connection refused" on HTTPS:

  • Check that port 443 is open in your EC2 security group
  • Verify Nginx is running: sudo systemctl status nginx

Certbot fails to verify domain:

  • Ensure DNS A record points to the correct EC2 IP
  • Wait for DNS propagation (can take up to 24 hours)
  • Check that Nginx server_name matches the domain

Certificate renewal fails:

  • Run sudo certbot renew --dry-run to test
  • Check that port 80 is accessible (Let's Encrypt uses HTTP-01 challenge)
  • Check Certbot logs: sudo cat /var/log/letsencrypt/letsencrypt.log

The Takeaway

Adding SSL with Let's Encrypt is free and automated with Certbot. Install certbot, run sudo certbot --nginx -d yourdomain.com, and Certbot handles certificate issuance, Nginx configuration, and auto-renewal. After SSL, update your app to use secure cookies and HTTPS URLs. Always verify with certbot renew --dry-run that auto-renewal is working.

Install certbot (sudo apt install certbot python3-certbot-nginx), ensure your domain points to your EC2 IP, then run sudo certbot --nginx -d yourdomain.com. Certbot obtains the certificate and configures Nginx automatically.

Certificates expire after 90 days. Certbot sets up automatic renewal by default (runs twice daily via cron). Test renewal with sudo certbot renew --dry-run to ensure it will work when needed.

Set secure: true (HTTPS only), httpOnly: true (no JS access), and sameSite: 'none' if frontend and backend are on different domains (requires secure: true). Use sameSite: 'lax' if they're on the same domain.

Check that your DNS A record points to the correct EC2 public IP, wait for DNS propagation (up to 24 hours), ensure Nginx is running and the server_name matches the domain, and verify port 80 is open in your security group.

Yes, Certbot modifies the Nginx configuration to add SSL certificate paths, listen on port 443, and redirect all HTTP traffic to HTTPS. You don't need to manually edit the Nginx config for SSL.

Ready to master Node.js completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.