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.

Elsewhere , , , ,

17 Responses to Migrating your WordPress website from HTTP to HTTPS

  1. One small clarification: “blogposts linked (from within the content)” don’t trigger mixed content warnings; only embedded resources such as images, scripts, stylesheets, and web fonts do. Of course, it’s still a very good idea to replace http://-links with their https:// counterpart whenever possible.

  2. Pingback: The Real Cost of the “S” in HTTPS

  3. Pingback: Mixed Content Scan: Scan your HTTPS-enabled website for Mixed Content | Bram.us

  4. Edge says:

    Nice Article.. Thanks.. Just what I was looking for to confirm my thoughts on how to switch over to https, plus the added tips for the htaccess… I found the procedure a bit more complicated in that I had hard coded embedded links to youtube vids, aweber mail lists, webchat client, and several other things, in many pages, that would not display in chrome and/or gave the all dreaded not all content secure button error in IE, that all needed changed to https as well, but all in all not a real difficult process..

    But since you took the time to create the article in the first place, just thought I’d take the time to say thanks and possibly add some helpful hints..

    Just as added precaution, along with the force admin, I also added this to wp-config.php.. Prop not needed, but doesn’t hurt anything either..

    define(‘FORCE_SSL_LOGIN’, true);

    Also thought I might suggest this link and tool that allows you to carry out database wide search/replace actions that don’t damage PHP serialized strings or objects, that your direct sql statements might.. I use this a lot to go back and forth between my localhost development and production site.. What a life saver!

    https://interconnectit.com/products/search-and-replace-for-wordpress-databases/

    This tool might also give you some hints on how to turn your mixed content script into a stand alone script that can be run by just navigating to a folder in your browser. I’m not sure you want to spend the time doing so, but it would definitely make it much more useful/useable for the non techy..

    A word to the wise.. Before running this script, or doing anything directly with your wordpress database.. Back it Up!!! I go one step further than that.. I export my working db, create a new db and import the exported one to it.. change my wp-config.php to point to my newly created db and run the script and/or do all my mods from it.. If all goes well, I just leave everything the way it is.. if for some reason something doesn’t work, it’s as easy as switching the wp-config.php back to the org db.. This is probably a redundant and unnecessary step, but personally makes me feel safer!

    Just my 2cents.. and thanks again for the article!

  5. Jamin says:

    Great Article!!! I got the full information about How to move http to https Protocol? But I have one question in my mind regarding this topic. After all setting of https in website then we need to change any setting in google webmaster too or not. If yes, then which set up will require for that.

  6. Thanks for this article.

    When I update WordPress Address (URL) and Site Address (URL) to their HTTPS counterparts.I am getting below error.

    The …. page isn’t working
    ….. redirected you too many times.
    Try:
    Reloading the page
    Clearing your cookies
    ERR_TOO_MANY_REDIRECTS

    I am running website on AWS, can you suggest me what should I do?

    Thanks

  7. Mavina says:

    And after making sure wordpress site is all good with SSL, what about google webmaster central and google analytics and SE rankings?. Any information and procedure around that area would help.

  8. Pingback: Come cifrare il tuo blog su WordPress. | …time is what you make of it…

  9. I was stuck after installing ssl in my website, and i was not working as i expected. your article helps me very much. Thank you Bramus for sharing.

  10. Rich Sale says:

    This is a really useful article.
    Have referenced it many times when design agencies struggle to get the migration to work properly.

    It is worth noting that you have to create a new property in Google Search Console for the https version of a site.

    thanks again

  11. Thank you for helpful post

  12. Debbie Lane says:

    Thanks … great post, very helpful. Got me over the last hurdle – the redirects.

  13. Kristine says:

    Hi Bram, thanks for simple step by step way to https.. I found many code to write on htacess, like this one:
    ——
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^yoursite.com [NC,OR]
    RewriteCond %{HTTP_HOST} ^www.yoursite.com [NC]
    RewriteRule ^(.*)$ https://www.yoursite.com/$1 [L,R=301,NC]
    ——

    What code should I use? In this case, I want to move https for (1) a brand news site (2) establish site.

    Thanks

  14. Kristine says:

    Hi bram, please reply.. what is the difference between your code and this one:

    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^yoursite.com [NC,OR]
    RewriteCond %{HTTP_HOST} ^www.yoursite.com [NC]
    RewriteRule ^(.*)$ https://www.yoursite.com/$1 [L,R=301,NC]

    Thanks

    • Bramus! says:

      Kristine,

      The code you’ve posted here does about the same as mine, except your code has extra checks in place so that only the domainname “yoursite.com” is matched.

      The code snippet I’ve posted works with all domains, and needs no editing.

      Regards,
      Bramus.

  15. Hi Bram.

    Thanks for the great tutorial, all good and just the right level.

    I just did a migration using a modified version of your script. The main changes are:
    – use wp-migrate-db to take a database backup
    – use wp=migrate-db to take detabase backup changing http://my-domain to https://mydomain
    – create new data base
    – import the migrated database into the new database
    – change the DB_NAME in wp-config.php

    This is much safer as wp-migrate-db understands serialized data and the old database is still sitting there on the server if anything seriously goes south.

    /peter

Leave a Reply

Your email address will not be published. Required fields are marked *