Creating a Self-signed SSL Certificate

In this post I will explain how to create a self-signed certificate for testing purposes.  If you have a virtual machine running on your home network (such as inside VirtualBox, Hyper-V, or inside Windows Subsystem for Linux), it will not be able to get a Certificate Authority (CA) signed SSL certificate because it isn’t accessible on a static IP address attached to a domain name.  However, you may still want to set it up as if it was a public facing server in order to test out a configuration, e.g. Postfix, GitLab.

You must have openssl installed.  This will be installed on any Linux machine, but under Windows, binaries can be hard to come by.  I recommend installing the excellent development environment MSYS2, and installing it by opening up an MSYS2 window and typing:

pacman -S openssl

Once it’s installed, you’ll be creating a private key, a certificate request, and then you’ll sign the request with the private key to create a public certificate. You can use any names you want for the files, but I have chosen to replicate what Let’s Encrypt gives you by default.

Generate the private key

sudo openssl genrsa -out "privkey.pem" 2048

Generating RSA private key, 2048 bit long modulus
e is 65537 (0x10001)

Generate the certificate request
You’ll be entering in some information here. The important one is the Common Name. Although you don’t have a real domain, it’s a good idea to make up one for your private network. I have seen people use the .lcl extension for it. Do not enter anything for the challenge password.

sudo openssl req -new -key "privkey.pem" -out "certrequest.pem"
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]:US
State or Province Name (full name) [Some-State]:New Mexico
Locality Name (eg, city) []:Albuquerque
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:*.example.lcl
Email Address []:john.doe@example.lcl

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:


Generate the certificate by signing the certificate request with the private key

sudo openssl x509 -req -days 30 -in "certrequest.pem" -signkey "privkey.pem" -out "cert.pem"
Signature ok
subject=C = US, ST = New Mexico, L = Albuquerque, CN = *.example.lcl, emailAddress = john.doe@example.lcl
Getting Private key


Now move them to a standard spot for certificates.

sudo chmod 644 cert.pem
sudo chmod 644 certrequest.pem
sudo chmod 640 privkey.pem
sudo mv cert.pem /etc/ssl/certs
sudo mv certrequest.pem /etc/ssl/certs
sudo mv privkey.pem /etc/ssl/private

You may now reference them in software that uses certificates such as Apache, Nginx, or Node.js apps. You will still get a warning saying that the certificate is invalid, but the data sent will be encrypted.

Leave a Reply

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