Self-signed certificates should not be used in production.
Almost all the websites nowadays have
https enabled and it’s really useful to have
https enabled environment while developing. Getting an
https enabled environment might cost you money but there is an alternate way of enabling
https with self-signed certificates.
In this post, we are going to see how we can create self-signed certificates for web services. We will not discuss the complex topic of certificate signing and signing authorities.
ROOT SSL should be the first step so that we can use this particular certificate to sign any number of certificates for all the necessary domains that we might have.
First, we need to generate a key named
rootCA.key then, we will use this key to generate the
ROOT SSL certificate.
passphrase is required to generate the key. Choose something complex, something that is hard to guess, and keep it saved in a safe place.
openssl genrsa -des3 -out rootCA.key 4096
This will generate a
4096 bit RSA key as shown in the image below
Now, we will use this generated key to generate the
ROOT SSL certificate named
rootCA.crt. It’s also possible to define the expiration time of the key, in this example, we will set it for
01 year or
From September 01, 2020, google chrome and apple’s safari browser will no longer support certificates that have a validity period of more than
365 days plus the
grace period. See this article from apple and this article from the
sslstore that says
google chrome will do the same.
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 365 -out rootCA.crt
Once all the questions are answered, it will generate the
rootCA.crt SSL certificate.
In this step, we have to install/trust the newly generated
rootCA.crt into our system, to do that please use the following guidelines from this blog post.
Now we can use this root SSL certificate to issue locally useable SSL certificates for local use in development or staging environments.
Let’s create an OpenSSL configuration file named
homelab.local.csr.cnf. I have used my desired domain name as a prefix to
.csr.cnf. Use a text editor to open the file
Add the following lines to the file, save and exit.
[req] default_bits = 4096 prompt = no default_md = sha256 distinguished_name = dn [dn] C=DE ST=Hessen L=Frankfurt O=DevOps Team OU=Automation emailAddressfirstname.lastname@example.org CN = staging.homelab.local
[dn] entries to match your requirements, specifically the
CN entry. This is the domain name that the certificate will be valid for.
For the new browsers to accept the certificates it’s recommended to use
X509 V3 certificates with an attribute named
subj of the certificate creation request.
So let’s create the configuration file named
v3.ext. Use a text editor to open this new file
Add the following content to the file, save and exit.
authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = staging.homelab.local
Consider the input at
DNS.1 entry, this should be an alternate name if required can be used as
Now we will create a certificate key for
staging.homelab.local using the configuration file that we created earlier.
openssl req -new -sha256 -nodes -out staging.homelab.local.csr -newkey rsa:4096 -keyout staging.homelab.local.key -config <( cat homelab.local.csr.cnf )
The above command will generate an SSL certificate key named
Finally, we can request a certificate signing with the
root ssl certificate to generate a domain certificate for
staging.homelab.local. We will also define the expiration of this certificate to
openssl x509 -req -in staging.homelab.local.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out staging.homelab.local.crt -days 365 -sha256 -extfile v3.ext
Root certificate key
passphrase is required at this stage again.
If everything is in place this should generate the domain certificate named
staging.homelab.local.crt and the
staging.homelab.local.key in your server configuration(s) to use
LOCAL DNS or
hosts file should resolve the domain name to the desired IP address.
If you require to sign a lot of certificates for a different environment, then this process of creating a request and signing get tiresome really fast and to address this issue, here is a little
shell script to automate these processes – (change the script to your likings…..)
#!/bin/bash # author: Dalwar Hossain (email@example.com) # Check is domain name provided or not if [ "$#" -ne 1 ] then echo "=> Usage: /bin/bash generate_certificate.sh <fqdn>" exit 1 fi # Assign the domain name to a variable FQDN=$1 # rootCA certificate and key files ROOTCA_CRT=../rootCA.crt ROOTCA_KEY=../rootCA.key # Validity of the certificate (365 days = 1 year) VALIDITY=365 # Create directory and change path to the newly created directory echo "=> Creating required directory....." mkdir $FQDN echo "=> Changing to newly created directory....." cd $FQDN # Create necessary files echo "=> Creating certificate request configuration file....." cat > $FQDN.csr.cnf << EOF [req] default_bits = 4096 prompt = no default_md = sha256 distinguished_name = dn [dn] C=DE ST=Hesse L=Frankfurt O=DevOps Team OU=Automation emailAddressfirstname.lastname@example.org CN = $FQDN EOF echo "=> Creating v3 extension configuration file with subjectAltName....." cat > $FQDN.v3.ext << EOF authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = $FQDN EOF echo "=> Generating certificate request key and request file....." # Create the certificate key and request for a certificate signing openssl req -new -sha256 -nodes -out $FQDN.csr -newkey rsa:4096 -keyout $FQDN.key -config <( cat $FQDN.csr.cnf ) echo "=> Signing the certificate with rootCA certificate and rootCA key....." # Sign the certificate with rootCA key and and rootCA certificate openssl x509 -req -in $FQDN.csr -CA $ROOTCA_CRT -CAkey $ROOTCA_KEY -CAcreateserial -out $FQDN.crt -days $VALIDITY -sha256 -extfile $FQDN.v3.ext echo "=> Signed certificate and key is available at [$FQDN] directory.
If you are using
localhost as a development environment and need to create the
.key file really quick, then use the following command to generate the key and the certificate for
openssl req -x509 -out localhost.crt -keyout localhost.key \ -newkey rsa:4096 -nodes -sha256 \ -subj '/CN=localhost' -extensions EXT -config <( \ printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
localhost.crt in your list of locally trusted roots as mentioned above in