How to generate self-signed SSL certificate

Today I will show you how to quickly generate ready to use self-signed SSL certificate for nginx HTTP server using command-line. It is a very handy ability that will allow you to perform various tasks locally or in home laboratory without touching dedicated certificates.

Sample self-signed multi-domain certificate
Sample self-signed multi-domain certificate

Initial notes

Use the minimal Debian Jessie installation and basic nginx server configuration to host and secure website used in the following examples and easily inspect commands described in this article.

Basic nginx site configuration used in the following examples.

server {
  listen 443 ssl;

  ssl_certificate ssl/nginx.crt;
  ssl_certificate_key ssl/nginx.key;

  root /var/www/html/;
  index index.nginx-debian.html;

Use hosts file or dnsmasq to resolve domain names.

Single domain SSL certificate

The simplest possible case is to create single domain SSL certificate which can be generated using the following openssl command.

$ sudo openssl req -subj "/" -x509 -nodes -days 730 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

It is purely optional, but you can provide more detailed information that will be included in generated certificate. Both of the following commands are equivalent.

$ sudo openssl req -subj "/countryName=PL/stateOrProvinceName=pomorskie/organizationName=personal/localityName=Malbork/" -x509 -nodes -days 730 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
$ sudo openssl req -subj "/C=PL/ST=pomorskie/O=personal/L=Malbork/" -x509 -nodes -days 730 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

Attributes are described in Additional notes section at the end of the article.

Wildcard SSL certificate

Generating wildcard SSL certificate is almost the same as the previous example, but it deserves distinct section due to asterisk label which only protects subdomains.

$ sudo openssl req -subj "/commonName=*" -x509 -nodes -days 730 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

You need to use two distinct certificates ( and * or one multi-domain certificate to protect whole domain with its subdomains. Most, if not all, of the commercially available wildcard certificates will secure domain name as well as its subdomains.

It is important to know that this kind of definition using wildcard character will protects only one level of subdomains. It means that certificate with defined common name * will protect, but not subdomain.

Multi-domain SSL certificate

This is where the fun begins, as creating multi-domain SSL certificate requires additional configuration file to define subject alternative names extension. That is why, it is also sometimes named as multi-domain (SAN) certificate..

$ cat <<EOF | sudo tee /etc/nginx/ssl/certificate.cfg
[ req ]
req_extensions     = req_ext
distinguished_name = req_distinguished_name
prompt             = no


subjectAltName   = @alt_names

DNS.1  =
DNS.2  = *
DNS.3  = *
DNS.4  =
DNS.5  = *
DNS.6  = *

See RFC 3280 - Internet X.509 Public Key Infrastructure [ HTML | TXT | PDF] for additional information about available options (DNS, IP and URI).

Generate certificate including additional req_ext section (see x509 manual page).

$ sudo openssl req -x509 -config /etc/nginx/ssl/certificate.cfg -extensions req_ext -nodes -days 730 -newkey rsa:2048 -sha256 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

Additional notes

The following table lists attributes that are used to describe certificate.

commonNameCNCommon name (domain)
organizationalUnitNameOUOrganizational unitIT Department
organizationNameOOrganizationPersonal Organization
localityNameLLocality Malbork
stateOrProvinceNameSTState or province namepomorskie
countryNameCCountry name (ISO code)PL

You can also use configuration file to store definitions for single single domain SSL certificate or wildcard SSL certificate.

$ cat <<EOF | sudo tee /etc/nginx/ssl/certificate.cfg
[ req ]
distinguished_name = req_distinguished_name
prompt             = no

$ sudo openssl req -x509 -config /etc/nginx/ssl/certificate.cfg -nodes -days 730 -newkey rsa:2048 -sha256 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

You can always print subject line using the following command.

$ openssl x509 -in /etc/nginx/ssl/nginx.crt -subject -noout
subject= /CN=*
Milosz Galazka's Picture

About Milosz Galazka

Milosz is a system administrator working for a successful Polish company and a long time supporter of Free Software Foundation and Debian operating system.

Gdansk, Poland