Setting up a private Docker Hub


This tutorial will explain how to set up your personal and private Docker Hub a.k.a. Docker Registry Server.


Hardware amd64 VPS
OS Debian 10 Buster


  1. Docker
  2. Internet Domain

Step by Step Instructions

1. Add DNS entry to your domain.

A domain of your choice needs to point to the address of your server.

2. Change to root user

sudo -s

3. Installation of additional Dependencies

apt update
apt install -y certbot nginx

4. Create dockerhub user and add persistence

useradd --system --create-home --shell /bin/bash --password <your-password-here> dockerhub
mkdir /home/dockerhub/registry

5. Create auth file

docker run --rm --entrypoint htpasswd registry:2 -bn admin <admin-password-here> > /home/dockerhub/nginx.htpasswd

6. Configure NGINX server

Create and open vhost file:

nano /etc/nginx/sites-available/dockerhub.domain.tld.vhost

Paste the following configuration into the file:

server {
  listen 80;
  server_name dockerhub.domain.tld;
  client_max_body_size 0;

  if ($host != "dockerhub.domain.tld") {
    return 444;

  location ~ /.well-known/acme-challenge/ {
    allow all;

  chunked_transfer_encoding on;

  location /v2/ {
    if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
      return 404;

    auth_basic "Registry realm";
    auth_basic_user_file /home/dockerhub/nginx.htpasswd;

    set $upstream "";
    proxy_pass                          http://$upstream$request_uri;
    proxy_set_header  Host              $http_host;
    proxy_set_header  X-Real-IP         $remote_addr;
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;

Activate vhost file:

ln -s /etc/nginx/sites-available/dockerhub.domain.tld.vhost /etc/nginx/sites-enabled/dockerhub.domain.tld.vhost

Restart NGINX:

systemctl restart nginx

7. Create Let's Encrypt certificate for dockerhub.domain.tld

Restart NGINX:

systemctl restart nginx

8. Run server

docker run --detach \
  --volume=/home/dockerhub/registry:/var/lib/registry \
  --publish=5000:5000 \
  --restart=on-failure \
  --name dockerhub \

9. Test server

if [[ $(curl -vs -H "Content-Type: application/json" 2>&1 | grep -q "200 OK")$? ]]; then echo OK; fi

If the last command responds with "OK" the server is set up successfully and works.