diff --git a/roles/ensure-skopeo/defaults/main.yaml b/roles/ensure-skopeo/defaults/main.yaml
index ad4385db1..08b6e315f 100644
--- a/roles/ensure-skopeo/defaults/main.yaml
+++ b/roles/ensure-skopeo/defaults/main.yaml
@@ -1,2 +1,4 @@
 ensure_skopeo_install_from_upstream: false
-ensure_skopeo_install_from_upstream_version: 'v1.9.3'
+# Needs to be 1.14.2 or newer to negotiate Docker API versions against
+# Docker 25 or newer.
+ensure_skopeo_install_from_upstream_version: 'v1.14.2'
diff --git a/roles/ensure-skopeo/tasks/Debian.yaml b/roles/ensure-skopeo/tasks/Debian.yaml
new file mode 100644
index 000000000..246251ef4
--- /dev/null
+++ b/roles/ensure-skopeo/tasks/Debian.yaml
@@ -0,0 +1,49 @@
+- name: Install skopeo from packages
+  when: not ensure_skopeo_install_from_upstream
+  package:
+    name:
+      - skopeo
+      - uidmap
+    state: present
+  become: yes
+
+- name: Install skopeo from upstream
+  when: ensure_skopeo_install_from_upstream
+  block:
+
+    - name: Install dependencies
+      become: yes
+      package:
+        name:
+          - libgpgme-dev
+          - libassuan-dev
+          - libbtrfs-dev
+          - libdevmapper-dev
+          - pkg-config
+          - build-essential
+          - golang
+        state: present
+
+    - name: Clone upstream source
+      git:
+        repo: https://github.com/containers/skopeo
+        dest: '{{ ansible_user_dir }}/skopeo'
+        version: '{{ ensure_skopeo_install_from_upstream_version }}'
+
+    - name: Build skopeo
+      command: 'make'
+      args:
+        chdir: '{{ ansible_user_dir }}/skopeo'
+      environment:
+        DISABLE_DOCS: 1
+
+    - name: Install binary
+      become: yes
+      command: 'make install'
+      args:
+        chdir: '{{ ansible_user_dir }}/skopeo'
+      environment:
+        DISABLE_DOCS: 1
+
+    - name: Test binary
+      command: '/usr/local/bin/skopeo --version'
diff --git a/test-playbooks/ensure-skopeo/main.yaml b/test-playbooks/ensure-skopeo/main.yaml
index b928b85e4..7234abc3f 100644
--- a/test-playbooks/ensure-skopeo/main.yaml
+++ b/test-playbooks/ensure-skopeo/main.yaml
@@ -11,6 +11,16 @@
         name: ensure-skopeo
       vars:
         ensure_skopeo_install_from_upstream: true
+        # Skopeo 1.14.0 and newer require golang 1.19 but only 1.18 is
+        # available on jammy.
+        ensure_skopeo_install_from_upstream_version: 'v1.13.3'
+
+    - name: Additionally test from source on Debian Bookworm
+      when: ansible_distribution_release == 'bookworm'
+      include_role:
+        name: ensure-skopeo
+      vars:
+        ensure_skopeo_install_from_upstream: true
 
     - name: Exercise skopeo
       command: /usr/bin/skopeo -v
diff --git a/test-playbooks/registry/buildset-registry-pre.yaml b/test-playbooks/registry/buildset-registry-pre.yaml
index ac0afc6d2..ff90bcf1e 100644
--- a/test-playbooks/registry/buildset-registry-pre.yaml
+++ b/test-playbooks/registry/buildset-registry-pre.yaml
@@ -1,7 +1,10 @@
 - hosts: all
   roles:
     - ensure-docker
-    - ensure-skopeo
+    - role: ensure-skopeo
+      vars:
+        # Needs to be new enough skopeo to negotiate docker api versions
+        ensure_skopeo_install_from_upstream: true
 
   tasks:
     # This happens in the pre-playbook of the
diff --git a/zuul-tests.d/container-roles-jobs.yaml b/zuul-tests.d/container-roles-jobs.yaml
index 0d2014aac..2a4ab9e84 100644
--- a/zuul-tests.d/container-roles-jobs.yaml
+++ b/zuul-tests.d/container-roles-jobs.yaml
@@ -235,12 +235,12 @@
     vars:
       container_command: docker
       multiarch: false
-    nodeset:
+    nodeset: &registry_nodeset
       nodes:
         - name: intermediate-registry
           label: ubuntu-jammy
         - name: executor
-          label: ubuntu-jammy
+          label: debian-bookworm
         - name: builder
           label: ubuntu-jammy
 
@@ -266,14 +266,7 @@
     vars:
       container_command: docker
       multiarch: true
-    nodeset:
-      nodes:
-        - name: intermediate-registry
-          label: ubuntu-jammy
-        - name: executor
-          label: ubuntu-jammy
-        - name: builder
-          label: ubuntu-jammy
+    nodeset: *registry_nodeset
 
 - job:
     name: zuul-jobs-test-registry-podman
@@ -298,17 +291,96 @@
     vars:
       container_command: podman
       multiarch: false
+    nodeset: *registry_nodeset
+
+- job:
+    name: zuul-jobs-test-registry-buildset-registry
+    parent: opendev-buildset-registry
+    description: |
+      Run a buildset registry for the test-registry jobs
+
+      This runs two registries: a real buildset registry so that we
+      can receive speculative zuul-registry images, and a fake
+      buildset registry (running the speculative or latest
+      zuul-registry) that is used to test using the buildset registry
+      role.
+
+      It is not meant to be used directly but rather run on changes
+      to roles in the zuul-jobs repo.
+    files:
+      - roles/pull-from-intermediate-registry/.*
+      - roles/push-to-intermediate-registry/.*
+      - roles/ensure-docker/.*
+      - roles/ensure-kubernetes/.*
+      - roles/ensure-openshift/.*
+      - roles/ensure-package-repositories/.*
+      - roles/build-docker-image/.*
+      - roles/run-buildset-registry/.*
+      - roles/use-buildset-registry/.*
+      - test-playbooks/registry/.*
+      - zuul-tests.d/container-roles-jobs.yaml
+    pre-run: test-playbooks/registry/buildset-registry-pre.yaml
+    run: test-playbooks/registry/buildset-registry.yaml
+    post-run: test-playbooks/registry/test-registry-post.yaml
+    vars:
+      container_command: docker
+      # Override the docker_mirror_base_url back to the role default. OpenDev
+      # base jobs set this to the OpenDev mirrors but those mirrors only host
+      # Ubuntu not Debian packages.
+      docker_mirror_base_url: '{{ _docker_mirror_base_url }}'
     nodeset:
       nodes:
-        - name: intermediate-registry
-          label: ubuntu-jammy
-        - name: executor
-          label: ubuntu-jammy
-        - name: builder
-          label: ubuntu-jammy
+        - name: debian-bookworm
+          label: debian-bookworm
+
+- job:
+    name: zuul-jobs-test-registry-buildset-registry-k8s-microk8s
+    dependencies: zuul-jobs-test-registry-buildset-registry
+    description: |
+      Test a buildset registry with microk8s
+
+      It is not meant to be used directly but rather run on changes
+      to roles in the zuul-jobs repo.
+    files:
+      - roles/pull-from-intermediate-registry/.*
+      - roles/push-to-intermediate-registry/.*
+      - roles/ensure-docker/.*
+      - roles/ensure-package-repositories/.*
+      - roles/build-docker-image/.*
+      - roles/run-buildset-registry/.*
+      - roles/use-buildset-registry/.*
+      - test-playbooks/registry/.*
+    run: test-playbooks/registry/buildset-registry-k8s-microk8s.yaml
+    post-run:
+      - test-playbooks/registry/test-registry-post.yaml
 
 # FIXME(yoctozepto): crio jobs are disabled because their repository seems to be broken
 
+# - job:
+#     name: zuul-jobs-test-registry-buildset-registry-k8s-crio
+#     dependencies: zuul-jobs-test-registry-buildset-registry
+#     description: |
+#       Test a buildset registry with kubernetes and CRIO
+
+#       It is not meant to be used directly but rather run on changes
+#       to roles in the zuul-jobs repo.
+#     files:
+#       - roles/pull-from-intermediate-registry/.*
+#       - roles/push-to-intermediate-registry/.*
+#       - roles/ensure-docker/.*
+#       - roles/ensure-kubernetes/.*
+#       - roles/ensure-package-repositories/.*
+#       - roles/build-docker-image/.*
+#       - roles/run-buildset-registry/.*
+#       - roles/use-buildset-registry/.*
+#       - test-playbooks/registry/.*
+#     run: test-playbooks/registry/buildset-registry-k8s-crio.yaml
+#     post-run:
+#       - test-playbooks/registry/buildset-registry-k8s-crio-post.yaml
+#       - test-playbooks/registry/test-registry-post.yaml
+#     vars:
+#       container_command: podman
+
 # - job:
 #     name: zuul-jobs-test-ensure-kubernetes-crio
 #     description: |
@@ -409,13 +481,33 @@
       used directly but rather run on changes to roles in the
       zuul-jobs repo.
     abstract: true
-    tags: ubuntu-platforms
+    tags: debuntu-platforms
     files:
       - roles/ensure-skopeo/.*
       - roles/ensure-package-repositories/.*
       - test-playbooks/ensure-skopeo/.*
     run: test-playbooks/ensure-skopeo/main.yaml
 
+- job:
+    name: zuul-jobs-test-ensure-skopeo-debian-bookworm
+    description: Test the ensure-skopeo role on debian-bookworm
+    parent: zuul-jobs-test-ensure-skopeo
+    tags: auto-generated
+    nodeset:
+      nodes:
+        - name: debian-bookworm
+          label: debian-bookworm
+
+- job:
+    name: zuul-jobs-test-ensure-skopeo-debian-bullseye
+    description: Test the ensure-skopeo role on debian-bullseye
+    parent: zuul-jobs-test-ensure-skopeo
+    tags: auto-generated
+    nodeset:
+      nodes:
+        - name: debian-bullseye
+          label: debian-bullseye
+
 - job:
     name: zuul-jobs-test-ensure-skopeo-ubuntu-bionic
     description: Test the ensure-skopeo role on ubuntu-bionic
@@ -499,8 +591,12 @@
         - zuul-jobs-test-registry-docker
         - zuul-jobs-test-registry-docker-multiarch
         - zuul-jobs-test-registry-podman
+        - zuul-jobs-test-registry-buildset-registry
+        - zuul-jobs-test-registry-buildset-registry-k8s-microk8s
         - zuul-jobs-test-ensure-kubernetes-microk8s-ubuntu-jammy
         - zuul-jobs-test-ensure-kubernetes-microk8s-debian-bookworm
+        - zuul-jobs-test-ensure-skopeo-debian-bookworm
+        - zuul-jobs-test-ensure-skopeo-debian-bullseye
         - zuul-jobs-test-ensure-skopeo-ubuntu-bionic
         - zuul-jobs-test-ensure-skopeo-ubuntu-focal
         - zuul-jobs-test-ensure-skopeo-ubuntu-jammy