Self-hosted container registry with web UI

Source: https://github.com/Joxit/docker-registry-ui

Docker/Podman compose

services:
registry-ui:
image: joxit/docker-registry-ui:main
restart: always
ports:
- "127.0.0.1:4433:80"
environment:
- SINGLE_REGISTRY=true
- REGISTRY_TITLE=hyperreal's Container Registry
- DELETE_IMAGES=true
- SHOW_CONTENT_DIGEST=true
- NGINX_PROXY_PASS_URL=http://registry-server:5000
- SHOW_CATALOG_NB_TAGS=true
- CATALOG_MIN_BRANCHES=1
- CATALOG_MAX_BRANCHES=1
- TAGLIST_PAGE_SIZE=100
- REGISTRY_SECURED=false
- CATALOG_ELEMENTS_LIMIT=1000
container_name: registry-ui

registry-server:
image: registry:2.8.2
restart: always
environment:
REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: '[http://aux-remote.carp-wyvern.ts.net]'
REGISTRY_HTTP_HEADERS_Access-Control-Allow-Methods: '[HEAD,GET,OPTIONS,DELETE]'
REGISTRY_HTTP_HEADERS_Access-Control-Allow-Credentials: '[true]'
REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '[Accept,Cache-Control]'
REGISTRY_HTTP_HEADERS_Access-Control-Expose-Headers: '[Docker-Content-Digest]'
REGISTRY_STORAGE_DELETE_ENABLED: 'true'
volumes:
- ./registry/data:/var/lib/registry
container_name: registry-server

Authorization and Authentication

For a public registry with authentication, the following headers are required:

environment:
REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '[Authorization,Accept,Cache-Control]'

For a private registry without authentication, the following headers are required:

environment:
REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '[Accept,Cache-Control]'

Caddy reverse proxy

Public registry

registry.hyperreal.coffee {
reverse_proxy localhost:4433
}

Private registry via Tailnet

aux-remote.carp-wyvern.ts.net {
reverse_proxy localhost:4433
}

Ensure the following is added to /etc/default/tailscaled:

TS_PERMIT_CERT_UID=caddy

The above will ensure Caddy receives SSL certs from the Tailscale daemon.