If you wanted to enable SSL for your website, it is the best time to do it - "Let's Encrypt" provides SSL certificates for free. This article describes how to setup SSL using certificate issued by "Let's Encrypt" for the Amazon EC2 instance and Amazon S3 bucket.
Part 1. Setting up SSL for the Amazon EC2 instance
The first thing you should do is to prepare your machine.
-
Install
Python 2.7and header libs:$ sudo yum install python27 python27-devel -
Update symlink to the
Pythoninstallation:$ ln -sfn /usr/bin/python2.7 /etc/alternatives/python -
Install
PIP:$ sudo curl https://bootstrap.pypa.io/get-pip.py | python2.7 -
Or update
PIPif you already have it installed:$ pip install --upgrade pip -
Update Virtual Environment:
$ pip install --upgrade virtualenv -
Create new virtual environment:
$ virtualenv -p /usr/bin/python27 venv27 -
Activate virtual environment:
$ . venv27/bin/activate -
If you don't have Git installed on your machine, install it:
$ yum install git -
Clone "Let's Encrypt" repo and go to the
letsencryptfolder:$ git clone https://github.com/letsencrypt/letsencrypt && cd letsencrypt/ -
If you have
Nginxserver running, stop it:$ service nginx stop -
Run
standaloneplugin to issue the certificate. Please note, that runningstandaloneplugin requires port80to be free (that is whyNginxwas stopped in the previous step) since this plugin will run the temporary server on it:$ ./letsencrypt-auto certonly --debug --standalone -d <domain-name> -
After last step you'll find 4 files in the
/etc/letsencrypt/live/<domain-name>:
cert.pem: Your domain's certificatechain.pem: The Let's Encrypt chain certificatefullchain.pem: cert.pem and chain.pem combinedprivkey.pem: Your certificate's private key
-
Now you need to edit
Nginxconfiguration file, setup certificate and write a rule to redirect fromhttpto thehttpsversion of your site:server { listen 80; server_name <your_server_name>; return 301 https://$server_name$request_uri; } server { listen 443 ssl; server_name your_server_name; ... add_header Strict-Transport-Security "max-age=31536000"; ssl_certificate /etc/letsencrypt/live/<domain-name>/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/<domain-name>/privkey.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:AES256+ECDHE'; ... } -
Open port
443in the security group for theEC2instance you are using in the EC2 management console. -
Great, now you can start the server and enjoy using
SSL:$ service nginx start -
Test the server for the
SSLconfiguration on the SSL Labs website. Probably, your mark will beB. This is because your server is vulnerable to theLogjamattack (more reading here, but this issue can be solved easily. All you need to do is just to generate strong Diffie-Hellman group:$ openssl dhparam -out dhparams.pem 2048And use it in the
Nginxconfiguration:server { ... ssl_dhparam {path to dhparams.pem} ... } -
Re-test the site using SSL Labs, now you should have
A+rating. -
Please note, that certificates issued by "Let's Encrypt" are valid for 3 months, so every 3 months you should renew them. You can take a look at the official guide for the details.
Part 2. Setting up SSL for the Amazon S3
If you are hosting static files on the Amazon S3 and would like to access the bucket using SSL with you domain name, this part is for you (please note, that by default Amazon S3 already provides SSL support for the buckets by using address https://<bucket-name>.<region>.amazonaws.com). For this part you'll have to use Amazon CloudFront service, please check the pricing.
-
Since you have no access to the
Amazon S3server, you need to usemanualplugin to generate the certificate (you should haveDNSrecord with statics sub-domain pointing to theAmazon S3bucket):$ ./letsencrypt-auto certonly --manual -d <your-subdomain-name>By using this plugin you'll be asked to place special file with a special string in the bucket. After verification is completed, you'll get the same 4 files as in previous part.
-
Install
Amazon Web Services CLI:$ pip install awscli -
Log in to the
Amazon IAMconsole. Now you need to create a user, just clickUsers->Create New Users. After user is created, save the file with its credentials (it will containAccess Key IdandSecret Access Key), then click on its name and copyUser ARN. -
The next thing you should do is to create the policy to upload the certificate. For this you can use policy generator:
Policies->Create Policy-> SelectPolicy Generator-> SelectAWS Identity and Access Managementin theAWS Servicedropdown and checkUploadServerCertificatein theActionsdropdown. In theAmazon Resource Name (ARN)pasteARNfrom the previous step. After the policy is created, attach it to the user.
-
Configure
Amazon Web Services CLI:$ awscli configurePaste
Access Key IdandSecret Access Keyyou've got on the step 3, other fields can be skipped. -
Upload certificate to the
AWS:$ sudo aws iam upload-server-certificate --server-certificate-name <certificate-name> --certificate-body file:///etc/letsencrypt/live/<subdomain-name>/cert.pem --private-key file:///etc/letsencrypt/live/<subdomain-name>/privkey.pem --certificate-chain file:///etc/letsencrypt/live/<subdomain-name>/chain.pem --path /cloudfront/certs/ -
Log in to the
Amazon CloudFrontconsole. Click on theCreate Distributionbutton ->Webdistribution.
-
The fields you should change/fill:
Origin Domain Name: click and selectS3bucket.Origin ID: type some unique name.View Protocol Policy:HTTPS only, but you can leave it as is if you want -HTTP and HTTPS.Alternate Domain Names (CNAMEs): type your sub-domain name.SSL Certificate: clickCustom SSL Certificateand choose the one you've uploaded at the step 6.Custom SSL Client Support: SelectOnly Clients that Support Server Name Indication (SNI). It is very important to choose this option, otherwise you'll be charged for ~600$ per month.
-
Click
Create distribution. After that you'll be given a link like<hash>.cloudfront.net. Please note, that it will take some time for the distribution to be created. -
Open console of your
DNSregistrar and createCNAMErecord with your sub-domain pointing to theCloudFrontaddress you've got at the previous step. That is it, now you have workingSSLforAmazon S3bucket with your sub-domain name.
Part 3. Troubleshooting
-
ERR_SSL_VERSION_OR_CIPHER_MISMATCH(Chrome)/ssl_error_no_cypher_overlap(Firefox) error while trying to access resource on theAmazon S3bucket using my sub-domain.Probably, you didn't fill correctly
Alternate Domain Names (CNAMEs)field for theCloudFrontdistribution. -
Website cannot be opened because of timeout error.
Probably, you forgot to open port 443 in the security group of the
EC2instance. -
Running
letsencrypt-autoreturnsImportError: No module named OpenSSLerror.Old Amazon AMIs have outdated
virtualenv, that is why you have to update it.OpenSSLmodule will be installed tolib64folder and this path is not correctly handled byvirtualenv. See https://github.com/letsencrypt/letsencrypt/issues/1680#issuecomment-170641501. You can check whereOpenSSLis installed by running:$ find ./ -type d | grep -i openssl