Docker-Powered Web Development Utilizing HTTPS and Local Domain Names
By: Onno Gabriel
Tags: Programming, Docker, Https, Web Development, Development

Creation of Self-Signed Certificates

We can perform all the next steps in the folder .certs , i.e. the one that nginx-proxy also uses for the HTTPS configuration.

The process is as follows:

First, we’ll create a root SSL certificate, also called CA certificate or just root CA. This has to be done only once. Then later, we will generate a certificate for each local domain and sign it with this root CA. I wrote a bash script to automate this process, but for now, we will go through the whole process step by step.

1. Creation of a root CA

First, we generate a private key for the root CA, a file called rootCA.key :

$ openssl genrsa -out rootCA.key 4096

This key is not password protected (it could be if we add the parameter -des3 to the command).

Please be aware that the process described here is just for your local development environment. Do not use it in production!

Now, we self-sign the generated key by answering some questions about us:

$ openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt 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]:DE

State or Province Name (full name) [Some-State]:Berlin

Locality Name (eg, city) []:Berlin

Organization Name (eg, company) [Internet Widgits Pty Ltd]:My-Company

Organizational Unit Name (eg, section) []:Development

Common Name (e.g. server FQDN or YOUR name) []:My-Company

Email Address []:xxx@yyyy.zz

It is not important what we enter here. The Common Name will later appear in the list of our trusted authorities, so we should choose a name we can easily recognize.

Now we have everything to become our own certificate authority. At least for our own purposes, because no browser in the world knows about our CA yet.

To make a browser familiar with our root CA, we have to import it.

On macOS, we can add the root CA to the Keychain.

On Linux or Windows, we can import the root CA to the trusted authorities in our browser(s).

Each browser has a different settings page, so please have a look at your browser’s documentation (or search e.g. “import root ca in chrome/firefox/edge/”).

2. Create a Certificate for Each Domain

The next step is the creation of a certificate for a local domain, e.g. for my-cool-app.localhost .

Again, we create a private key first:

$ openssl genrsa -out my-cool-app.localhost.key 2048

Then, we create a signing request for this key:

$ openssl req -new -sha256 -key my-cool-app.localhost.key -out my-cool-app.localhost.csr

We will again be asked some questions. The important one is the one about the Common Name: this has to be equal to our local domain (e.g. my-cool-app.localhost ).

The last step will be the signing of your certificate with the root CA.

To do so, we will need a small configuration file called my-cool-app.localhost.v3.ext :

authorityKeyIdentifier=keyid,issuer

basicConstraints=CA:FALSE

keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment

subjectAltName = @alt_names

[alt_names]

DNS.1 = my-cool-app.localhost

Important here is the last line, which again contains the local domain.

For this domain, we can now sign the certificate with the root CA:

$ openssl x509 -req -in my-cool-app.localhost.csr -CA my-cool-app.localhost.crt -CAkey my-cool-app.localhost.key -CAcreateserial -out my-cool-app.localhost.crt -days 1024 -sha256 -extfile my-cool-app.localhost.v3.ext

This finally creates our certificate: my-cool-app.localhost.crt .

The .certs folder should now contain the key and certificate for my-cool-app.localhost .

Restart Docker Compose and the nginx-proxy should serve our demo app via HTTPS now: