This blogpost describes how to easily deploy a secure docker registry with Portus.

Intended audience: system administrators and DevOps engineers familiar with Docker and its ecosystem.

By Quentin Anglade, professional tinkerer and security freak @ Objectif Libre

Self-hosting a secure docker registry with Portus

Having your own registry for storing public or private images is useful. Stay tuned, there will soon be another post about different self-hosted open-source docker registries, including more details on Portus and its integration of clair.

So you might want to deploy Portus to cover your needs. As you are a responsible person, you may want to deploy portus with https/tls AND the vulnerability scanner clair. Unfortunately, the docker-compose files provided in the portus github only have https without clair and clair without https.

Do not look further, here is an https + clair deployment.

Deploying Portus registry

We will be using docker-compose for an easy deployment. Just clone the Portus repository to get the compose folder, edit the .env and the nginx configuration to set the server_name according to your domain, then add the https + clair compose file.

$ git clone /tmp/portus
$ mv /tmp/portus/examples/compose ./portus
$ cd portus && $EDITOR .env nginx/nginx.conf
$ rm docker-compose.* && wget

If you want to test this secure installation of Portus without your own trusted certificate on a public ip, you can simply generate one (do not forget to change with your server IP/domain):

echo "subjectAltName = IP:" > extfile.cnf #You can use DNS:domain.tld too
openssl genrsa -out secrets/rootca.key 2048 -nodes
openssl req -x509 -new -nodes -key secrets/rootca.key \
 -subj "/C=US/ST=CA/O=Acme, Inc." \
 -sha256 -days 1024 -out secrets/rootca.crt
openssl genrsa -out secrets/portus.key 2048
openssl req -new -key secrets/portus.key -out secrets/portus.csr \
 -subj "/C=US/ST=CA/O=Acme, Inc./CN="
openssl x509 -req -in secrets/portus.csr -CA secrets/rootca.crt -extfile \
 extfile.cnf -CAkey secrets/rootca.key -CAcreateserial \
 -out secrets/portus.crt -days 500 -sha256

Let me explain what we’ve done here:

  • We need a certificate authority (CA), so we created a random key (rootca.key) and used it to generate a certificate (rootca.crt) valid for 1024 days.
  • We need a private key for portus, so we generated a random one.
  • Then we created a certificate signing request and used it to create our portus certificate using the “extfile.cnf”.

This step is required because without the subjectAltName you will run into issues with the registry.

You will need to add secrets/rootca.crt to your system to use portus and its registry with your custom CA.

If you already have a certificate for your domain, simply add your existing key and certificate as portus.key and portus.crt in the secrets folder.

A simple docker-compose up -d and that’s all you need to deploy portus. Now, head to your server IP/domain with your favorite browser and setup the portus admin account. Next, portus will ask you about your registry. Enter a friendly name and the full ip and port of the machine portus is installed on (to avoid https/tls errors about common name mismatch). Of course, since we use https, check the “Use SSL” box.


You now have a fully functionnal docker registry with Portus as its ui / authentication frontend. You should be able to docker login yourserver:5000 with your recently created admin credentials. Be careful, it takes time for clair to download all the vulnerabilities, so clair may not report any vulnerabilities at first. You should see a list of vulnerabilities when clair is working properly: