What is Localhost? 🏠🔗
Localhost is a hostname that refers to the local machine currently making the request. On many computers, localhost is an alias for the IP address 127.0.0.1. When a computer pings this IP address, it is communicating with itself. Localhost is useful for software testing and security purposes independent of a larger network.
Now, why is it so important nowadays? 🤔
The HTTPS protocol is mandatory for any website or web application. It guarantees trust and security, and its wide adoption is due to the effort of browser providers and other supporters. Aside from providing critical security and data integrity for both your websites and your users’ personal information, HTTPS is a requirement for many new browser features, particularly those required for progressive web apps (aka PWA). However, many developers still use HTTP in their development environment.
So, why Use HTTPS during Local Development? 😮
Hopefully, you use HTTPS in your production environment since security is a primary concern for your web application. But why should you enable HTTPS in your local development environment? You are comfortable with your http://localhost
. What are the security concerns in your local environment?
Check out this blog post to learn more about how HTTPS works.
There are different reasons to enable HTTPS, even for your localhost. Let’s discuss some of them.
(1) ➤ Environment parity
The first and perhaps most logical reason is that the development environment should be similar to the production environment. This is one of the main principles of modern software development and deployment. It’s one of the tenets of the twelve-factor methodology : dev/prod parity. Having development and production environments configured similarly helps reduce the risk of experiencing issues in production that you cannot find in development.
For example, suppose you are using a JavaScript library from an HTTP-based CDN. Everything works as expected in your local development environment. However, in your HTTPS-based production environment, things may go differently. You have mixed content in your pages, i.e., your page is composed of content delivered through HTTPS and content delivered through HTTP. Browsers may refuse to load an HTTP-based resource from an HTTPS-based page. This is a security measure to prevent HTTPS downgrade attacks. It is just a simple example of an issue you can get only in your production environment. Other hard to detect problems could arise if you keep different protocols in the two environments.
(2) ➤ Strong security policies
Enabling HTTPS in your production environment isn’t enough to keep security for your application and the data it handles. It’s mentioned earlier that HTTPS downgrade risks your application may be exposed to. To enforce your application avoiding mixed content and blocking insecure requests, you should use Content Security Policy (CSP). This standard security layer helps mitigate certain types of attacks. In particular, it prevents possible unintentional protocol switches.
If you use CSP to prevent your application from switching from HTTPS to HTTP, you need to use HTTPS in both production and development environments. The CSP directives wouldn’t work in an HTTP-based environment. In other words, if you care about your application security in production, you can’t help but use HTTPS even in your development environment.
(3) ➤ Using specific browser features
If you want to use some advanced features supported by modern browsers, you need to use HTTPS in your local development environment. This applies to service workers, secure cookies, or prefixed cookies, for example.
Some browsers allow you to use plain HTTP by explicitly specifying localhost
or 127.0.0.1
as the host name while testing a service worker. However, this violates the environment parity principle discussed earlier. In addition, it is strongly discouraged by browser manufacturers.
(4) ➤ Custom hostname
Usually, you use localhost
as the name for your local machine. This is a reserved name and is mapped to the 127.0.0.1
IP address. Browsers treat it in a special way, especially in terms of security.
However, there are situations where you may need to use a custom hostname, such as myapplication
or myhost.dev
or maybe, something else. For example, you can use a custom hostname to rely on meaningful names to distinguish multiple development environments. You can do it by editing your machine’s ’hosts’ file.
⚠️ Warning: changing the content of your hosts
file may create access problems to certain Internet domains.
In this case, your browser won’t consider it a secure site, but it will when you enable HTTPS.
Other reasons 🌠
So far, you have learned about the most common reasons you should enable HTTPS in your development environment, but there are many more. For example, if you want to use HTTP/2 or if your third-party library explicitly requires HTTPS.
There are several reasons to change to HTTPS in your local development, but after all, the environment parity principle is the primary reason.
Some may think to start a new project with HTTP support and switch to HTTPS later when the project has grown. This approach is based on the common thought that switching from HTTP to HTTPS is painless. Learn about some of the issues that Stack Overflow ran into by reading the story of their migration.
Finally, how does HTTPS in Localhost Work? 🤩
The HTTPS protocol is an extension of HTTP. In HTTPS, the server and the client exchange encrypted data using the Transport Layer Security (TLS) protocol.
You don’t need to understand every little detail of the encryption mechanism for the purpose of this article, but a little basic terminology is necessary for what you’ll be doing next. For example, you need to know that data exchanged between the client and the server is encrypted using the Public-Key Cryptography, which is based on a private and public key pair. The server provides the client with its public key through a digital certificate issued by a Certificate Authority.
When your browser reaches out to an HTTPS-enabled web server, it receives the server’s digital certificate, which contains the server’s public key. The first thing the browser does is check that the server’s domain name matches the domain name in the certificate. This validation ensures that the public key comes from a trusted source. The browser also checks other things, such as the certificate expiration date and the Certificate Authority that issued that certificate.
In a production environment, you need a certificate issued by a real Certificate Authority. However, you can be more relaxed in a development environment and create your own certificate, known as your self-signed certificate.
A Practical Example: Node and HTTPS
Now you have a high-level vision of what you need to enable HTTPS in your development environment. Let’s put these concepts into practice by setting up a basic example using Node.js.
Each development framework may have its own procedures or tools. Please, check out your framework’s documentation for specific information. One thing that stays the same in all frameworks is the need for a private and public key pair and a certificate for the public key.
➤ Creating the certificate
Earlier you read that you could create your own certificate for your development environment. But how can you do it? The best-known and most powerful tool is probably OpenSSL. However, it requires a good knowledge of Public-Key Infrastructure concepts. In most cases, you don’t have advanced requirements for your HTTPS environment. So, using a simple tool like mkcert is a great choice.
Install mkcert
in your machine following the instructions for your operating system.
The first time you use mkcert
, you must run the following command to install a local Certificate Authority:
1mkcert -install
When running this command, you may notice a warning message like the following:
1Warning: "certutil" is not available, so the CA can't be automatically installed in Firefox! ⚠️2Install "certutil" with "brew install nss" and re-run "mkcert -install" 👈
This is related to supporting the trust store in Firefox. If you are not using Firefox, you can ignore this message. Chromium and Safari are expected not to log this message.
💡 Installing a local CA avoids your browser complaining that it does not trust the certificate you are about to create.
Once you install your local CA, you are ready to create a certificate and a key pair for your development environment.
I suggest you create a folder to put your Node.js project and the certificate. Say you named this folder dummy-test-app
, move to this folder and run the following command:
1mkcert localhost
After the command runs, you will find two files in your folder:
localhost-key.pem
, which is the file containing your private key,localhost.pem
, which is the certificate containing the public key.
➤ Setting up the HTTPS server with Node.js
It’s time to build your HTTPS-enabled server with Node.js.
In the same folder where you put the key and certificate files, create a server.js
file with the following content:
1const https = require('https');2const fs = require('fs');34const options = {5 key: fs.readFileSync('localhost-key.pem'),6 cert: fs.readFileSync('localhost.pem')7};89https.createServer(options, function (req, res) {10 res.writeHead(200);11 res.end("Neilblaze is HTTPS-enabled!");12}).listen(8080);1314console.log("Server listening to port 8080 with HTTPS enabled! 🎉");
The first line of the file imports the https
module, which is the key to this implementation. The options
constant gets the values of the private key and the certificate from the respective files. Finally, you create a server based on these options and listening to the 8080
port. That’s all!
Run the server with the following command:
1node server.js
Then, head your browser to http://localhost:8080. You’ll get a screen like the following:
This screen tells you that the server does not initialize a plain HTTP communication. If you change that address to https://localhost:8080, you will get the following page:
💡 This time the server replied to your request as expected. You are ready to develop your application using HTTPS.
Conclusion 🚀
Hopefully after reading this article, you should have learnt a few reasons why it’s a good practice to use HTTPS in your development environment. Moreover, you also learnt that you need a pair of cryptographic keys and a certificate to enable HTTPS in your development web server. Finally, you saw how to create a simple Node.js server that uses HTTPS.
I hope that you now have the initial understanding of how to configure and set up HTTPS in your local development environment.
That’s it for now! I hope you learned something valuable. Let’s make the Internet safer by using HTTPS everywhere! 🛡️