Posted by & filed under Developer Blog.

It is obvious from the grunt-contrib-watch documentation that it is possible to get livereload working over https to avoid browser complaints such as Google Chrome’s blocked message “this content should also be loaded over HTTPS.”

What isn’t so obvious is how to go about getting it all working properly—especially to a front-end focused developer, who may not be familiar with server-side ssl, keys, and certs.

Create .key/.crt Files

For livereload to work over https, you need to provide a path to both a private key file and a certificate. These can easily be autogenerated using a CLI app called OpenSSL. There are other examples out there on how to do this with Windows, but for this example we’ll stick to Mac/Linux using Terminal. Note: in the following examples the files will be generated and saved to the current directory, so if you want it saved somewhere else, either move it after generation completes or cd (change directory) to that directory prior to executing.

A private key can be created using OpenSSL in Mac by opening terminal and using the following command:

openssl genrsa -out livereload.key 1024

The first step to getting a certificate is to create a “Certificate Signing Request” (CSR) file. This is done with:

openssl req -new -key livereload.key -out livereload.csr

Several questions will be asked, but many of them are purely optional. Fill out the minimum you care to include. These options are generally used for submitting the .csr file through a certificate verification process and using it in production. Since we won’t be submitting these or using them for production, it doesn’t really matter what you answer. For convenience, answer “localhost” for the Common Name.

Now, to finally create a self-signed certificate with the CSR, do this:

openssl x509 -req -in livereload.csr -signkey livereload.key -out livereload.crt

Now you should have 3 files generated. You really only need to hang on to 2 of them: livereload.key and livereload.crt. Copy or move those files into your project at a location accessible by your Gruntfile.js.

Configure Grunt Watch Settings

Follow the example for configuring livereload in your grunt-watch settings given in the documentation. For convenience, the example is copied here:

watch: {
  css: {
    files: '**/*.sass',
    tasks: ['sass'],
    options: {
      livereload: {
        port: 9000,
        // you can pass in any other options you'd like to the https server, as listed here:

A few things to note here:

First, you will notice that we didn’t set the port to the standard 35729 used by livereload; we used 9000 instead. This is intentional. If you have multiple watches or even the Livereload app running, you can continue to do so on over http (non-secure) on the default port without conflict. This has come in handy for me on multiple occassions, so I just recommend getting into the habit of using a different port, even if you never end up needing it.

Next, livereload uses its own key and crt files. These do not need to be the same key/crt used by your app. This is why there’s no real harm including it in your project. They aren’t valid keys and won’t be used anywhere else. Although you could use your same key/crt as your app, the pros outweigh the cons for not doing so. We’ll get more into those pros and cons in a moment.

Lastly, you don’t ever explicitly tell liverealod to use https. As long as you provide both a key and a crt it will automatically do so.

Enable Livereload Listener

If you are used to using a browser plugin to inject the livereload.js listener into your page, you will probably be as frustrated as I am that these all have hard-coded http:// paths and have no option for using https://. So, we are left with our only option, include the livereload.js listener manually. To do this, you must place the following script at the bottom of your page. I generally delete this line before pushing to production, which is why those browser plugins are so handy:

<script>document.write('<script src="https://' + ( || 'localhost').split(':')[0] + ':9000/livereload.js"></' + 'script>')</script>

Notice that we are including both https:// and our previously set port :9000 in this script. There have been cases where I’ve needed to hard code the host instead of letting this script inject it. For example, if I’m running livereload in localhost, but my page is being served in a development hostname then I would just hard-code localhost. The important thing is that it looks for livereload.js from wherever your watch server is serving it up, not from your app per-se. Make sense?

The Tricky Part

Because you are using a “self-signed” certificate to serve up livereload over ssl, your browser will be unhappy about it. Without the steps below, you will likely start seeing strange errors in our console and livereload will still not be reloading your content as expected.

We must first tell the browser we are cool with the self-signed certificate.

To do this, simply open a new tab in your browser and browse to your livereload.js being served up by grunt-watch. For example, you will likely go to the following url:


Now you can see right up front that your browser is scared to death. It’s ok, we don’t need to be. Just tell your browser you are cool with it and let it load that file “anyway.” Once you do, you will probably see the javascript contents of the livereload.js file being served to let you know your browser isn’t so scared anymore.

Head back to the browser tab you are developing from using livereload and refresh.

Note: If you are using the same key/crt as your app, you might be able to avoid this step (remember the pros/cons mentioned earlier). But chances are your livereload isn’t being served on the same host that your certificate was set up for, and the browser will complain anyway. I like my way better. Feel free to disagree.


Livereload should now be working for you over ssl without being blocked and without errors.