Using HTTPS on Next.js local development server
Tags: nextjs, https, local, development
Published: 2021-03-03 12:04:14

In today's world, HTTPS is everywhere.
So we should keep our development environment the same as the production environment. Because some things may not work in HTTP but work in HTTPS and vice versa. 

The Next.js development server runs on HTTP by default. In this post, we will discuss how to run the Next.js development server on HTTPS. 

### Prerequisite: 
First, we need to get an SSL certificate. [Mkcert](https://github.com/FiloSottile/mkcert) is the recommended option here which is simpler than the alternatives.
**mkcert** will create a **CA** and **SSL Certificate** for the servers for us. We will explain later how they work.

So first we need to **install** [mkcert](https://github.com/FiloSottile/mkcert#installation). 

After installing, we will **generate a CA** i.e Certificate Authority first. 
`mkcert -install` will do this. 

Then, **we have to generate a certificate for specific servers**. 
let we want to generate a certificate for `localhost` since most of the time we use this as a server. 
Here, `mkcert localhost` will do this. 
This will generate a **certificate** and a **key** named as *.pem and *-key.pem respectively. 

### The CA and Certificate(with the key)
The client( Browser or tools like postman) uses the CA certificate to authenticate the CA signature on the server certificate, as part of the authorizations before launching a secure connection. [Courtesy: [Wikipedia](https://en.wikipedia.org/wiki/Certificate_authority)]

So on next.js, we will create a custom server with the **certificate( \*.pem )** and **key( \*-key.pem )**. This server will run on **HTTPS!**.
We have explained how to create the server with code in the next section.

The client such as Browser(Chrome, Firefox) or tools like Postman will use the CA to verify the Certificate of the server. The CA's are stored on Browser's **trusted root store**. Fortunately, we may not need to add the CA to the **trusted root store** for Chrome or Firefox. The **mkcert** does this. We just need to restart the browser. If for some reason it doesn't work then we need to add the certificate to the **trusted root store** manually. Hope we don't need this extra task :) :)

But in case we need to add the CA file manually to a browser or tool, first, we need to locate the CA file. 
This can be done by `mkcert -CAROOT` command.
It will show the directory location where the CA is stored. There will be a certificate with a key. This key shouldn't be shared with others. The directory may be hidden. In that case, we may need to copy the files to another directory so that browser or other tools can locate the files. 

To add the CA on **postman** you only need to add the certificate, not the key. See it [here](https://blog.postman.com/encryption-ssl-tls-and-managing-your-certificates-in-postman/#:~:text=You%20can%20manage%20CA%20certificates,domain%2C%20you%20can%20upload%20the%20.)

<br/><br/>

### Creating the Next.js Custom Server(which runs on HTTPS!)
First copy the **certificate( \*.pem )** and **key( \*-key.pem )** to a directory on the next.js project. Let the directory is on the project root and named as **https_cert**.

Now create a file named **server.js** on the project root and paste the following configuration. **Don't forget to change the certificate and key name according to your certificate and key on httpsOptions**. 

```javascript

const { createServer } = require("https");
const { parse } = require("url");
const next = require("next");
const fs = require("fs");
const port = 3000;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

const httpsOptions = {
    key: fs.readFileSync("./https_cert/localhost+1-key.pem"),
    cert: fs.readFileSync("./https_cert/localhost+1.pem")
};

app.prepare().then(() => {
    createServer(httpsOptions, (req, res) => {
        const parsedUrl = parse(req.url, true);
        handle(req, res, parsedUrl);
    }).listen(port, (err) => {
        if (err) throw err;
        console.log("ready - started server on url: https://localhost:" + port);
    });
});

```

Now on the terminal, run `node server.js`. 
This will start a server on https://localhost:3000. 

If there are [API routes](https://nextjs.org/docs/api-routes/introduction), then these will be available on https://localhost:3000/api/*.