How to Enable the Peer-to-Peer OCI Registry Plugin for DigitalOcean Kubernetespublic

Last verified 11 Aug 2026

DigitalOcean Kubernetes (DOKS) is a Kubernetes service with a fully managed control plane, high availability, and autoscaling. DOKS integrates with standard Kubernetes toolchains and DigitalOcean’s load balancers, volumes, CPU and GPU Droplets, API, and CLI.

Note

The peer-to-peer OCI registry plugin is in public preview and is available on new clusters running Kubernetes 1.36 or later. Existing clusters upgrading to 1.36 are not yet supported.

DigitalOcean Kubernetes (DOKS) includes an optional peer-to-peer OCI registry plugin that mirrors container images across cluster nodes. The plugin uses Spegel, an open-source, stateless OCI registry mirror, to let nodes pull image layers from each other instead of the origin registry every time. This reduces the number of pulls that leave the cluster, which lowers your exposure to external registries’ rate limits and speeds up image pulls on clusters that reuse the same images across many nodes.

Each node runs its own Spegel instance and advertises the image layers it already has to the rest of the cluster. When a node needs to pull a layer, containerd checks whether a peer already has it before falling back to the original registry. This works transparently. You don’t need to change your image references or registry configuration to benefit from it.

The plugin is disabled by default. You can enable or disable it using doctl, the DigitalOcean API, Godo, or Terraform, and verify that it’s running with kubectl.

Enable or Disable the Plugin

In the API, the plugin is controlled through the p2p_oci_registry_plugin object on the Kubernetes cluster resource. Set enabled to true to turn the plugin on, or false to turn it off. Omitting the object from a request leaves the plugin’s current state unchanged.

To enable the plugin when creating a cluster, set the --enable-peer-to-peer-oci-registry-plugin flag to true.

doctl kubernetes cluster create example-cluster --region nyc1 --version latest --enable-peer-to-peer-oci-registry-plugin=true

To enable or disable the plugin on an existing cluster, update the cluster with the same flag:

doctl kubernetes cluster update example-cluster --enable-peer-to-peer-oci-registry-plugin=false

To check whether the plugin is enabled on a cluster:

doctl kubernetes cluster get example-cluster --format PeerToPeerOciRegistryPlugin

The output shows whether the plugin is enabled:

Output
Peer-to-peer OCI registry Plugin
true

To enable the plugin when creating a cluster, send a POST request to https://api.digitalocean.com/v2/kubernetes/clusters with a request body similar to the following:

curl --location 'https://api.digitalocean.com/v2/kubernetes/clusters' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
--data '{
    "name": "example-cluster",
    "region": "nyc1",
    "version": "1.36.1-do.0",
    "node_pools": [
        {
            "size": "s-2vcpu-4gb",
            "count": 3,
            "name": "worker-pool"
        }
    ],
    "p2p_oci_registry_plugin": {
        "enabled": true
    }
}'

To enable or disable the plugin on an existing cluster, send a PUT request to https://api.digitalocean.com/v2/kubernetes/clusters/{cluster_id} with a request body similar to the following:

curl --location --request PUT 'https://api.digitalocean.com/v2/kubernetes/clusters/{cluster_id}' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
--data '{
    "name": "example-cluster",
    "p2p_oci_registry_plugin": {
        "enabled": false
    }
}'

Go developers can use Godo, the official DigitalOcean V2 API client for Go. To enable the plugin when creating a Kubernetes cluster with Godo, use code similar to the following:

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/digitalocean/godo"
)

func main() {
	client := godo.NewFromToken("your-digitalocean-token")

	cluster, _, err := client.Kubernetes.Create(context.Background(), &godo.KubernetesClusterCreateRequest{
		Name:        "example-cluster",
		RegionSlug:  "nyc1",
		VersionSlug: "1.36.1-do.0",
		NodePools: []*godo.KubernetesNodePoolCreateRequest{
			{
				Name:  "worker-pool",
				Count: 3,
				Size:  "s-2vcpu-4gb",
			},
		},
		P2pOciRegistryPlugin: &godo.KubernetesP2pOciRegistry{
			Enabled: godo.PtrTo(true),
		},
	})
	if err != nil {
		fmt.Printf("Error creating cluster: %s\n", err)
		os.Exit(1)
	}

	isEnabled := *cluster.P2pOciRegistryPlugin.Enabled
	fmt.Printf("Cluster creation successfully issued with peer-to-peer OCI registry plugin enabled=%v\n", isEnabled)
}

To enable or disable the plugin on an existing cluster with Godo, use code similar to the following:

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/digitalocean/godo"
)

func main() {
	client := godo.NewFromToken("your-digitalocean-token")

	cluster, _, err := client.Kubernetes.Update(context.Background(), "your-cluster-id", &godo.KubernetesClusterUpdateRequest{
		Name: "example-cluster",
		P2pOciRegistryPlugin: &godo.KubernetesP2pOciRegistry{
			Enabled: godo.PtrTo(false),
		},
	})
	if err != nil {
		fmt.Printf("Error updating cluster: %s\n", err)
		os.Exit(1)
	}

	isEnabled := *cluster.P2pOciRegistryPlugin.Enabled
	fmt.Printf("Cluster update successfully issued with peer-to-peer OCI registry plugin enabled=%v\n", isEnabled)
}

To enable the plugin, add a p2p_oci_registry_plugin block to the digitalocean_kubernetes_cluster resource:

resource "digitalocean_kubernetes_cluster" "example" {
  name    = "example-cluster"
  region  = "nyc1"
  version = "1.36.1-do.0"

  node_pool {
    name       = "worker-pool"
    size       = "s-2vcpu-4gb"
    node_count = 3
  }

  p2p_oci_registry_plugin {
    enabled = true
  }
}

To disable the plugin, set enabled = false in the same block.

Verify the Plugin Is Running

When the plugin is enabled, DOKS runs Spegel as a DaemonSet named k8s-spegel in the kube-system namespace, labeled c3.doks.digitalocean.com/component=p2p-oci-registry. To confirm it’s running on every node:

kubectl get daemonset k8s-spegel -n kube-system

The output looks similar to the following:

Output
NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
k8s-spegel   3         3         3       3            3           <none>          10m

The DESIRED and READY columns should match your node count. If they don’t, check the plugin’s pods for errors:

kubectl get pods -n kube-system -l c3.doks.digitalocean.com/component=p2p-oci-registry

Each node should have one k8s-spegel pod in the Running state. Fewer pods than nodes, or pods stuck in another state, means the plugin isn’t running on every node yet.

We can't find any results for your search.

Try using different keywords or simplifying your search terms.