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
Components are:
- The
req
component is like the toot of the tree of options which will make up thereq
command of openssl. - The
req_distinguished_name
component contains all the (default) parameters for the distinguished name (the ones you get asked when you create a CSR) - The
v3_req
has all the parameters for our certificate (CRT) alt_names
has 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
Initial errors
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.
Next steps:
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.
HTH,
Member discussion: