# How to set up local SSL with Next.js

### Summary

This guide will teach you a cross-platform solution on how to add local SSL in a Next.js project.

The name and file structure used here is not mandatory. You can name files or reorganize the folder structure however you see fit.

#### Before we start

We'll create a new Next.js project using `npx create-next-app`.

---

#### Step 1

We'll use [devcert](https://github.com/davewasmer/devcert) to automatically generate certificates for us. It automates almost the whole process and works on every SO. Refer to its documentation to see how it works.

Add it to your project as a devDependency.

```plaintext
yarn add devcert --dev
```

---

#### Step 2

Create a `scripts` folder in your project.

Create a new file `create-ssl-certs.js` inside the scripts folder:

```plaintext
const devcert = require('devcert');
const fs = require('fs');

if (!fs.existsSync('./certs')) {
  fs.mkdirSync('./certs');
}

const domains = ['my-cool-domain.local'];

devcert
  .certificateFor(domains, { getCaPath: true })
  .then(({ key, cert, caPath }) => {
    fs.writeFileSync('./certs/devcert.key', key);
    fs.writeFileSync('./certs/devcert.cert', cert);
    fs.writeFileSync('./certs/.capath', caPath);
  })
  .catch(console.error);
```

Change `my-cool-domain.local` to the domain you wish to use. You can pass multiple domains if needed.

The script automatically creates a `certs` folder and generates the certificate files, plus another file with devcert's caPath, which we'll need in Step 6.

---

#### Step 3

Add a new script to your `package.json`:

```plaintext
"ssl:setup": "node scripts/create-ssl-certs.js"
```

---

#### Step 4

We don't want to push locally generated certs to the repository.

Add the `certs` folder to your .gitignore

---

#### Step 5

Run `yarn dev` and try accessing [http://my-cool-domain.local:3000](http://my-cool-domain.local:3000).

You'll notice it's accessible, and that's because devcert automatically added an entry in `/etc/hosts` for you.

It doesn't have SSL enabled yet though, as we haven't setup Next.js to use those certs yet. In order to do that, we need to create a local [custom server](https://nextjs.org/docs/advanced-features/custom-server).

---

Install `chalk` as a devDependency

```plaintext
yarn add chalk --dev
```

We will use chalk to create a nice error message for developers who try to run the project without setting up SSL first. This is entirely optional.

---

Create a new file `create-local-server.js` inside the scripts folder

```plaintext
const { createServer: createHttpsServer } = require('https');
const next = require('next');
const fs = require('fs');
const chalk = require('chalk');

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const PORT = process.env.PORT || 3000;

if (!fs.existsSync('./certs/.capath')) {
  const macOsCommand = chalk.greenBright('sudo yarn ssl:setup');
  const linuxCommand = chalk.greenBright('yarn ssl:setup');

  console.error(chalk.red('\nError: Missing SSL certificates\n'));

  console.error(`To fix this error, run the command below:`);
  console.error(`→ MacOS: ${macOsCommand}`);
  console.error(`→ Linux: ${linuxCommand}\n`);

  process.exit();
}

app
  .prepare()
  .then(() => {
    const server = createHttpsServer(
      {
        key: fs.readFileSync('./certs/devcert.key'),
        cert: fs.readFileSync('./certs/devcert.cert'),
      },
      (req, res) => handle(req, res)
    );

    return server.listen(PORT, (err) => {
      if (err) throw err;

      console.log('> Ready on https://my-cool-domain.local:3000')
    });
  })
  .catch((err) => {
    console.error(err);
  });
```

---

#### Step 6

Update the `dev` script in your package.json:

```plaintext
"dev": "NODE_EXTRA_CA_CERTS=\"$(cat ./certs/.capath)\" node scripts/create-local-server.js",
```

#### Why do we need NODE\_EXTRA\_CA\_CERTS?

Node does not use the system root store, so it won't accept devcert certificates automatically. This might not cause any apparent issue at first, but it will cause errors when using [Next.js's Image component](https://nextjs.org/docs/api-reference/next/image).

You'll see `500 internal error` page when trying to load a `_next/image?url=...` route, and `UNABLE_TO_VERIFY_LEAF_SIGNATURE` errors on the console when trying to load images if you don't pass the `NODE_EXTRA_CA_CERTS`.

---

#### Step 7

Run your project using `yarn dev`

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630986904417/qhnuWul7Q.png align="left")

You should see our beautiful error message, as we didn't generate the certs yet. So go ahead, read the message and generate your certificates.

Run `yarn dev` again and access `https://my-cool-domain.local`

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630985403236/G5PH-VC_5.png align="left")

---

#### Conclusion

That's it! Hope the tutorial was straightforward :)

* You can check out the code in this [example repository in GitHub.](https://github.com/wbgneto/setup-ssl-nextjs)
    
* Follow me on twitter: [@waltergalvao\_](https://twitter.com/waltergalvao_)
    
* [Contact me on LinkedIn.](https://www.linkedin.com/in/wbgneto/)
