Creating your own root certificate authority (CA)

Create your own local Certificate Authority and use that CA to create your site certificate. To have your browser trust your certificate, add the CA to known certificate authorities.

Create CA root certificate

First we create a CA private key and then a CA certificate.:

mkdir -p ~/rootCA/private
mkdir ~/rootCA/certs

openssl genrsa -out ~/rootCA/private/rootCA.key 4096
openssl req -x509 -new -nodes -key ~/rootCA/private/rootCA.key -sha256 -days 1024 -out ~/rootCA/certs/rootCA.pem

...
Country Name (2 letter code) [AU]:<mycountry>
State or Province Name (full name) [Some-State]:<myprovince>
Locality Name (eg, city) []:<mycity>
Organization Name (eg, company) [Internet Widgits Pty Ltd]:<mycompany>
Organizational Unit Name (eg, section) []:<mydepartment>
Common Name (e.g. server FQDN or YOUR name) []:<server_name in nginx>
Email Address []:

Create extension file we will use to create client certificates:

vi ~/rootCA/v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = %%DOMAIN%%

Create a site certificate

To create a site certificate, we first create a private key and a certificate request. This request is then signed by the CA with a certificate as a result:

cd ~/rootCA
openssl req -new -newkey rsa:4096 -sha256 -nodes -keyout ~/rootCA/private/<mysite>.key \
            -subj "/C=<mycountry>/ST=None/L=<mycity>/O=None/CN=<mysite>" \
            -out ~/rootCA/certs/<mysite>.csr
cat v3.ext | sed s/%%DOMAIN%%/<mysite>/g > /tmp/_v3.ext
openssl x509 -req -in ~/rootCA/certs/<mysite>.csr -CA ~/rootCA/certs/rootCA.pem \
            -CAkey ~/rootCA/private/rootCA.key -CAcreateserial \
            -out ~/rootCA/certs/<mysite>.crt -days 3650 -sha256 -extfile /tmp/_v3.ext

Copy the keys to /etc/ssl:

cp ~/rootCA/private/<mysite>.key /etc/ssl/private
cp ~/rootCA/certs/<mysite>.crt /etc/ssl/certs

The certificate names should be correctly set in nginx for the site.:

ssl_certificate /etc/ssl/certs/<mysite>.crt;
ssl_certificate_key /etc/ssl/private/<mysite>.key;

Now open your browser and add the CA to the trusted CA. On Debian/Ubuntu you can do this on the computer where you need to have the CA trusted:

mkdir -p /usr/share/ca-certificates/extra
cp ~/rootCA/certs/rootCA.pem /usr/share/ca-certificates/extra/rootCA.pem

Note

Firefox doesn't use the system-wide certificates but uses it's own certificate store. If you use Firefox, you will have to add the rootCA to the Firefox certificate store.

In case of a .pem file on Ubuntu, it must first be converted to a .crt file:

openssl x509 -in /usr/share/ca-certificates/extra/rootCA.pem -inform PEM -out /usr/share/ca-certificates/extra/rootCA.crt
dpkg-reconfigure ca-certificates

...

<add the rootCA certificate>
...
Bezig met afhandelen van triggers voor ca-certificates (20170717~16.04.1) ...
Updating certificates in /etc/ssl/certs...
WARNING: Skipping duplicate certificate COMODO_RSA_Certification_Authority.pem
WARNING: Skipping duplicate certificate COMODO_RSA_Certification_Authority.pem
WARNING: dhparam.pem does not contain a certificate or CRL: skipping
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

Now browse to the site, and you shouldn't get a SSL warning anymore.

Firefox certificate store

If you use Firefox, the above steps to add the rootCA don't work as it uses it's own keystore. To manually add the rootCA certificate, open preferences, go to "Privacy & Security", scroll down to "Certificates" and click "View Certificates...". Choose the tab "Organisations", click "Import". At the bottom right choose "Certificate files", choose rootCA.crt and click Open/OK.

Chrome certificate store

For chromium, visit chrome://settings, advanced, manage certificates, click Authorities, then click import, and select your .crt.