Add SSL Certification to EC2 WordPress Instance to use HTTPS

Add SSL Certification to EC2 WordPress Instance to use HTTPS

Using HTTPS in your apps and websites is becoming increasingly important. Using it gets you in the good graces of Google, keeps your customer’s data safe and secure, and (with Amazon Web Services) opens up the doors to efficiently load balancing your traffic. I wanted to add SSL to this website to not only get the experience and learn how to tackle the task with AWS but to also rake in that sweet SEO bonus (of course). So I wrote the steps I took (minus the 4 hours of banging my head on the keyboard) to get this successfully installed. It was great practice and a lot of fun despite the endless redirect loop that WordPress stumped me with, so I highly recommend it.

For this guide, we’re going to add SSL certificate to a load balancer that we’re going to put in front of our WordPress instance. We’re going to tackle all that entails, such as updating our DNS and Search Console, to configuring WordPress to properly handle the HTTPS traffic all the way through to your admin panel.

What does it mean to add SSL

Simply put, SSL is a way to encrypt all data sent from one server to another. Doing so useful for all sorts of reasons, including banks, online retailers, and all kinds of applications that handle sensitive and personal information. Web sites that provide SSL encryption are flagged with ‘HTTPS’ (the secured version of ‘HTTP’) and are reliable services. This increase in security is why Google now gives SEO weight to SSL encrypted websites – and why I wanted it here! So let’s get started!

Provision your SSL Certificate with AWS Certificate Manager

Before beginning this step, make sure that the WHOIS information for your website is correct and you have access to the email account listed.

The easy steps first: log in to your console and select ‘Certificate Manager’ from the list of available services. At the top, you want to ‘Request a certificate’ and enter the different domain names of the website you want to add encrypt with SSL. You can use wildcards as described in the examples on the page, so for this site, I set the domain names to www.davidmeents.com, davidmeents.com, *.davidmeents.com. Then click ‘Add another name to this certificate’ followed by ‘Review and request.’ Lastly, click ‘Confirm and request’ and on the next screen read the warning and click ‘Confirm.’

You’ll shortly receive an email sent to all the emails listed in the WHOIS information for your domain. Follow the directions in the email to confirm that you requested the SSL and you now have a certificate!

Add SSL with AWS Classic Load Balancer

Amazon Web Services makes the process to add SSL super easy. We’ll be putting a classic load balancer in front of the WordPress instance (created with EC2 ), and we’ll route traffic through it. We’ll offload the certificate at this presentation layer and then send the secured user down into our website. While provisioning the SSL through Amazon is free, creating the Load Balancer will inquire typical charges based on usage at the rate of 2.5 cents an hour. This comes out to be about $20 a month – which is steep for just providing SSL. However, the load balancer has lots of other tricks for making your application or website highly available. I would recommend looking into them to get the most value out of your ELB.

Provisioning the Load Balancer

First things first, go to your EC2 dashboard and select ‘Load Balancers’ and click ‘Create Load Balancer.’ You’ll then have to make a decision between an ‘application load balancer’ and a ‘classic load balancer.’ Despite the message that the ‘application load balancer’ is preferred for HTTP/HTTPS, we’re going to use a classic load balancer for this tutorial. Using an application load balancer would require us to offload the SSL certificate inside our application, which would be WordPress. I don’t know about you, but I would much rather not mess with that mess. Select ‘Classic Load Balancer.’ The ELB will handle the certificate and then pass the encrypted user down into our WordPress app with minimal effort on our part.

Load Balancer Basic Configuration

On the next screen, set the initial configuration for our load balancer. Give your ELB a friendly name that ideally matches the convention you’ve been using for your different architecture. For example, my EC2 instance for this website is called dpm-wordpress I named my ELB the same thing. By adding similar tags to all related resources, we keep everything unified and make our lives easier. Next, you are going to leave the ‘Create LB Inside’ setting to the default ‘My Default VPC.’ Leave the other options the same.

Lastly, on this page, we want to add a ‘Load Balancer Protocol.’ Click Add, and in the protocol drop down select ‘HTTPS (Secure HTTP).’ After clicking this button, it should auto-populate the load balancer port to 443 (the secured port used for HTTPS instead of 80). Leave the ‘Instance Protocol, ‘ and ‘Instance Port’ set to their default options (HTTP and 80) and click the next choice.

Setting the Security Groups and SSL

On the next screen, you’ll select your security group that you assigned to your WordPress EC2 instance. For the sake of thoroughness, your security group should allow inbound traffic through the TCP Protocol on the Types and Ranges: HTTP / 80, SSH / 22, and HTTPS / 443.

After selecting your desired security group click next and on the next screen you’ll be setting the SSL certificate. In the ‘Certificate type’ section select ‘Choose an existing certificate from AWS Certificate Manager (ACM).’ Then (naturally) select the certificate you just created. In the last section leave the ‘Cipher’ settings to the defaults.

Add your WordPress instance and Create a health check

On the next page, we create the health check for our load balancer. The health check will ping our WordPress website on the port and protocol that we specify. Select ‘TCP’ from the ‘Ping Protocol’ and change the port to ‘443’. As we’re only load-balancing a single WordPress instance, I upped the ‘Interval’ to 60 seconds and left everything else to their default values. Next, select the EC2 instance where you have your WordPress website installed, and leave the ‘Availability Zone Distribution’ to its defaults. Give your load balancer a tag called ‘Name’ and pop in your naming convention one more time for good measure. This websites name tag is of course ‘dpm-wordpress’. After a quick review of all the settings, click Create!

Note: your classic load balancer is going to fail its health check and mark your instance status ‘OutOfService’. It fails because we haven’t finished configuring WordPress or your DNS to accept encrypted traffic sent from the 443 port.

Configuring WordPress for HTTPS sent from a Load Balancer

The next step to add SSL is arguably the most difficult – but we’re not going to have any problems. You’re almost there! The first thing we want to do is FTP into our WordPress instance where we’ll be editing the .htaccess and wp-config files. If you’re using the Bitnami WordPress installation (which I highly recommend!), you can find these files at /opt/bitnami/apps/wordpress/htdocs.

Always take the proper precautions when editing these critical WordPress files. Create backups!

Add an Apache Rewrite Rule to WordPress

Save your progress: following this tutorial any further will cause your website to no longer function properly until the rest of this tutorial is completed. I recommend reading the rest thoroughly before making these changes. Should you run into any issues, you can just undo these steps, and everything should return to normal.

Open up your .htaccess file first and let’s add in the rewrite rule we’re going to use to direct all inbound traffic ‘HTTPS’. Because our load balancer is taking all traffic handling it on port 443 and encrypting it before sending it down to our WordPress instance on port 80, we want to ensure that WordPress continues to honor the ‘HTTPS’ protocol and exclusively use only that. At the very top of this file, before anything else, add the following rule. Be sure to replace ‘your-domain’ with your actual domain name.

Easy as that you just added an Apache rewrite rule to take all traffic and direct it towards the HTTPS URL.

Force SSL on the admin pages

We also want to encrypt and use HTTPS on the WordPress admin pages. To do so open up your wp-config file and add in the following code underneath the ‘MySQL settings’ – but be sure to keep the code above the comment that says ‘stop editing’.

Two different things are happening here. The first one is we’re telling WordPress to use SSL for the admin pages. The next command prevents us from getting stuck in a never ending redirect loop. If you remember, we are taking all traffic to our website through 443, offloading our certificate, and then pushing it down into our WordPress application on port 80. Then, since we’re forcing SSL, WordPress tries to redirect us back to port 443. And so on, and so on. This second command checks the headers of the user as it enters the website to validate if it’s already coming from HTTPS and stops this redirect loop.

Lastly, a little bit further down we want to change the default WordPress site URLs. Sometimes this can be done from the admin control panel, but it’s just as easy to change it here in the wp-config file since we have it open. Scroll down to the appropriate section and just add in the ‘s’ in front of ‘HTTP,’ like so:

Save all of your changes and let’s jump back into our Amazon console to make some DNS changes.

Updating your DNS to point to the Load Balancer

At this stage, if you try to access your website you’re going to get a nasty error saying that your site isn’t secure. This error is because we are redirecting all of our traffic to ‘https’ without sending along the SSL certificate. So what we need to do now is point our DNS records to our load balancer, which will then take all the traffic, offload its SSL certificate, and pass it along properly to our website. We’re going to assume you’re using Amazon’s Route 53 for this task as well. However, the process should be similar to any DNS service.

Go to Route 53 and select your WordPress site out of the ‘Hosted Zones’. You want to update your ‘A’ records to point to the load balancer we made, and luckily for us, Amazon makes this ridiculously easy. Select the A record and then change the Alias from ‘no’ to ‘yes’. You should be presented with a list of load balancers – just select the right one. Be sure to update all of the A records you have. The DNS changes should only take a few moments but could take up to an hour.

That should be it! Your load balancer should be passing its health check, and your website should secure. If you’re still having issues with your connection not being private, try emptying your cache, retyping in the domain name, or waiting a little longer. If that’s not working – leave some details in the comments below, and we can try to get it working!

Last steps and getting SEO ready

There were some small things I did after updating my domain to HTTPS. Since I was mostly concerned about any SEO benefit (at this time) I wanted to make sure that Google was aware of my now nicely encrypted website. What I found out was that in the Search Console you need to have all variations of your site listed. For example, ‘http://www.davidmeents.com’ and ‘http://davidmeents.com’. This requirement means that you need to also add the ‘HTTPS’ versions of these two. Your WordPress site should have four properties when complete.

You’ve successfully gone through all the steps required to add SSL! I spent a good amount of time compiling this and getting stuck with redirect loops at every turn when I did it the first time. So hopefully I saved you some time, or solved your frustrating problems! Either way, please let me know in the comments if you have questions.

Most likely it could be your browsers cache – it’s working great for me! Nice job randsroark!

randsroark

Thanks for the reply. It was a mixed content issue. WordPress was calling the logo and a background image insecurely. Probably because they were hard coded that way in the theme settings.

Adca

I got the same Issue.. I’m still looking for the insecure content, how did you do to find exactly which insecure content is running?

lora

Thank you for this guide– was super straightforward.
I am having an issue though– everything works when when the url is input as http://www.domain.com, forwards to https://www.domain.com just fine, checks out with browser. But, when i input the domain.com without the www, it redirects to https://domain.com but is still considered “not secure.” I roamed the internet for a solution (serverAlias virtual host, etc) but not sure if i’m putting this in the right places because either nothing has worked or I am missing something because having no luck. I have my domain registered at godaddy and everything else on AWS. Should I change DNS records on both AWS and godaddy? Tried and failed on many fronts… any advice?

Hey! Thanks for asking! It is likely that the certificate you made was only for http://www.domain.com not the non-www url domain.com. Without the ‘www’ the certificate won’t recognize https://domain.com as a secured address.

AWS makes it super easy to just swap out a new certificate into your loadbalancer. Or you can write some fancy rewrite rules to get all of your non-www traffic to route to www. But that’s a pain and in my experience isn’t the best route.

I’d recommend just making a new certificate, and make sure to add both ‘*.domain.com’ and ‘domain.com’

Thanks for reading!

lora

Hi, thanks! So I did have additional names for the original certificate (www.domain.com with additional names ‘domain.com’ and ‘*.domain.com’). Seeing this though I created a new certificate so domain.com was the main certificate name and the other two were additional. Switched the certificate on the load balancer, and now neither the www nor the non-www will redirect correctly (both are marked as “not secure” by the browser. Was there another step? Should I just delete everything and start again?

Hm, that’s strange. Nothing is coming to mind as possible solution, I’m sorry! I feel like the issue is still in the certificate, so destroying it all and starting over likely wouldn’t solve anything. Best of luck, if you find out what caused it please let me know!

Jenny Smith

Hey! Did you find the solution to this issue? I am having the same problem now…any suggestions?

The only difference between your instructions and my deployment is that I got my Domain from google and not aws.
In fact, the error actually makes sense to me – as when I try to go to my site, I get redirected to the AWS domain name(which I setup using subdomain forwarding in google domains console).
Now since the certificate indeed only had mydomain.com, http://www.mydomain.com, it is kind of expected that this error will be returned.
Did I miss a setting somewhere which is causing this behavior?
Any help is greatly appreciated.

Hey Nikhil, I take it your managing your DNS with Google as well. Have you created an Elastic IP Address and attached your server to it? This Elastic IP address is what should be the value for your A records. It sounds to me like you’ve set the A tag to direct to the public DNS name of the EC2 instance, not the instances IP address.

Nikhil Tayal

Thanks you so much for the prompt response David!
Your observation was spot on.

In my case, I had to add a custom resource of CNAME resource type to redirect to my load balancer’s domain name. Originally I had set up subdomain forwarding which is different than adding a resource as forwarding only does a redirect to a different domain but what I really needed for SSL to work correctly was to add the new AWS LB domain name as a resource to my registered/certified domain.
In case someone else gets stuck at the same step or comes looking for how to do this with Google domains, here is what I followed:http://stackoverflow.com/questions/32467541/link-a-google-domain-to-amazon-ec2-server

After following your suggestion, I was able to get past the Bad certificate error and see the secure sign if I access the site using https.
However, I am still getting insecure site if I don’t specify https:// to access my site. The instructions you provided outline how to automatically forward all http requests to https on the application instance. Is there some similar setup required on the load balancer as well?

Also, I am using the same security group(which accepts inbound connections from port 80 and 443 from anywhere) for my load balancer as well as the instance.
I feel like I can restrict the ports 80 and 443 on the instance to only accept traffic from the load balancer, Do you think it is a good idea?

Rick Bronkhorst

Hi David & Nikhil. I’m using Cloudflare as well. Initially I used it for the SSL Certificate with the bonus of a speedy delivery of the site to South Africa as Amazon does not have any zones in Africa.
I’m using the Elastic IP address in Cloudflare but get the following error when loading the page in Chrome.

Hey Rick, thanks for reading. Unfortunately I can’t say for certain why you’re getting these errors. The ‘too many redirects’ one is most always an issue with the .htaccess or apache server settings. I ran into it a couple times when my load balancer was taking traffic on port 80 and directing it to port 443 (where my server lived), but then my apache server was routing back to 80. It was just an infinite loop. Since really the only we changed here in this tutorial was the .htaccess I’d take a look into that, and make sure everything looks good.

As for the internal error or misconfiguration issue, that really could be anything – syntax error in your apache files maybe? Apache normally tries to catch those before it starts again though. Sorry I’m not much more help on that one.

Adca

Thanks so much for this guide!!
I have an issue.. I didn’t find the ‘.htaccess’, so I created a new one in the folder were is wp-config.php. But it doesn’t work. What do you think?

I create the links with loadbalancer and I connect everything selecting instead ‘TCP’ -> ‘HTTP’ from the ‘Ping Protocol’ and I left the protocol in 80. So I didn’t modify the .htaccess and wp-config.pho file and is working. However, is working the insecure page at the same time and I think is because that..
Helpp!

Adca

All working perfect, the problem was the port! Thanks for the guide was awesome.

Saul Andrade

David, thank you so much. I’m new to aws and your guide sure made my head hurt less when dealing with wordpress. A word of advice for the other newbies, make sure you use bitnami wordpress instance, it saves a lot of work. I tried to install wordpress from scratch and, even though I was successfull, things got nasty when applying the certificate to it…definitely not whorthwhile.

Saul Andrade

One quick thing…to avoid elb infinte redirection loop one should use the following RewriteCond on https-prefix.conf:

Thanks for the tutorial, David!!! If anyone else experiences the issue of getting a HTTP 503 ERROR when trying to redirect their WordPress site to https, the issue is with the health check. David nailed it on the head when he said to use TCP for the health check Protocol and 443 for the port. If you don’t use these ports, AWS will think that there is something wrong with your instance and will disconnect the instance from the ELB (elastic load balancer), causing the 503. This (the 503) only happens after you change WP_SITEURL to use https.

Torsten Engelbrecht

Thanks for the guide David. For me the article worked for most of the part, except when I changed the last steps outlined (changing htaccess and wp-config). So I did a few things different:

This will pretty much take care of the correct redirect to HTTPs for all URLs of the blog. I did not have to edit my wp-config file at all after that (even not adding https for WP_SITEURL and WP_HOME.

Another thing I did different is that I left the Health check to use port 80 and HTTP. Actually I don’t believe port 443 would have worked at all as long the there is not SSL certificate installed and used on the instance itself. The instance is supposed to run on port 80 and the load balancer does all the HTTPS action.

Hi Guys,
Everything worked out for me. My site is working with https.
But it gave a problem. When we type agencia61.com.br, it adds at the end “/? V = 19d3326f3137”, that is, the complete URL is “https://agencia61.com.br/?v=19d3326f3137”.
Is this right? How do I get it off?
Thank you all

Steeve Roucaute

Hi David,

I did follow your instructions to the letter, but unfortunately my instance stays out of service. I did try to create a “healthy.html” file and change the health check to HTTPs instead of TCP 443 but no luck either. If I try to access the instance direct via HTTP, the site is being served. However, when trying to get the admin login page, I get routed via HTTPs and I am getting an error saying “This site can’t be reached, ERR_CONNECTION_CLOSED”.
Any idea?
Steeve.

Saroz Saroz

Hi David Meents,
Thank you very much and its very usefully.
HTTPS and HTTP both working good.
but when using HTTPS(its in secure connection with green color lock icon), wordpress theme not loading properly. HTTP its loading fine.
can you/anyone help me out from this task.
Thank you advance

I am really glad you were able to figure it out! I was scratching my head on this one for a bit. I know I had some issues with images and icons not loading because of mixed content.

You’re very welcome! Thank you so much for your kind words and reading!

VandergenBlog

Resolved: Thanks to @disqus_6cqSz5b8VS:disqus for the direction and @emeentsmedia:disqus for the perfectly written instructions!
It was a mixed content issue and I found it by running my site through the link below:https://www.whynopadlock.com/check.php

Sumit Rathore

Hi David,
Thanks for writing such a detailed post. Its really good.

I have followed it all, and made all the config changes. But still my site do not load when I am pointing my A-Name record to this newly created load balancer. It just doesn’t shows anything.

The one thing, I can notice in my load balancer is, that for “Instances’ , the status is shown as “OutOfService” , against my instance ID.

Whereas my Ec2 instance is running and I can still access the site, If I directly hit the IP. I have alse checked the health check record on Ec2 and its all good.

I hve the Route 53 setup with all the required configs. One other problem I have is :-

I have a domain name (Eg: http://www.myurl.com) and my website is running in an Elastic Beanstalk instance on AWS EC2.

I have created a hosted zone and made all the entries for pointing my domain to my EC2 instance.

Everything works fine, but the only problem is , when I hit my domain url (www.myurl.com) , the website loads from EC2 but the url also changes to the EC2 url, something like (http://someec2.url.aws.com)

How can I keep my url (www.myurl.com) in the browser, while the website still loads from ec2 and restrict to show the ec2 url.

A record – an alias record for (mysite.com) pointing to existing A record ((www.mysite.com)

CName – I tried creating a cname record instead of A-record, but it also didn’t work
But still when I hit my website (www.mysite.com) , the url in browser changes to (myec2 url) .Am I still missing something.

Hey Sumit, thanks for reading! It sounds like the healthcheck on your load balancer isn’t configured. Make sure the healthcheck is pinging the “/” target on port 8080 with the TCP protocol. Then after waiting a little while you should see your instance become available through the load balancer.

Hey everyone… so I’m having a bit of a problem I could use a hand with. I went through all these steps, and even went through and made sure I removed all my http linked assets (icons/background/etc), but I think that bitnami is causing problems.

When I load the “network” tab in chrome developer tools, I’m getting two errors in chrome which is causing the dreaded red “Not Secure” triangle. It reads: “Subject Alternative Name Missing” and “Certificate Error
There are issues with the site’s certificate chain (net::ERR_CERT_AUTHORITY_INVALID).” When I view the details of the certificate, it still is showing “www.example.com” as the “Issued To” and “Issued By”…. aka I think for some reason, bitnami is still trying to use my “local” SSL certificate instead of using the one AWS is passing through.

Any ideas?

James Sullivan

As a side note… if I uncomment the “Include conf/extra/httpd-ssl.conf” line in my httpd.conf in apache, then bitnami redirects me to a “Awesome! WordPress is now installed.” page… also still without https 🙁

James Sullivan

After beating my head into the wall for a few hours… but mostly after a short break, and a beer, I finally figured it out.

In my case, I had to remove the redirect from the .htaccess file, so that it didn’t give me a redirect error. I think something in my apache setup is causing it to already be configured to redirect, so it was creating a loop….. oh well.

Hey James, sorry for the delayed response! I am glad you figured it out – I have to say that the solution was not what I would have expected!

Thanks again for reading and posting your experience here and happy coding!

Sam

Hi @emeentsmedia:disqus , great tutorial! Thanks for that. I followed everything here but having trouble with redirecting pages on my website. I used the exact redirect rule in .htaccess that you mentioned. My site is livelikeanegyptian.com if you try going there you get directed to the https version. However, if you try goinng to livelikeanegyptian.com/blog you stay on the http version. Any idea why? Do I need to modify that redirect rule? Thanks!

Sam

Extending this to the broader community if anyone could help, please. Thanks.

Rasmus Friis

Thank you very much for this tutorial. All is working now……

shani shahid

Hi I just have error that my site is not secure. In the route 53 I unable to Find record A, so I added .

David, I got to the last step where you update your DNS and point to the load balancer. Our DNS is managed through Network Solutions, and the options for editing the A Record is completely different. Any help?

Subscribe to my mailing list

View older content

Keeping the lights on

To put it simply, I want to make a little extra to justify the amount of time and effort I put into this website. I love writing these tutorials, so every bit helps make it possible. Don’t worry, my advertising will never become intrusive. I value your readership and thank you for your support!