Enable GitLab Container Registry on an instance running HAProxy.

Edit /etc/gitlab/gitlab.rb GitLab configuration file to define registry address.

[...]
registry_external_url 'https://registry.example.org/'
[...]
Beware, parameters like nginx['listen_https'] = false and nginx['listen_port'] = 80 have no effect here.

Ensure that /etc/gitlab/ssl directory exists.

$ sudo mkdir /etc/gitlab/ssl

Generate a self-signed SSL certificate.

$ sudo openssl req -subj "/commonName=registry.example.org/" -x509 -nodes -days 730 -newkey rsa:2048 -keyout /etc/gitlab/ssl/registry.example.org.key -out /etc/gitlab/ssl/registry.example.org.crt

Reconfigure GitLab instance.

$ sudo gitlab-ctl reconfigure

It will set up a registry, so the Packages & Registries will become available in the sidebar.

Registry will use /var/opt/gitlab/nginx/conf/gitlab-registry.conf nginx configuration file. There is no possibility of using plain HTTP. Maybe that will change in the future, but not just yet.

# This file is managed by gitlab-ctl. Manual changes will be
# erased! To change the contents below, edit /etc/gitlab/gitlab.rb
# and run `sudo gitlab-ctl reconfigure`.
## Lines starting with two hashes (##) are comments with information.
## Lines starting with one hash (#) are configuration parameters that can be uncommented.
##
###################################
##         configuration         ##
###################################
server {
  listen *:443 ssl;
  server_name registry.example.org;
  server_tokens off; ## Don't show the nginx version number, a security best practice
  client_max_body_size 0;
  chunked_transfer_encoding on;
  ## Strong SSL Security
  ## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/
  ssl_certificate /etc/gitlab/ssl/registry.example.org.crt;
  ssl_certificate_key /etc/gitlab/ssl/registry.example.org.key;
  ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4';
  ssl_protocols  TLSv1.2 TLSv1.3;
  ssl_prefer_server_ciphers on;
  ssl_session_cache  builtin:1000  shared:SSL:10m;
  ssl_session_timeout  5m;
  ## Real IP Module Config
  ## http://nginx.org/en/docs/http/ngx_http_realip_module.html
  access_log  /var/log/gitlab/nginx/gitlab_registry_access.log gitlab_access;
  error_log   /var/log/gitlab/nginx/gitlab_registry_error.log;
  location / {
    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 https;
    proxy_set_header X-Forwarded-Ssl on;
    proxy_read_timeout                  900;
    proxy_cache off;
    proxy_buffering off;
    proxy_request_buffering off;
    proxy_http_version 1.1;
    proxy_pass          http://localhost:5000;
  }
}

Update the HAProxy configuration file.

global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
        stats timeout 30s
        user haproxy
        group haproxy
        daemon
        # Default SSL material locations
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private
        # Default ciphers to use on SSL-enabled listening sockets.
        # For more information, see ciphers(1SSL). This list is from:
        #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
        # An alternative list with additional directives can be obtained from
        #  https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
        ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
        ssl-default-bind-options no-sslv3
defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http
frontend ssh-gitlab-frontend
  bind 1.2.3.4:22
  mode tcp
  use_backend backend-gitlab-ssh
frontend web-frontend
  bind 1.2.3.4:443 ssl crt /etc/haproxy/ssl/cloudflare.pem
  mode http
  acl is-gitlab    hdr(host) -i gitlab.example.org
  acl is-registry  hdr(host) -i registry.example.org
  use_backend backend-local-gitlab if is-gitlab
  use_backend backend-local-registry if is-registry
  default_backend no-match
backend backend-local-gitlab
  server gitlab 172.16.0.10:80
backend backend-local-registry
  server registry 172.16.0.10:443 ssl verify none
backend backend-gitlab-ssh
  mode tcp
  server gitlab-ssh 172.16.0.10:22
backend no-match
  http-request deny deny_status 400
Notice, it will not verify the SSL certificate.

Reload HAProxy service and use your GitLab registry.

$ sudo systemctl reload haproxy