Search the site:

Copyright 2010 - 2024 @ DevriX - All rights reserved.

How to Create your Own SSL Certificate Authority (CA) for Local HTTPS

How to create your own SSL Certificate Authority (CA) for local HTTPS

TLS/SSL works by using a combination of a public certificate and a private key. The SSL key is kept secret on the server. It is used to encrypt content sent to clients.

The SSL certificate is publicly shared with anyone requesting the content. It can be used to decrypt the content signed by the associated SSL key.

In 2018, Google began promoting the adoption of HTTPS encryption, flagging websites without SSL certificates as “not secure” in the Chrome browser. This recommendation gained broad approval, as safeguarding web traffic protects both the website owner and their users.

Although Let’s Encrypt and its API have greatly simplified the process of generating and installing SSL certificates on servers, they provide minimal assistance to developers working on HTTPS in their development environments.

Crafting a local SSL certificate for serving development sites over HTTPS can be a challenging task. Even if you successfully create a self-signed certificate, it may still lead to browser privacy errors.

In this article, we will guide you through the process of establishing your own SSL Certificate Authority (CA) for local servers, enabling you to run HTTPS sites locally without encountering any problems.

  1. Why use HTTPS for local development?
  2. How It Works
  3. Establish Your Own Trusted SSL Certificate Authority
  4. Setting Up Your Root Certificate
  5. Generating CA-Authenticated Certificates for Your Development Sites
  6. Shell Automation Script
  7. Alternative Solutions

Why Use HTTPS for Local Development?

Why not stick to regular HTTP for local development? Well, if your production site operates exclusively on HTTPS, and you’re developing locally using regular HTTP, your development and production environments won’t be as closely aligned as they could be.

It’s crucial for your development environment to closely resemble production to minimize potential issues appearing in the live environment that didn’t surface during development.

Opting for HTTP when your production site is HTTPS-only introduces an unnecessary risk. Even in cases where mirroring the production environment isn’t feasible, it’s advisable to run HTTPS locally to avoid grappling with mixed content SSL warnings throughout the development process.

If you’ve ever attempted to access a local site via HTTPS without a configured SSL certificate, you’ve likely encountered the following message in Chrome: chrome-ssl-error (1) Alternatively, you might have come across the following message in Firefox: firefox-ssl-error (2) Various browsers display different messages, but the underlying idea remains the same.

One workaround is to transition your local WordPress development environment to platforms like LocalWP, DevKinsta, or even Laravel Valet, as they provide built-in local SSL solutions.

However, the downside is that this involves altering your development workflow, which may not be ideal if you’re already comfortable with your current setup, especially if it aligns with your production environment.

Exploring local SSL solutions online often leads to navigating the complexities of self-signed certificates. Attempting to make a self-signed SSL certificate work with your local server can be cumbersome unless you’re using a tool that streamlines the process, potentially necessitating a switch in your local development environment.

The primary challenge with locally self-signed certificates lies in the browser’s trust factor. Simply setting up a local self-signed certificate isn’t sufficient, and you’ll still encounter the same browser message, now accompanied by ERR_CERT_AUTHORITY_INVALID.

This occurs because the browser seeks to validate the certificate with a certificate authority, and in this case, it can’t. Therefore, the solution involves establishing yourself as your own Certificate Authority (CA)!

How Does SSL Certificate Authority Work?

When requesting an SSL certificate from a Certificate Authority (CA) such as Verisign or GoDaddy, you submit a Certificate Signing Request (CSR) to them. In return, they provide you with an SSL certificate signed using their root certificate and private key.

Browsers have access to a copy of the root certificate from various CAs (or access it from the operating system), enabling the browser to verify that your certificate was issued by a trusted CA.

This explains why a self-signed certificate is not trusted by the browser—it lacks the validation from a recognized CA. The workaround involves generating our own root certificate and private key.

We then incorporate the root certificate into all our devices just once. Subsequently, any self-signed certificates we generate will inherently be trusted, as they are tied to our custom root certificate.

Establish Your Own Trusted Certificate Authority

To create your own SSL certificate authority, you only require two commands. Let’s delve into the process on macOS and Linux, and subsequently, we’ll explore how it operates on the Windows operating system.

Creating the Private Key and Root Certificate on macOS Monterey and Linux (Step-by-Step Guide)

Since macOS and Linux are both Unix-like operating systems, the procedures for generating the necessary files are identical.

The primary distinction lies in the fact that on macOS, you may need to install the OpenSSL command-line application. If you don’t have it already, you can install Homebrew, which will enable you to install OpenSSL.


/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install openssl

Most Linux distributions come pre-installed with OpenSSL. If not, you can easily install it using your default package manager.

Afterward, you can designate a directory to store your local certificate files. While not mandatory, this practice simplifies locating the keys later on.

mkdir ~/certs
cd ~/certs

With these preparations in place, we are prepared to generate the private key and assume the role of a local Certificate Authority (CA):

openssl genrsa -des3 -out myCA.key 2048

The command is using the OpenSSL tool to generate a 2048-bit RSA private key with Triple DES (3DES) encryption and save it to a file named “myCA.key.”

Let’s break down the command:

  • openssl: This is the command-line tool for using the OpenSSL library, which provides cryptographic functions and utilities.
  • genrsa: This command is used to generate an RSA private key.
  • des3: This option specifies that the private key should be encrypted using Triple DES (3DES) cipher. Encryption adds a layer of security to the private key by requiring a passphrase to access it.
  • out myCA.key: This part of the command specifies the output file name for the generated private key. In this case, the private key will be saved in a file named “myCA.key.”
  • 2048: This parameter specifies the key length, and in this case, it is set to 2048 bits. The key length determines the security level of the RSA key. A longer key is generally more secure but requires more computational resources.

After running this command, OpenSSL will prompt for a passphrase, and we strongly advise against skipping this step. It’s crucial to keep the passphrase secure, as it serves as an added layer of protection. The passphrase helps prevent unauthorized individuals from using your private key to generate their own root certificate. The output should resemble the following:

Generating RSA private key, 2048 bit long modulus
.................................................................+++
.....................................+++
e is 65537 (0x10001)
Enter pass phrase for myCA.key:
Verifying - Enter pass phrase for myCA.key:

Following that, we proceed to generate a root certificate:
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem

The provided command is using OpenSSL to generate a self-signed X.509 certificate for a Certificate Authority (CA). This certificate can be used for various purposes, such as signing other certificates within a public key infrastructure (PKI). Let’s break down the command:

  • openssl: The command-line tool for OpenSSL.
  • req: This command is used for X.509 certificate signing request (CSR) management.
  • -x509: This option specifies that a self-signed certificate should be created, rather than generating a certificate signing request for submission to a Certificate Authority.
  • -new: This option is used to generate a new certificate.
  • -nodes: This option indicates that the private key should not be encrypted. In other words, it generates a private key without a passphrase, making it more convenient but potentially less secure.
  • -key myCA.key: This specifies the private key file (myCA.key) to be used in generating the certificate.
  • -sha256: This option specifies the hash algorithm to be used for the certificate. In this case, SHA-256 is chosen for stronger security.
  • -days 1825: This sets the validity period of the certificate in days. Here, it’s set to 1825 days (5 years).
  • -out myCA.pem: This specifies the output file name for the generated certificate. In this case, the certificate will be saved in a file named “myCA.pem.”

You will receive prompts for the passphrase associated with the chosen private key and a series of questions. The responses to these questions are not overly critical since they primarily appear when inspecting the certificate, a task you’ll rarely perform.

We recommend choosing a Common Name that you can easily identify as your root certificate within a list of other certificates. This is the most significant aspect to consider.

Enter pass phrase for myCA.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:BG
State or Province Name (full name) [Some-State]:Sofia
Locality Name (eg, city) []:Sofia
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DevriX
Organizational Unit Name (eg, section) []:7G
Common Name (e.g. server FQDN or YOUR name) []:DevriX
Email Address []:[email protected]

At this point, you should possess two files: “myCA.key” (your private key) and “myCA.pem” (your root certificate).

🎉 Congratulations, you’ve officially become a CA. Well, kind of.

Creating the Private Key and Root Certificate on Windows: (Step-by-Step Guide)

In Windows, it’s feasible to configure your environment to execute the openssl commands, but you’ll need some additional tools.

If you’re using Windows Subsystem for Linux (WSL), the commands will work the same as in Linux. If you’re working with Windows alongside tools like WampServer or XAMPP, you’ll need to install the OpenSSL command-line utility on Windows. The easiest way to do this is by installing Git for Windows, which includes OpenSSL and the Git Bash utility.

Upon opening a Git Bash window, you can run the same commands as on macOS or Linux, with a small difference. Due to the specific behavior of some console applications (particularly OpenSSL) in Git Bash, you need to prefix all openssl commands using the winpty utility.

For example, the command below illustrates how to generate the private key and assume the role of a local CA in Git Bash:
winpty openssl genrsa -des3 -out myCA.key 2048

Another minor difference lies in the file paths within Git Bash. When you launch a Git Bash session, the home directory in the terminal corresponds to your User directory on Windows, but with a directory structure resembling Linux.

For instance, if your User directory is situated at c:\Users\DevriX on Windows, your Git Bash home directory will be c/Users/DevriX.

Setting Up Your Root Certificate

To truly function as a Certificate Authority (CA), you’d need to distribute your root certificate to every device across the globe.

However, it’s not necessary to become a globally recognized CA. Your focus should be on being a CA for the devices within your ownership. It’s necessary to include the root certificate on any laptops, desktops, tablets, and phones that access your HTTPS sites.

While this may be a bit cumbersome, the positive aspect is that it’s a one-time task. Once added, your root certificate remains valid until it expires.

Including the Root Certificate in macOS Monterey Keychain

Through the Command Line Interface (CLI)

sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" myCA.pem

The provided command uses the security command on macOS to add a custom certificate (myCA.pem) to the system’s list of trusted root certificates.

This is a crucial step in establishing a secure communication environment, especially in scenarios where a custom Certificate Authority (CA) is being used.

Let’s break down the command:

  • sudo: This is a command in Unix-like operating systems that allows a permitted user to execute a command as the superuser or another user.
  • security: This is a command-line tool on macOS used for managing various security services, including certificates.
  • add-trusted-cert: This subcommand is used to add a certificate to the system’s list of trusted certificates.
  • -d: This flag specifies that the certificate being added is a leaf certificate, indicating that it is an end-entity certificate rather than an intermediate or root certificate.
  • -r trustRoot: This flag indicates that the certificate is being added as a trusted root certificate. Trusted root certificates are used to verify the authenticity of other certificates in a chain of trust.
  • -k “/Library/Keychains/System.keychain”: This flag specifies the keychain where the certificate is to be added. In this case, it’s the System keychain, which is a system-wide keychain on macOS.
  • myCA.pem: This is the path to the certificate file (in PEM format) that is being added to the trusted certificates store.

Through the macOS Keychain Application

  1. Open the macOS Keychain app.
  2. If necessary, ensure you’ve chosen the System Keychain (older macOS versions default to this keychain).
  3. Navigate to File > Import Items
  4. Choose your private key file (i.e., myCA.pem)
  5. Search for the “Common Name” you provided earlier. macos-keychain-app (3)
  6. Double-click on your root certificate in the list.
  7. Expand the Trust section.
  8. Modify the “When using this certificate:” dropdown to “Always Trust”.
  9. Close the certificate window.
  10. Throughout the process, you may be prompted to enter your password (or use your fingerprint), so please proceed accordingly.

Adding the Root Certificate on Linux Systems

Linux comes in various distributions, with Ubuntu being the most widely used. These instructions will focus on Ubuntu.

  1. If not already installed, install the ca-certificates package using the command:
    sudo apt-get install -y ca-certificates
  2. Copy the myCA.pem file to the /usr/local/share/ca-certificates directory, renaming it as myCA.crt:
    sudo cp ~/certs/myCA.pem /usr/local/share/ca-certificates/myCA.crt
  3. Update the certificate store with:
    sudo update-ca-certificates

You can verify the installation of the certificate by executing the following command:
awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-certificates.crt | grep DevriX

Upon successful installation, you should observe the details of the root certificate.
subject=C = BG, ST = Sofia, L = Sofia, O = DevriX, OU = 7G, CN = DevriX, emailAddress = [email protected]

Adding the Root Certificate on Windows 10

  1. Open the “Microsoft Management Console” by pressing Windows + R, typing mmc, and clicking Open.
  2. Navigate to File > Add/Remove Snap-in.
  3. Select Certificates and click Add.
  4. Choose Computer Account and proceed by clicking Next.
  5. Select Local Computer and click Finish.
  6. Click OK to return to the MMC window.
  7. Expand the view by double-clicking Certificates (local computer).
  8. Right-click on Certificates under “Object Type” in the middle column, select All Tasks, and then Import.
  9. Click Next, followed by Browse. Change the certificate extension dropdown next to the filename field to All Files (*.*) and locate the myCA.pem file.
  10. Click Open, then Next.
  11. Choose “Place all certificates in the following store.” with “Trusted Root Certification Authorities store” as the default. Proceed by clicking Next, then Finish, to finalize the wizard.

If the process unfolded smoothly, you should find your CA certificate listed under Trusted Root Certification Authorities > Certificates. mmc-windows (4)

Generating CA-Authenticated Certificates for Your Development Sites

Now, having established ourselves as a Certificate Authority (CA) on all our devices, we have gained the capability to sign certificates for any new development sites requiring HTTPS. Initially, we generate a private key for the development site.

It’s worth noting that we’ve named the private key using the domain name URL of the development site. While not mandatory, adopting this practice facilitates management, especially when dealing with multiple sites:
openssl genrsa -out local.devrix.com.key 2048

Change local.devrix.com with the name of your project. Next, we proceed to generate a Certificate Signing Request (CSR):
openssl req -new -key local.devrix.com.key -out local.devrix.com.csr

Replace local.devrix.com with the name of your project.

You will encounter the same set of questions as before, and once again, your answers hold minimal significance. In this case, they matter even less since you won’t generally be inspecting this certificate in a list alongside others.

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:BG
State or Province Name (full name) [Some-State]:Sofia
Locality Name (eg, city) []:Sofia
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DevriX
Organizational Unit Name (eg, section) []:7G
Common Name (e.g. server FQDN or YOUR name) []:local.devrix.com
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Finally, we’ll generate an X509 V3 certificate extension configuration file, utilized for defining the Subject Alternative Name (SAN) for the certificate. In our instance, we’ll craft a configuration file named local.devrix.com.ext, encompassing the following content:

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = local.devrix.com

Swap out local.devrix.com with the name of your specific project.

We will utilize the openssl x509 command, as it provides the capability to modify certificate trust settings. In this scenario, we’re employing it to sign the certificate in collaboration with the config file, enabling us to specify the Subject Alternative Name.

Now, execute the command to generate the certificate using our CSR, the CA private key, the CA certificate, and the config file:

openssl x509 -req -in local.devrix.com.csr -CA myCA.pem -CAkey myCA.key \
-CAcreateserial -out local.devrix.com.crt -days 825 -sha256 -extfile local.devrix.com.ext

You may be asked for a passphrase. This is the passphrase you set on the myCA.key file.

We’ve successfully generated three files: local.devrix.com.key (the private key), local.devrix.com.csr (the certificate signing request, or CSR file), and local.devrix.com.crt (the signed certificate). These files can be utilized to configure local web servers for HTTPS by incorporating the private key and the signed certificate.

For users of MAMP Pro, version 6.0 has integrated SSL support. You can activate it by selecting the SSL option under your chosen web server.

If you’re operating in a Linux or Windows environment that utilizes Nginx, you can refer to the instructions provided here “Install WordPress on Ubuntu 20.04“.

For Apache on Linux or Windows: Enable SSL, set up a virtual host on port 443, and configure directives (SSLEngine, SSLCertificateFile, SSLCertificateKeyFile) to point to the generated certificate and key files. 

   <VirtualHost *:443>
   ServerName local.devrix.com
   DocumentRoot /var/www/subdomains/local.devrix.com

   SSLEngine on
   SSLCertificateFile /path/to/certs/local.devrix.com.crt
   SSLCertificateKeyFile /path/to/certs/local.devrix.com.key
</VirtualHost>

Creating Apache SSL Virtual Host File for Your Linux Project

Let’s create a copy of the original SSL Virtual Host file for our project:

sudo cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/local.devrix.com-ssl.conf

Now, open the SSL Virtual Host file to make adjustments:

sudo nano /etc/apache2/sites-available/local.devrix.com-ssl.conf

Inside, with most of the comments removed, the Virtual Host file should look something like this by default: /etc/apache2/sites-available/local.devrix.com-ssl.conf


<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        ServerAdmin webmaster@localhost

        DocumentRoot /var/www/html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        SSLEngine on

        SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
        SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

        <FilesMatch "\.(cgi|shtml|phtml|php)$">
                        SSLOptions +StdEnvVars
        

        
                        SSLOptions +StdEnvVars
        
    </VirtualHost>

We will be making some minor adjustments to the file. We will set the normal things we’d want to adjust in a Virtual Host file (ServerAdmin email address, ServerName, etc., and adjust the SSL directives to point to our certificate and key files.

After making these changes, your server block should look similar to this:


    <IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        ServerAdmin [email protected]
        ServerName local.devrix.com
     
        DocumentRoot /var/www/subdomains/local.devrix.com/

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        SSLEngine on

        SSLCertificateFile /path/to/certs/local.devrix.com.crt
        SSLCertificateKeyFile /path/to/certs/local.devrix.com.key

        <FilesMatch "\.(cgi|shtml|phtml|php)$">
                        SSLOptions +StdEnvVars
        

        
                        SSLOptions +StdEnvVars
        
    </VirtualHost>
</IfModule>

Save and close the file when you are finished.

Note: Sometimes, depending on the server’s default configuration, you may need to add a few more things to the Directory block:

The main fields that Node.JS itself needs are name and version. The name holds the project’s name and version – the package version.

{
<Directory "/var/www/subdomains/local.devrix.com">
        SSLOptions +StdEnvVars
        Options Indexes FollowSymLinks Includes ExecCGI
        AllowOverride All
        Require all granted

}

Enabling the Changes in Apache on Linux

Now that we’ve made our changes, we can enable the SSL module in Apache, enable our SSL-ready Virtual Host, and restart Apache.

We can enable mod_ssl, the Apache SSL module, needed by some settings in our SSL snippet, with the a2enmod command:

sudo a2enmod ssl

Next, we can enable our SSL Virtual Host with the a2ensite command:

sudo a2ensite local.devrix.com-ssl

At this point, our site and the necessary modules are enabled. We should check to make sure that there are no syntax errors in our files. We can do this by typing:

sudo apache2ctl configtest

If everything is successful, you will get a result that looks like this:

Syntax OK

If your output has Syntax OK in it, your configuration file has no syntax errors. We can safely restart Apache to implement our changes:

sudo systemctl restart apache2

Creating a new CA for each site is unnecessary; you can simply repeat the last step of generating a certificate for any additional development sites.

Shell Automation Script

For an even faster process, here’s a convenient shell script that you can customize for your specific needs. It is compatible with macOS, Linux, or Windows using Git Bash:

#!/bin/sh

if [ "$#" -ne 1 ]
then
  echo "Usage: Must supply a domain"
  exit 1
fi

DOMAIN=$1

cd ~/certs

openssl genrsa -out $DOMAIN.key 2048
openssl req -new -key $DOMAIN.key -out $DOMAIN.csr

cat > $DOMAIN.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
EOF

openssl x509 -req -in $DOMAIN.csr -CA ../myCA.pem -CAkey ../myCA.key -CAcreateserial \
-out $DOMAIN.crt -days 825 -sha256 -extfile $DOMAIN.ext

  • Create a file with .sh extension
  • Write the script in the file using an editor
  • Make the script executable with command chmod +x <fileName>
  • Run the script using ./<fileName>

Alternative SSL Certificate Authority Solutions

Another option worth exploring when generating locally trusted SSL certificates is mkcert.

If you are comfortable using one of the various package managers outlined in mkcert’s readme file to install the tool, it serves as a reliable alternative for creating locally trusted SSL certificates.

The drawback is that it solely installs the root CA certificate on your local machine and generates locally signed SSL certificates, necessitating manual configuration for each local site.

Wrapping It Up

So, that’s how to create your own SSL Certificate Authority for your local sites and enable HTTPS.

This should help you avoid encountering the discouraging “Your connection is not private” message on your local development websites.

Don’t forget that, in case you are experiencing technical difficulties, or in any other aspect of managing your website, DevriX is here to help.