I'm preparing my docker-based infrastructure and one of the items (to make my live a bit more complicated) is to install a private docker registry. One of the requirements is to obtain a certificate (so I don't have an insecure registry).
Create a self-signed certificate
First, we need to establish our requirements:
- Certificate is self-signed (for officially signed certificates, the process is different)
- We need the certificate to be for a domain and all its subdomains
- We might need to add an IP address too
Now that we have this isn place, let's build a configuration file (
openssl accepts config files!). I'll show the file in its entirety and then explain its components:
# file: selfsigned.cnf [req] distinguished_name = req_distinguished_name req_extensions = v3_req [req_distinguished_name] countryName = BE country_name_default = BE stateOrProvinceName = Belgium stateOrProvinceName_default = Belgium localityName = Belgium localityName_default = Belgium organizationalUnitName = LaurIvan organizationalUnitName_default = LaurIvan commonName = *.domain.com commonName_max = 64 [v3_req] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = *.domain.com IP.1 = 192.168.1.200
reqcomponent is like the toot of the tree of options which will make up the
reqcommand of openssl.
req_distinguished_namecomponent contains all the (default) parameters for the distinguished name (the ones you get asked when you create a CSR)
v3_reqhas all the parameters for our certificate (CRT)
alt_nameshas all the names accepted by the certificate. This will allow us that subdomains are accepted and also a specific IP address (e.g. where my docker registry is)
Create the certificate
First, we create the private key:
sudo openssl genrsa -out domain.com.key 2048
Then, we create the CSR, with our self-signed configuration:
sudo openssl req -new -out domain.com.csr \ -key domain.com.key \ -config selfsigned.cnf
Lastly, we create the CRT:
sudo openssl x509 -req -days 3650 \ -signkey domain.com.key \ -in domain.com.csr \ -extensions v3_req -extfile selfsigned.cnf \ -out domain.com.crt
To note that I already have a self-signed certificate, but while playing around, I've got a number of errors...
First one was:
x509: certificate signed by unknown authority
I passed it by adding the certificate into my build machine's list of docker certificates:
Create a docker folder with your server's address:
sudo mkdir -p /etc/docker/certs.d/[IP Address]:[Port]/
Copy the certificate used by the registry there:
sudo scp \ laur@[server]:/etc/certificates/[registry_cert].crt \ /etc/docker/certs.d/[IP Address]:[Port]/
A second error was:
x509: cannot validate certificate for <ip-address> because it doesn't contain any IP SANs
For this one, I had do add the IP address in the
alt_names section of the self-signed config file.
I have the following next steps in mind:
- Use a reverse proxy (working with the IP address of the registry server is not nice)
- Create an ansible role to do it for me in a reproducible way (and in a way I can add the certificates everywhere I need :)
- Use a different certificate like let's encrypt.