Deploy Zot, an OCI-native container registry, on CoreWeave Kubernetes Service (CKS). Store container images in CoreWeave AI Object Storage and use LOTA as the S3 endpoint for faster reads within the cluster.Documentation Index
Fetch the complete documentation index at: https://docs.coreweave.com/llms.txt
Use this file to discover all available pages before exploring further.
OCI conformanceCoreWeave has tested that the zot registry has passed the OCI Distribution Specification conformance suite, validating its compliance with the Open Container Initiative standards on our cloud. The conformance suite tests core registry operations including push and pull workflows, content discovery, and content management. This certification ensures Zot works reliably with OCI-compatible tooling and clients across the container ecosystem.
What you’ll use
This tutorial uses:- Zot: OCI-native container registry
- CoreWeave AI Object Storage: S3-compatible object storage for image layers
- LOTA: Local Object Transport Accelerator for in-cluster performance
- cert-manager: Automatic TLS certificate management
- Public LoadBalancer Service: Direct external exposure with a public FQDN under
.coreweave.app
What you’ll do
In this tutorial, you will:- Install cert-manager to issue a TLS certificate for the registry
- Create registry credentials for authenticating with the registry
- Issue a TLS certificate for the registry hostname
- Deploy Zot using Helm with S3-backed storage via LOTA, a public LoadBalancer Service, and the TLS certificate mounted into the pod
- Push and pull a container image to verify the registry
Prerequisites
Before you start, you must have:- A working CKS cluster
- Access Key and Secret Key with permissions to use a CoreWeave AI Object Storage bucket
- kubectl installed and configured for your cluster
- Helm version 3.8+
- Docker or another OCI-compatible client
Verify cluster access
Verify that you can access your cluster withkubectl:
cpu in the CLASS column:
Install cert-manager
This tutorial uses the CoreWeave cert-manager Helm chart to issue a TLS certificate for the registry. Add the CoreWeave Helm repository:ClusterIssuers:
ClusterIssuers are ready:
Determine the registry hostname
CoreWeave’s External Hostname Controller allocates an FQDN under.coreweave.app for any public LoadBalancer Service annotated with service.beta.kubernetes.io/external-hostname. For more details, see Create a public DNS name.
Your registry hostname will follow this pattern:
[ORG-ID]with your organization ID.[CLUSTER-NAME]with the name of the target CKS cluster.
abc123 and your cluster is named prod, your registry hostname is registry.abc123-prod.coreweave.app. Note this hostname for the steps below.
Create a storage bucket
Create an AI Object Storage bucket in the Cloud Console. Note the bucket name for later use.Generate access credentials
Create an Access Key for the bucket in the Cloud Console. Save the Access Key ID and Secret Key. You’ll need both when configuring Zot’s storage driver.Create registry credentials
Generate a bcrypt-hashed password for the registry admin user. Replaceyour-username and your-password with your chosen credentials:
If
htpasswd is not installed, install it with apt-get install apache2-utils on Debian/Ubuntu or brew install httpd on macOS.This tutorial uses htpasswd for simplicity. Zot also supports LDAP, mutual TLS, bearer token (OAuth2), and OpenID Connect with providers like GitHub, Google, and GitLab.
Issue a TLS certificate
Create aCertificate resource so cert-manager issues a TLS certificate for your registry hostname using the bundled letsencrypt-prod ClusterIssuer.
Save the following as registry-cert.yaml. Replace registry.[ORG-ID]-[CLUSTER-NAME].coreweave.app with the hostname from the previous step:
registry-cert.yaml
tls.crt and tls.key keys, which you’ll mount into the Zot pod in the next step.
Deploy Zot
Add the Zot Helm repository:zot-values.yaml file. Replace the placeholder values with your own:
zot-values.yaml
| Placeholder | Value |
|---|---|
[REGION] | The region of your AI Object Storage bucket (for example, us-east-14a) |
[BUCKET-NAME] | Your AI Object Storage bucket name |
[ACCESS-KEY-ID] | Your AI Object Storage Access Key ID |
[SECRET-KEY] | Your AI Object Storage Secret Key |
[USERNAME] | The registry admin username from the credentials step |
[HTPASSWD-STRING] | The $HTPASSWD value generated in the credentials step |
- The
serviceblock creates a publicLoadBalancerService. Theexternal-hostname: registryannotation tells the External Hostname Controller to allocateregistry.[ORG-ID]-[CLUSTER-NAME].coreweave.appfor the Service. Thecoreweave-load-balancer-type: publicannotation provisions a public IP. The Service listens on port 443 and forwards to the container’szotnamed port, which is set byhttpGet.port(see below). - The
ingress.enabled: falsefield disables the chart’s Ingress resource. External clients connect directly to the LoadBalancer Service, so no ingress controller is required. - The
httpGetblock sets the probe scheme toHTTPSand the container port to5000. The chart uses these values for its startup probe and to name the container port that the Service targets. The scheme must beHTTPSbecause Zot terminates TLS on this port; probing withHTTPwould fail. - The
extraVolumesandextraVolumeMountsfields mount theregistry-certSecret (created by cert-manager in the previous step) at/tlsinside the Zot container. Thehttp.tlsblock in the Zot config points totls.crtandtls.keyin that directory, so Zot terminates TLS natively. - The
regionmust match where your AI Object Storage bucket was created. Find this in the Cloud Console on the bucket details page. - The
regionendpointis set tohttp://cwlota.com, the LOTA endpoint. LOTA caches object storage reads on local Node disks for faster access. Thesecurefield isfalsebecause LOTA uses HTTP within the cluster. To access the bucket from outside a CKS cluster, usehttps://cwobject.comas the endpoint and setsecuretotrue. - The
compat: ["docker2s2"]field enables Docker v2 manifest support. Without this,docker pushwill fail because Zot rejects Docker v2 manifests by default. Remove this field if your workflow exclusively uses OCI-format images.
cert-manager renews the
registry-cert Secret automatically before expiry. Because the Secret is mounted into the Zot pod, the updated certificate is available on disk after rotation. Restart the Zot pod to pick up the renewed certificate if Zot does not reload it automatically.EXTERNAL-IP column should show a public IP address, and the second command should print registry.[ORG-ID]-[CLUSTER-NAME].coreweave.app. DNS propagation typically completes within one to two minutes.
Verify the registry
Log in to your registry using Docker. Replace[ORG-ID] and [CLUSTER-NAME] with the values for your cluster, and use the username and password you created in the Create registry credentials step:
REGISTRY_PASS in the Create registry credentials section (or use -p $REGISTRY_PASS to provide it directly).
Push a test image:
Enable the web UI (optional)
Zot ships with an optional web UI that lets you browse repositories, tags, and image manifests in a browser. The UI is disabled by default. To turn it on, enable theui and search Zot extensions in the Zot config. Both are required: the UI depends on the search extension for catalog data.
Add the following extensions block to the http object in zot-values.yaml. Place it as a sibling of log:
zot-values.yaml: configFiles.config.json additions
helm upgrade:
Retrieving the login passwordZot stores only the bcrypt hash of the password in the If Update the Sign in with the new credentials.
registry-htpasswd Secret, so the plaintext password cannot be read back from the cluster. If your shell still has the $REGISTRY_PASS environment variable from the Create registry credentials step, print it with:$REGISTRY_PASS is no longer set, use the plaintext password you chose when generating the htpasswd entry. If you’ve lost the password, rotate it by generating a new htpasswd entry and applying it through helm upgrade:secretFiles.htpasswd field in zot-values.yaml with the new $HTPASSWD value, then:What you’ve deployed
You now have a Zot container registry running on CKS with htpasswd authentication, S3-backed storage through LOTA, a Let’s Encrypt TLS certificate issued via a DNS01 challenge, and a public FQDN under the.coreweave.app domain.
External clients connect directly to the Zot LoadBalancer Service on port 443. Zot terminates TLS inside the pod using the mounted registry-cert Secret, and no ingress controller sits in the request path. cert-manager renews the certificate automatically before expiry.
To pull images from this registry in your CKS workloads, create an imagePullSecret with the same credentials used in the Create registry credentials step.
Clean up
To remove the registry and all resources installed in this tutorial:Uninstalling cert-manager leaves its Custom Resource Definitions (CRDs) in the cluster. To remove them completely: