{
"path": "/3mjdpz4ti422b",
"site": "at://did:plc:nuc33thnsiqzhytkleyr5jek/site.standard.publication/3mjdo3xyaoc2l",
"tags": [
"self-hosting",
"caddy",
"tailscale",
"container-registry"
],
"$type": "site.standard.document",
"title": "Self-hosted container registry with web UI",
"content": {
"$type": "pub.leaflet.content",
"pages": [
{
"id": "019d8476-8c22-7220-b994-274411b6faef",
"$type": "pub.leaflet.pages.linearDocument",
"blocks": [
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 51,
"byteStart": 8
},
"features": [
{
"uri": "https://github.com/Joxit/docker-registry-ui",
"$type": "pub.leaflet.richtext.facet#link"
}
]
}
],
"plaintext": "Source: https://github.com/Joxit/docker-registry-ui"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Docker/Podman compose"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "yaml",
"plaintext": "services:\n registry-ui:\n image: joxit/docker-registry-ui:main\n restart: always\n ports:\n - \"127.0.0.1:4433:80\"\n environment:\n - SINGLE_REGISTRY=true\n - REGISTRY_TITLE=hyperreal's Container Registry\n - DELETE_IMAGES=true\n - SHOW_CONTENT_DIGEST=true\n - NGINX_PROXY_PASS_URL=http://registry-server:5000\n - SHOW_CATALOG_NB_TAGS=true\n - CATALOG_MIN_BRANCHES=1\n - CATALOG_MAX_BRANCHES=1\n - TAGLIST_PAGE_SIZE=100\n - REGISTRY_SECURED=false\n - CATALOG_ELEMENTS_LIMIT=1000\n container_name: registry-ui\n\n registry-server:\n image: registry:2.8.2\n restart: always\n environment:\n REGISTRY_HTTP_HEADERS_Access-Control-Allow-Origin: '[http://aux-remote.carp-wyvern.ts.net]'\n REGISTRY_HTTP_HEADERS_Access-Control-Allow-Methods: '[HEAD,GET,OPTIONS,DELETE]'\n REGISTRY_HTTP_HEADERS_Access-Control-Allow-Credentials: '[true]'\n REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '[Accept,Cache-Control]'\n REGISTRY_HTTP_HEADERS_Access-Control-Expose-Headers: '[Docker-Content-Digest]'\n REGISTRY_STORAGE_DELETE_ENABLED: 'true'\n volumes:\n - ./registry/data:/var/lib/registry\n container_name: registry-server",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Authorization and Authentication"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "For a public registry with authentication, the following headers are required:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "yaml",
"plaintext": "environment:\n REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '[Authorization,Accept,Cache-Control]'",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "For a private registry without authentication, the following headers are required:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "yaml",
"plaintext": "environment:\n REGISTRY_HTTP_HEADERS_Access-Control-Allow-Headers: '[Accept,Cache-Control]'",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Caddy reverse proxy"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 3,
"plaintext": "Public registry"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "plaintext",
"plaintext": "registry.hyperreal.coffee {\n reverse_proxy localhost:4433\n}",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 3,
"plaintext": "Private registry via Tailnet"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "plaintext",
"plaintext": "aux-remote.carp-wyvern.ts.net {\n reverse_proxy localhost:4433\n}",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 56,
"byteStart": 33
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
}
],
"plaintext": "Ensure the following is added to /etc/default/tailscaled:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "shellscript",
"plaintext": "TS_PERMIT_CERT_UID=caddy",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "The above will ensure Caddy receives SSL certs from the Tailscale daemon."
}
}
]
}
]
},
"description": "",
"publishedAt": "2026-02-16T02:34:00.000Z"
}