Create a Self Signed Certificate with OpenSSL

Categories:

SSL has become a requirement for today’s websites. While testing your website or application on a private server (a server without a public IP) you cannot use a certificate signed by a trusted authority and you need to create a self-signed certificate.

For public servers there are better options, including free options like Let’s Encrypt. Follow the steps in this short tutorial only for your private test server.

To create the self-signed certificate we will use OpenSSL.

What is OpenSSL?

OpenSSL is an open-source commercial-grade toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. 

OpenSSL is available for most Unix-like operating systems (including Linux, macOS, and BSD) and Microsoft Windows.

The OpenSSL project started 1998 and is constantly updated.

How to install OpenSSL on Ubuntu / CentOS?

The software may already be installed on your server. You can verify this using the which command:

which openssl

And you should get something like: /usr/bin/openssl

If not, then let’s install it (and also verify if https is allowed by the firewall):

Ubuntu

sudo apt install openssl
sudo ufw app list

CentOS

sudo dnf install openssl
sudo firewall-cmd --permanent --list-all

NOTE: If you don’t see https allowed by the firewall you will need to add it if you want to access the server from another IP from the private network.

With OpenSSL installed, we can proceed to create a Certificate Authority (CA) and an SSL Certificate.

While many short tutorials only show a solution where you don’t create a Certificate Authority and you create a single SSL Certificate for all your websites, I don’t suggest following this route. Spending one more minute to create the CA will prevent you from getting annoying messages when accessing your test websites in browsers like Google Chrome which check if the SSL certificate is valid but also if the CA who issued the certificate is trusted.

The solution below is based on an idea I found from Stack Overflow user: JellicleCat. His/her solution was actually more elegant (the process was automated) but to keep things simple, I removed the automation part. Thank you, JellicleCat!

How to create a Certificate Authority (CA)?

For testing purposes, let’s create the CA certificate in the user’s home directory. These files should be kept safe and private so make sure to restrict access to them.

# Go to home directory
cd ~
openssl genrsa -des3 -out theCA.key 2048
# Generate root certificate
openssl req -x509 -new -nodes -key theCA.key -sha256 -days 825 -out theCA.pem

Make sure you remember the pass phrase.
You should now have .pem and .key files for the CA
The CA is ready, let’s create a free SSL certificate with this CA.

How to create a self signed certificate?

Here are the commands to create the free SSL certificate.
My test domain is called amadeus500.xyz. Make sure to replace amadeus500.xyz with your test domain in all the lines below.

# Generate a private key
openssl genrsa -out amadeus500.xyz.key 2048
# Create a certificate-signing request
openssl req -new -key amadeus500.xyz.key -out amadeus500.xyz.csr

Create a filename with the data for the certificate:

vi amadeus500.xyz.ext

Place the content below in the file (change amadeus500.xyz with yours):

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = amadeus500.xyz # Your test domain (e.g. tse12345.com)
DNS.2 = www.amadeus500.xyz # Optionally, add additional subdomains (e.g. www)
IP.1 = 192.168.0.101 # Optionally, add your IP 

Finally, let’s create the SSL certificate:

openssl x509 -req -in amadeus500.xyz.csr -CA theCA.pem -CAkey theCA.key -CAcreateserial -out amadeus500.xyz.crt -days 825 -sha256 -extfile amadeus500.xyz.ext

Where to store the certificate?

The recommended directories to store certificates / private keys are /etc/ssl/certs and /etc/ssl/private.
You can store them in another location as long as you provide the correct location to the software using them. For example Let’s Encrypt creates and uses the certificates from /etc/letsencrypt/live/.
For our test server, I suggest going with the standard solution:

sudo cp amadeus500.xyz.crt /etc/ssl/certs
sudo cp amadeus500.xyz.key /etc/ssl/private

How to use the self signed certificate with Apache?

The process of adding the SSL certificate to the Virtual Host is identical regardless of how the certificate is signed.
The new VirtualHost config for port 443 can be based on your non-SSL config adding a few lines:

<VirtualHost *:443>
...
   SSLEngine on
   # Replace with the location and name of your .crt and .key files
   SSLCertificateFile /etc/ssl/certs/amadeus500.xyz.crt
   SSLCertificateKeyFile /etc/ssl/private/amadeus500.xyz.key
...
</VirtualHost>

To redirect http traffic to https, add a redirect to the http config:

<VirtualHost *:80>
...
    Redirect / https://amadeus500.xyz
...
</VirtualHost>

How to use the self signed certificate with nginx?

Just like with the Apache configuration, you can create your SSL config based on the non-SSL config adding a few lines to let the server know where to find the certificate. You may also want to alter your http to redirect traffic to https:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name amadeus500.xyz;
...
    ssl_certificate /etc/ssl/certs/amadeus500.xyz.crt;
    ssl_certificate_key /etc/ssl/private/amadeus500.xyz.key;
...
}

server {
    listen 80;
    listen [::]:80;
    server_name amadeus500.xyz www.amadeus500.xyz;
    return 301 https://amadeus500.xyz$request_uri;
}

How to trust the CA?

After you successfully created the certificate and added it to your Virtual Host configuration (and, of course, restarted your web server) you can test your newly encrypted web application in the browser. You will probably get a message saying something like “Your connection is not private”.

Error: Your connection is not private
Screenshot from Google Chrome showing error “Your connection is not private”

This is because even though you have an SSL certificate, the issuer is not trusted.
To resolve this, you need to add the CA certificate to the Trusted CAs.

Google Chrome
– Go to Settings > Security > Manage Certificates
– In the Trusted Root Certification Authorities tab press the Import button and browse for your CA certificate file (theCA.pem).
– Import it and restart the computer

Firefox
– Go to Options > Privacy & Security > View Certificates
– In the Authorities tab, click the import button and choose the CA certificate file.
– Reload the page

NOTE: The setup in this article should be used only for testing purposes on non-commercial applications. For production servers, only use certificates signed by trusted authorities.

Enjoy testing with https!

Leave a Reply

Your email address will not be published. Required fields are marked *