Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
AWS EB elastic beanstalk single instance nodejs nginx SSL/HTTPS ebextensions config file
# set the following configuration environment variables at: configuration -> software -> modify -> environment variables
# CERT_EMAIL: the email address used for registering the cert
# CERT_DOMAIN: the domain to create a cert for
# EB environment URL (listed at the top of the environment page) or a custom domain, custom domains must have a DNS CNAME record pointing to the EB environment URL
# !! MUST NOT have "http://" prefix or the trailing "/" at the end !!
# AWS resources to be provisioned for the EB environment
# define a SG inbound rule that allows HTTPS traffic to the EB instance
Type: AWS::EC2::SecurityGroupIngress
# added to the EB environment SG
GroupId: { "Fn::GetAtt": ["AWSEBSecurityGroup", "GroupId"] }
IpProtocol: tcp
# to (instance) and from (internet) TCP port 443
ToPort: 443
FromPort: 443
# any IP address source (public internet)
# add EPEL release package repo to yum for installing certbot dependencies
epel-release: [] # latest version
# create a custom nginx proxy config that will be targetd by certbot
# after certificate is issued certbot will populate this file with SSL terminating attributes
mode: "000644"
owner: root
group: root
content: |
# defines the nodejs server namespace listening on 8081
upstream nodejs {
# default port 8081, change if directly set in app code
keepalive 256;
server {
# capture all traffic on port 80 (http, unsecure)
# after cert success certbot will create a server block that redirects all traffic
# from port 80 (and 8080, default nginx) to port 443 (https, secure)
listen 80;
listen 8080; # default nginx service port
# define the server name so certbot can configure SSL after cert success
# this is either the EB environment URL or a custom domain
# custom domains must have a DNS CNAME record pointing to the EB environment URL
server_name `{"Fn::GetOptionSetting": {"Namespace": "aws:elasticbeanstalk:application:environment", "OptionName": "CERT_DOMAIN"}}`;
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/access.log main;
access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;
# location block to route access for ACME challenge
# certbot uses the endpoint /.well-known/acme-challenge/<CODE_FILE_NAME> during verification
location ~ /.well-known {
allow all;
# direct requests to the webroot where certbot creates the ACME challenge code
# this is the default webroot for AWS Linux AMI nginx
# any webroot can be used but must match the webroot param (-w) in the certbot command
root /usr/share/nginx/html;
location / {
# proxy requests + headers to the nodejs app server (namespaced from upstream above)
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;
# enable gzip compression for faster data transmission to clients of the nodejs app
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;
# script commands to setup and run the certbot process
# these are run in alphabetical order hence the numbering prefix
command: |
mkdir -p /opt/certbot
wget -O /opt/certbot/certbot-auto
chmod 700 /opt/certbot/certbot-auto
# make the default EB proxy conf a backup to prevent conflict with new conf
command: mv /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf.bak
# reload to use new conf
command: sudo initctl reload nginx
# run certbot process
# creates an ACME challenge in the webroot directory
# verifies the challenge with an http (80) request
# installs the certificate in /etc/letsencrypt/live/<DOMAIN_NAME>
# updates /etc/nginx/conf.d/http-https-proxy.conf to listen on 443, use the cert, and redirect all unsecure traffic (80, http) to 443 (https)
# --debug: required by AWS Linux AMI to install certbot deps
# --redirect: creates nginx port :80 -> :443 redirect rule on success
# --agree-tos: agrees to TOS without prompting
# -n: run without user interaction
# -d: set domain for certificate
# -m: set email for ACME account registration
# -i: select nginx as the installer plugin to update the conf file on success
# -a: select webroot as the authenticator plugin to use the ACME challenge
# -w: set the webroot path for serving the ACME challenge
command: /opt/certbot/certbot-auto run --debug --redirect --agree-tos -n -d ${CERT_DOMAIN} -m ${CERT_EMAIL} -i nginx -a webroot -w /usr/share/nginx/html --staging
# !! --staging: REMOVE FOR PRODUCTION, use the staging server for the certificate !!
# reload nginx to apply new conf
# depending on your AMI this may fail
# if it does replace with: service nginx restart or reload
command: sudo initctl reload nginx
# setup cron job to auto renew certificates
# 40_setup_cron_job:
# command:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment