tobireif.com / posts

Switching to HTTPS

Why?

Chrome shows a "Not Secure" warning in the URL bar for all HTTP (non-HTTPS) pages. (info)

HTTPS (HTTP over SSL/TLS) is more secure than HTTP. (As a user you still have to make sure you're at the right domain ðŸ˜ƒ )

Service Workers "should be hosted over HTTPS".

The Web Share API requires "a secure context (typically HTTPS)".

For HTTP/2, HTTPS (TLS) is "de facto mandatory".

"Brotli availability is restricted to HTTPS connections."

If a site of yours is still being served over HTTP, here's one way of switching. Let's go!

Important Notes

HTTPS is supported by all current browser versions. Some obsolete browser versions don't support it, but they're obsolete.

Switching to HTTPS shouldn't negatively impact your Google ranking. And: Google says it uses HTTPS as a positive ranking signal (the effect might be small). But until Google finished indexing the new URLs there might be a negative impact on Google traffic/ranking.

If you have a huge complex website with many possibilities for non-HTTPS requests, you might want to consider doing the steps on a staging domain first.

For this howto, Chrome is assumed. Open the dev tools (eg on Mac do opt-cmd-j), then in the dev tool settings (accessed eg via the cog near the closing cross) make sure that caching is disabled.

In this howto, "example.com" always stands for the domain.

You might need to adapt some steps to your site setup. For example, in addition to searching through static files using grep you might also have to search through the respective database.

For each step: If it didn't automatically cover the subdomains, do it for them as well.

Change any same-domain URLs to Paths

In the local website directory, search for same-domain URLs:

(Make sure to replace "example.com" with your domain:)

grep -ri "example.com" *

If the URL is a ref/link, change it to a path. (If necessary test eg the ref/link.)

Update URLs pointing to other Domains

In the local website directory, search for non-https URLs:

grep -ri "http:" *

For each URL:

(Namespace URIs typically are not to be changed.)

(Should be changed to "https:" when it's a link, must be changed to "https:" when it's a ref.)

Make sure that it can be loaded via HTTPS, then make sure that the URL starts with "https:". (And also adjust the link URL that gets displayed on the page, if any.) If necessary test it: Make sure that the refd resource / linked page works using that updated ref/link/URL (also open the browser console and reload).

Set up an SSL (TLS) Certificate

In the hosting account, activate an SSL (TLS) certificate (it might be free / included in your plan). Another option to consider is Let's Encrypt (Wikipedia).

Ensure a Blank Slate

Chrome → click top right on the profile icon → cog → Add. As name have "DELETE_THIS_PROFILE", Save.

Use the new browser profile. Ignore the page content. Open the dev tools, open the network tab.

Enter the HTTP URL of your domain.

In the URL bar there should be the status for HTTP pages: "Not Secure".

Forward to HTTPS

For example if the site gets served by Apache: See "RewriteHTTPToHTTPS". For example add these lines to eg the .htaccess file, including R=301:

RewriteEngine On RewriteCond %{HTTPS} !=on RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]

If you use NGINX there's an example at Creating NGINX Rewrite Rules → "Forcing all Requests to Use SSL/TLS".

In the browser enter the HTTP URL of your domain (still do everything in the new browser profile).

In the dev tools network tab you should see (for the site index page) status 301, and in the next line (also for the site index page) status 200.

All is good: 301 is a good status code for the redirect, and 200 means OK.

(Make sure to replace "example.com" with your domain:)

Make sure that both URLs "http://example.com" and "https://example.com" can be entered. The "http:" URL should automatically change to "https:". Both should load the site, and there should be the HTTPS status in the browser's URL bar (eg a symbol → click → "Connection is secure") / there should be no text "Not Secure" in the URL bar.

Set the HSTS Header

From the Mozilla Developer Network page: "The HTTP Strict-Transport-Security response header (often abbreviated as HSTS) is a security feature that lets a web site tell browsers that it should only be communicated with using HTTPS, instead of using HTTP." (more)

For example if you use Apache ensure eg this (eg in the .htaccess file):

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" env=HTTPS

Enter the HTTP URL.

Now there might be a different status code in the network tab, eg status 307 - that's because of the HSTS header, and is OK:

Zineb Ait of Google says: Tweet 1: "The 307 is just an "internal redirect". The browser basically decides to not even try to call the HTTP version". Tweet 2: "It uses the 307 "internal redirect" to go directly to the HTTPS version, without talking to the server."

In the second network tab row for the site index page there should be status 200. And there should be the HTTPS status in the browser's URL bar (eg a symbol → click → "Connection is secure") / there should be no text "Not Secure" in the URL bar.

Delete the profile: Chrome → click top right on the profile icon → cog → the profile "DELETE_THIS_PROFILE" → three dots → Delete.

Check the Site

Navigate through a small but roughly representative subset of pages, using eg the website dir tree as list.

(Always have the browser console open. After opening the console, reload.)

For each of these pages (including the site index page) check the browser console, and check the URL bar: there should be the HTTPS status in the browser's URL bar (eg a symbol → click → "Connection is secure") / there should be no text "Not Secure" in the URL bar.

Also use jitbit.com/sslcheck.

Check the Setup

Open the dev tools security tab, reload, check the info. Also use ssllabs.com/ssltest (it seems "A+" is the highest rating).

Monitor the Site

Ideally ensure availability monitoring / "uptime monitoring". It should load a file from the domain, not just ping it. That should catch any major HTTPS/SSL/TLS request issues.

Monitor for Mixed-Content Warnings

If there's a risk that there will be non-HTTPS (HTTP) resources requested from your site in the future, do all you can to prevent that.

You also might have to monitor the pages for mixed-content warnings. There's an example described in this post about Moving the Washington Post to HTTPS. (In that post see the paragraphs containing "Selenium", "Content-Security-Policy-Report-Only" and "Sentry".)

Also see this page about CSP (Content Security Policy) → reporting.

The Apache line could look like this (untested) example:

Header always set Content-Security-Policy-Report-Only "default-src https:; report-uri /your/secure/and/locked-down/reporting-tool/"

Update the URL everywhere

Update any email signatures, and account profiles (eg the URL in the GitHub profile). Also consider the most important other places where the URL is used.

For each site where you might ref/link/feature the site, make sure that the URL starts with "https:". In each respective dir do this:

(Make sure to replace "example.com" with your domain:)

grep -ri "http:\S\+example.com" *

(Also do this for the site itself.)

If you have a sitemap, update it as well.

Google

If you're using "Google Search Console": See eg this guide → "create a new Google Search Console profile for the HTTPS version" etc. If you're using "Google News Publisher Center": If you're "making use of News sitemaps", contact the News team. If you monitor your Google traffic/ranking: If after 2-3 weeks you're (still) seeing issues, contact Google.

It's a Wrap

That's it! Chrome should be happy now ðŸ˜ƒ
And your users can enjoy a more secure data transfer.

P.S. HTTP/2

Your hosting provider might have automatically switched you to HTTP/2 when you switched to HTTPS. Here's an online checker. Or you can use Chrome's dev tools: network tab, reload the page, right-click (or eg on Mac ctrl-click) on a table header eg Name or Method, make sure Protocol is checked and present, check for protocol "h2" or eg "http/2".