Locally Signed Certificates With Mkcert

Published on 2023/01/01 by John Kosmetos

What is SSL, and why do I need it?

If you're building a website, wep app, or anything else that is served over the web, you're going to need a SSL certificate, to verify the identity of your site, and to encrypt the data being transferred between your server and the clients connecting to it.

It's worth noting that the SSL (Secure Sockets Layer) protocol has been supplanted by TLS (Transport Layer Security), a newer and more secure incarnation, but SSL has been in use for so long, that it's still referred to whenever web security is mentioned, so SSL and TLS are often used interchangeably.

The Problem

Ok, you've got an idea for a website, and you've just set up your local web server to start bringing it to life, most likely using Nginx or Apache.

You launch your browser, head to https://127.0.0.1/, expecting to be greeted by Hello World 🌍, but instead you see the following.

SSL Error

The Solution

To get rid of this eyesore, you're going to have to generate locally signed certificates, and configure your web server to use them, which under normal circumstances would be a lenghty, and painful process, but thankfully, we have mkcert to do all the heavy lifting! 🥳

In short, it creates and installs a local CA (Certificate Authority) that is then used to generate the aforementioned certificates.

Step 1: Install mkcert

Mac OS

Make sure Homebrew is installed, then fire up your terminal and run the following.

brew install mkcert
brew install nss # if you use Firefox

Linux

First, make sure certutil is installed, so depending on your distribution you'll run one of the following commands.

sudo apt install libnss3-tools
    -or-
sudo yum install nss-tools
    -or-
sudo pacman -S nss
    -or-
sudo zypper install mozilla-nss-tools

After which you can install Homebrew on Linux,then finally, mkcert.

brew install mkcert

Windows

Make sure Chocolatey is installed, then fire up your terminal and run the following.

choco install mkcert

Step 2: Install the local CA

Once you have mkcert up and running on your machine, you need to install the local certificate authority that will be used to generate all of your local certificates, by running the following command.

mkcert -install

After which you should see the following output.

Created a new local CA 💥
The local CA is now installed in the system trust store! ⚡️
The local CA is now installed in the Firefox trust store (requires browser restart)! 🦊

Step 3: Generate your locally trusted certificates

Assuming your website's URL is awesomesauce.com, navigate to your project's root and run the following to generate locally trusted certificates, utilising the CA we installed in the previous step.

mkcert awesomesauce.com "*.awesomesauce.com" awesomesauce.local localhost 127.0.0.1 ::1

Which should result in brand spanking new certificates in your current directory, and the following output! 😎

Created a new certificate valid for the following names 📜
 - "awesomesauce.com"
 - "*.awesomesauce.com"
 - "awesomesauce.local"
 - "localhost"
 - "127.0.0.1"
 - "::1"

The certificate is at "./awesomesauce.com+5.pem" and the key at "./awesomesauce.com+5-key.pem" ✅

Step 4: Update your server configuration

Once you have your new certificates, you'll need to update your web server to make use of them.

First things first, copy the certificates over into their respective directories.

# Copy over the cert file
cp ./awesomesauce.com+5.pem /etc/ssl/certs/

# Copy over the key file
cp ./awesomesauce.com+5-key.pem /etc/ssl/private/

Note: If you're using Docker, just mount the above directories into your web server container.

Apache (v2.4)

Make sure that the Apache SSL module is installed and enabled, then update your config file to make use of the newly generated cert files.

# /etc/apache2/sites-available/awesomesauce.com.conf

<VirtualHost *:443>
   ServerName awesomesauce.com
   DocumentRoot /var/www/awesomesauce.com/public_html

   SSLEngine on
   SSLCertificateFile /etc/ssl/certs/awesomesauce.com+5.pem
   SSLCertificateKeyFile /etc/ssl/private/awesomesauce.com+5-key.pem
</VirtualHost>

Nginx (v1.25)

Update the server block to make use of the newly generated cert files.

# /etc/nginx/conf.d/ssl.conf

server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name awesomesauce.com;

    ssl_certificate /etc/ssl/certs/awesomesauce.com+5.pem;
    ssl_certificate_key /etc/ssl/private/awesomesauce.com+5-key.pem;
}

Time to test

If you haven't already, add the following lines to your hosts file to point your domain to your local machine.

It's typically located in the following locations, depending on your operating system.

  • Mac OS & Linux - /etc/hosts
  • Windows 10 - C:\Windows\System32\Drivers\etc\hosts
127.0.0.1   awesomesauce.local
127.0.0.1   awesomesauce.com
127.0.0.1   www.awesomesauce.com

All done! 🎉 When you navigate to https://awesomesauce.com in your favourite browser, you should now be greeted with a lock symbol, indicating that the connection between your browser and website is encrypted and secure.