Migrating your WordPress website from HTTP to HTTPS

In light of #https2015 I flipped the switch on bram.us earlier today: from today forth bram.us is only accessible over HTTPS.

If you run a news site, or any site at all, we’d like to issue a friendly challenge to you. Make a commitment to have your site fully on HTTPS by the end of 2015 and pledge your support with the hashtag #https2015.

The switch itself should be transparent, as all “old” http:// URLs automatically redirect to their https:// counterparts.

When initially looking for information regarding this switch for WordPress sites I’ve found a lot of cruft out there. A rather high hit on Google was one dating back from 2006 (2006? … Chrome didn’t even exist for another two years) ; A few other ones recommend you to install a WordPress plugin which is just wrong (You really needn’t install a WordPress plugin to enable HTTPS!); A slew of other ones had it right, yet were incomplete; etc.

~

Here’s how to move your WordPress website from HTTP to HTTPS in just a few simple steps:

1. Install an SSL Certificate

Buy a certificate for your domain and activate it on the server. Most of the time your hosting provider offers a simple UI for this activation: paste in the private key, the certificate itself, and the CA-bundle. If you have to manually install it, I recommend taking a look at Mozilla’s SSL Configurator to get you started with the correct settings.

Note: Don’t let SSL Certificate Providers rip you off though. Services like sslcertificaten.nl or startssl.com offer them really cheap or even for free! Starting mid 2015 Let’s Encrypt will open it’s doors, offering free certificates for everyone.

You can safely install the certificate as your site will remain accessible over HTTP. In addition it’ll also be reachable over HTTPS. Verify this by manually changing the URL in the address bar from http://yoursite.com/ to https://yoursite.com/. Your website should appear, and the URL in the address bar should still hold the entered https:// URL.

Note that your browser will most likely not show the green lock icon next to the URL just yet, as your website will contain “Mixed Content”: the HTML of your site may be loaded over HTTPS, yet images contained may still be referred to using their http:// URL. We’ll fix this issue later on, in step 4.

https-mixed-content
Mixed Content warning in Chrome

Tip: Tools such as SSLLabs’ SSL Server Test come in handy to verify the proper installation of your certificate. Above that you’ll get a lovely report from it. Just one word of caution though: don’t run it on URLs used by your bank … those reports are mostly just depressing (sad but true)

Note: My first encounter with certificates back in the day had me confused about the CA-bundle. It took me a while to get to know that it’s no more than a text file containing all intermediate certificates, alle pasted one after the other.

2. Update the WordPress Settings

When having finished step 1 you’ll notice that next/prev links to blogposts and links to pages will still use the insecure http:// URLs. That’s because WordPress itself doesn’t know yet you’ll be using HTTPS from now on.

To let WordPress know you’re using HTTPS log in to wp-admin and under “Settings” → “General Settings” adjust the values for WordPress Address (URL) and Site Address (URL) to their HTTPS counterparts.

https-wordpress-settings
The WordPress Settings one needs to change

Once saved you should be able to start on your website over HTTPS and click through it – using the WordPress rendered links such as next/prev blogpost, pages, etc. – whilst remaining over HTTPS.

3. Force SSL for wp-admin

WordPress offers a setting to force the wp-admin only being accessible over HTTPS. To activate this edit your wp-config.php and add the following line:

define('FORCE_SSL_ADMIN', true);

Once adjusted you should be automatically redirected from http://yoursite.com/wp-admin/ to https://yoursite.com/wp-admin/. Whilst we later on (step 5) will redirect all traffic to HTTPS, it’s a good test before we change it all.

4. Fix those mixed content warnings

We’re almost to getting our site working entirely over HTTPS. What still remains is to update the content all our blogposts so that images referred, and blogposts linked (from within the content) use our https:// URLs instead of the http:// ones. Updating all blogposts manually would be a very time-consuming job. Luckily a single SQL query can this it for you.

Log on to PhpMyAdmin (or another tool which your hosting provider offers) and execute the queries below on your WordPress database.

Make sure you take a backup of your database first. If things were to go wrong you can always restore that backup.

Whilst at it I’ve also added a few extra queries to updating all internal pingbacks, and to updating all YouTube & Vimeo embeds.

# Update self-hosted embeds (images, iframes, scripts, etc.)
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://yoursite.com', 'https://yoursite.com');
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://www.yoursite.com', 'https://www.yoursite.com');

# Update internal pingbacks
UPDATE wp_comments SET comment_author_url = REPLACE(comment_author_url, 'http://yoursite.com', 'https://yoursite.com');
UPDATE wp_comments SET comment_author_url = REPLACE(comment_author_url, 'http://www.yoursite.com', 'https://www.yoursite.com');

# Update YouTube embeds
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://www.youtube.com', 'https://www.youtube.com');
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://img.youtube.com', 'https://img.youtube.com');

# Update Vimeo embeds
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://player.vimeo.com/', 'https://player.vimeo.com/');

# Update Flickr embeds
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://farm', 'https://farm');

# Update Slideshare embeds
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://www.slideshare.net', 'https://www.slideshare.net');

[UPDATE] Note: Whilst the internal pingbacks don’t trigger any Mixed Content warnings themselves, I thought of the update as being a bit of forward thinking: that way you don’t bounce back from HTTPS to HTTP. And whilst we’re in PhpMyAdmin anyway, I’ve added them right here.

Once executed the mixed-content warnings should be gone and the green lock should appear. Clicking from blogpost to blogpost should work just fine, all whilst remaining on HTTPS.

https-green-lock
No more mixed content: the green lock icon appears in the address bar

[UPDATE] To automatically scan one’s website for Mixed Content I’ve created a PHP CLI script that does the job for you. Check it out here.

If you do still get mixed content warnings (check for a little shield in the Chrome Address Bar) open the DevTools Console for more information: it could be – and I had this – that a CSS file still references an http:// URL. Manually fix all those errors one by one until you get the green lock icon.

https-green-lock-shield
A green lock icon is present, yet a shield (on the right) also appears. DevTools has more information needed for pinpointing the problem.

Do note that if you’ve included external resources (images/scripts/css/…) you may not be able to fix them all: if they’re not accessible over HTTPS, you won’t be able to fix that error.

5. Redirect all HTTP requests to HTTPS

Now that your site works fine over both HTTP and HTTPS, it’s time to flip the switch and make it no longer accessible over HTTP. Add these rules to your .htaccess:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

The rules are written in such a way that “old” http:// URLs will transparently redirect to their https:// counterparts. That way incoming links that still use http:// will keep on working just fine, but will get a security upgrade along the way.

6. Tweak your SSL Settings

If you want you can tweak some of your SSL settings, such as enabling only a strict set of ciphers. Whilst this is entirely optional, one tweak is recommended though: enabling HTTP Strict Transport Security (thanks for the tip @mathias!)

To enable HSTS, add this line to your .htaccess:

# Enable HSTS
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains" env=HTTPS

~

Following these steps you should be able to migrate your WordPress website from HTTP to HTTPS. It looks quite cumbersome, yet it’s done in no time (writing this blogpost took more time than actually rolling it out). Above that you only gain benefits from embracing HTTPS. And yes, TLS is fast.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)