So, after procrastinating for quite some time, I finally made the time to go about adding HTTPS to this website.
I have no major breakthroughs here, but a) I wanted to brag a little, and b) I wanted to highlight a couple issues I encountered, resources I found, and workarounds I used.
The set-up
First of all, I use Dreamhost to host this WordPress site. I try to keep up with the latest PHP and WP versions (currently using 5.6 and 4.3.1). My site is hosted on a shared server, and has unlimited storage and bandwidth. For the most part, since I switched from GoDaddy a couple years ago, I have been quite happy (I do have what I consider to be a rather slow TTFB, and I have not been able to track that down yet, but otherwise, I’m pretty happy).
But before we get started…
With no experience setting up HTTPS before, and not really being a server-admin-kinda-guy, I did some reading up first. Namely:
- The article that finally got me moving was WPMU DEV‘s How to Use SSL and HTTPS with WordPress.
- I also got a little encouraged by CertSimple’s Domain validated SSL will soon be free from the large CAs, which pointed me to…
- Let’s Encrypt, which made me want to learn more about…
- The various types of SSL certificates, which helped me to realize that Extended Validation Certificates were probably beyond my price range for this little blog, so instead I looked into…
- Domain Validated Certificates, but they apparently provide “little value that could not be provided by a self-signed certificate” (which are free), so that made me want to look into…
- The Self-Signed Certificate Generator, which gave me the private and public keys that I needed (Yay!), but then I realized I had no idea how to add these to my remotely hosted WordPress site…
- So I finally just Googled “Dreamhost WordPress add SSL” and found Dreamhost’s Wiki article Secure Hosting, which finally led me to…
- Dreamhost’s next Wiki article Adding an SSL Certificate…
- Whew! Looking back at this list, it really seems I could have gotten to that article title a lot sooner… :-)
Finally getting somewhere!
I had also previously read several horror stories of others converting to HTTPS, so I was prepared for this to completely suck. However, all-in-all, the process went pretty well! Several steps took a bit longer than the documentation led me to expect, and there is a point during Dreamhost’s process where you (surprise) need to have one of the very specific domain-based email addresses that they insist on sending the SSL’s validation email to (“for security reasons”, even though adding the SSL and accessing the validation email that they want to send can both be done in the exact same login session), but otherwise, creating and adding the SSL was pretty painless.
Not so fast…
When I logged into my WP Admin I got the following PHP error:
Warning: require_once(): https:// wrapper is disabled in the server configuration by allow_url_include=0
Doh! This error definitely did not exist prior to the conversion, so… Time to start digging…
From my slight Apache and PHP experience, I recognized that the phrase “server configuration” and the look of allow_url_include=0
would probably involve my server’s php.ini
file, but I also knew I wouldn’t have direct access to that file on a shared server. So, another quick Google hunt led me back to yet another Dreamhost Wiki article, appropriately titled PHP.ini.
Well, Dreamhost does not let me edit the php.ini
file for my shared server, but instead they offer a phprc
file, where I can add custom configuration lines, and they will be used as if they were part of the php.ini
file on any of my site’s pages. Sweet!
After a few seconds in FTP-land, I had my folders and file in place, and click Refresh and… no change, same error message. [Read back through the page again, double-check all my spellings, make sure I have the allow_url_include=1
override properly coded…] Nothing… [Finally notice the “Live Chat” link on Dreamhost’s admin page!]
After a few bits back and forth with a very helpful rep told me the obvious answer to the obvious problem that I actually already knew, but just didn’t think about: the server needed to be restarted. And I couldn’t do that via FTP, of course, but the rep could. Refresh again, and Voila!, error message gone! Thanks, Dreamhost support!!
Back on track! Sort of…
Now that my WP Admin was working properly again, I wanted to do a few cross-browser checks: FF worked beautifully, lovely little padlock; IE required me to turn on TLS (why is it off?) but then worked just fine; Opera also fine; then I tried the one that I typically expect to work flawlessly, Chrome, and… still saw that yellow “yield” sign… (facepalm)!
It was complaining about a script
that was still using HTTP as its src
… It turns out I had two settings in my wp-config.php
that I needed to change:
define( 'WP_HOME', 'http://'.$_SERVER['HTTP_HOST'] ); define( 'WP_SITEURL', 'http://'.$_SERVER['HTTP_HOST'] );
That hard-coded http
obviously needed to be changed to https
thusly:
define( 'WP_HOME', 'https://'.$_SERVER['HTTP_HOST'] ); define( 'WP_SITEURL', 'https://'.$_SERVER['HTTP_HOST'] );
And that fixed that!
Now we’re really cooking with steam! Well, sort of…
The final piece is the HTTP -> HTTPS redirect that I need to add to force all existing URLs to redirect users to my new, safe and shiny HTTPS URLs! After playing with a bunch of mod_rewrite
variations in my .htaccess
file, I finally stumbled across this little gem that does the trick:
<IfModule mod_rewrite.c> # enable Rewrite RewriteEngine On # make sure not already HTTPS RewriteCond %{HTTPS} !=on # redirect from original to same location using HTTPS RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] </IfModule>
Except… Luckily I remembered from some previous variation that the R
in the [R,L]
of the RewriteRule
makes it a 302
(meaning, a temporary redirect), so I had to change that to [R=301,L]
to make it a permanent redirect, and finally this little lovely gave me the final piece to my little odyssey…
<IfModule mod_rewrite.c> # enable Rewrite RewriteEngine On # make sure not already HTTPS RewriteCond %{HTTPS} !=on # redirect from original to same location using HTTPS RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L] </IfModule>
Safe and sound!
I now serve all posts, pages (even the few static ones I have), and admin sections via HTTPS, and old existing indices and links will be automatically redirected, permanently, to the new securely-served URLs. And that feels good. :-)
Update: Until the next morning…
The following morning I awoke to find this lovely message in my Inbox:
“Your total downtime was 1 year”… I think I would have noticed that… Anyhow, it made me realize that some services might bypass the .htaccess
redirect (like a ping
) and therefore… I really should update my database entries, too, changing all http://aarontgrogg.com
entries to https://aarontgrogg.com
…
The first step, of course, was backing up my current database.
After that, I looked around for good options to update all my tables (this is actually a Multisite installation). I found nothing except plugins that would make the changes as the content was requested, but I really didn’t want that overhead with every request, for now on. So, I started manually scrolling through my main site’s database tables, looking for fields that might logically contain my site’s URL.
It wasn’t a lot of fun, but I came across this list of SQL commands for my main site (you would need to replace wp_
with your table prefix, and domainname.com
with your domain name):
UPDATE `wp_comments` SET `comment_author_url` = replace(comment_author_url, 'http://domainname.com', 'https://domainname.com'); UPDATE `wp_comments` SET `comment_content` = replace(comment_content, 'http://domainname.com', 'https://domainname.com'); UPDATE `wp_options` SET `option_value` = replace(option_value, 'http://domainname.com', 'https://domainname.com'); UPDATE `wp_postmeta` SET `meta_value` = replace(meta_value, 'http://domainname.com', 'https://domainname.com'); UPDATE `wp_posts` SET `post_content` = replace(post_content, 'http://domainname.com', 'https://domainname.com'); UPDATE `wp_posts` SET `guid` = replace(guid, 'http://domainname.com', 'https://domainname.com'); UPDATE `wp_sitemeta` SET `meta_value` = replace(meta_value, 'http://domainname.com', 'https://domainname.com');
If you are using a Multisite installation, you will need to do all of the above, except the last one, for each of your Multisite sites, changing the table names for each.
Finally!
And this finally got my site all clean, set-up, safe and sound…
I hope this might encourage a few developers to take the same plunge, and hopefully also help a few either avoid, or at least get around, the issues I encountered.
Happy HTTPSing,
Atg
This is excellent information, I hope to use it in the future for my Dreamhost sites!
BTW, Dreamhost will be supporting Let’s Encrypt so free SSL certs for everyone!
https://www.dreamhost.com/blog/2015/12/03/lets-encrypt-and-dreamhost/
Thanks for the excellent information yourself, Micah! :-)
Hi Aaron,
If you want to do double-check your configuration, I can recommend the OWASP cheat sheet (https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet).
Also this SSL Server Test is pretty useful: https://www.ssllabs.com/ssltest/index.html
aaaaaaand, don’t use ModRewrite, Apache recommends Redirect:http://httpd.apache.org/docs/current/rewrite/avoid.html#redirect
Keep on going with your blog, I’m a regular reader and like it :)
Hey, Kai, thanks!
I had no idea there was so much involved with a SSL/TLS certificate! Mine did pretty well on the test page, only missing an old Android and IE8 on XP (not sure if SNI can be added to the cert I have or not).
Also, as this is a hosted site, I don’t seem to have access to the
httpd.conf
file (https://discussion.dreamhost.com/thread-5981-post-5982.html#pid5982), so I have to use.htaccess
…And good to “see” you again! :-)
This is neither Dreamhost- nor WordPress-related, but the subject (adding HTTPS to your site) is important enough that I want to help anyone that can use it, so here is Tim Kadlec’s post about adding a Let’s Encrypt SSL certificate to his Digital Ocean-hosted website.
Aaron,
Re: your TTFB problem if you still have it.
You might try the Comet Cache (my preferred WP caching) or other caching and Autopimize plugins in tandem. Works for me.
Thanks so much for posting that detailed step-by-step.
Am using it now to troubleshoot “what I did wrong” after changing _one setting_ within my WordPress site the official site URL after having gotten SSL certificates and turning on CloudFlare.
Doh!! Yeah, that can be frustrating…
Good luck!