Zot Registry supports Bearer Authentication. For configuration details, check the documentation.
The main advantage of using Bearer Authentication is the ability to reuse your existing Docker authentication services. As you may know, Docker’s authentication relies on third-party services, like the popular docker_auth. docker_auth offers more flexible access control lists (ACL) compared to Zot’s current setup and allows you to leverage existing infrastructure.
However, it’s important to note that Zot’s support for Bearer Authentication is limited to the CLI. If you enable Bearer Authentication, the Zot UI login will become unusable. The implementation of Bearer Authentication is separate; once you configure it, other authentication methods will no longer be available.
Unfortunately, this means some modifications are necessary. You can find the hack version here.
Make sure to enable at least one other authentication method (like LDAP or htpass). This way, the CLI will prioritize using the docker_auth Bearer Authentication service, while the web will switch to the next available authentication method based on Zot’s own permission configurations (my web setup is read-only, so my permissions are straightforward).
Another consideration is if you have caching configured in Nginx. You need to disable caching for the /v2/
route. If you’ve set up proxy_hide_header www-authentication
, be sure to remove it. Zot should handle authentication without interference to avoid push failures. If you’re not using Bearer Authentication and need path remapping (like syncing image caches to different paths), this configuration must remain in place.
update:
Podman will pull image by first ping /v2/
url, which will return www-authentication header with information of authentication. But our pull through cache made image path remapping which will cause auth request with wrong scope.
For example, when we pull image docker.io/library/debian:bookworm
which remmapped to <your_mirror>/docker.io/library/debian:bookworm
. Instead of request auth svc with https://<docker_auth>/auth?scope=repository%3Adocker.io%2Flibrary%2Fdebian%3Apull&service=<svc>
, podman will request https://<docker_auth>/auth?scope=repository%3Alibrary%2Fdebian%3Apull&service=docker.io
. Notice the different scope of docker.io/library/debian
and library/debian
.
We must tell the docker_auth svc that scope has been remmapped. But we can’t ask podman to change this path mapping cause we wanna provide a transparent mirror svc without client noticed. So we have to find a way to provide mapping info to our docker_auth service. Here I reused service field to provide mapping info.
In the mirror nginx config I add this conf to override the zot returned auth info to change service arg to the mirror host.
map $upstream_http_www_authenticate $rewritten_www_authenticate_header {
~^(?<prefix2>.*service=\").*(?<suffix2>\",scope=).*$ ${prefix2}${mirror_subpath}${suffix2}"${mirror_subpath}";
}
location = /v2/ {
...
proxy_cache off;
proxy_hide_header Www-Authenticate;
add_header Www-Authenticate $rewritten_www_authenticate_header always;
}
And in the docker_auth nginx config
map $args $rewritten_docker_auth_scope_args {
~^(?<mirror_docker_auth_p1>scope=repository%3A)(?<mirror_docker_auth_s1>.*&service=)(?<mirror_docker_auth_s2>.*)$ ${mirror_docker_auth_p1}${mirror_docker_auth_s2}%2F${mirror_docker_auth_s1}${mirror_docker_auth_s2};
default $args;
}
location / {
...
if ($args !~* "^scope=repository%3A.+service=.+<your_mirror_service>$") {
# for zot registry mirror auth
set $args $rewritten_docker_auth_scope_args;
}
}
It take the service field and add it as the prefix of the original scope so we can get the right path mapping. For our original mirror serice (image we uploaded by ourself), we just skip the mapping hacking.