diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b8f7f493b61728676cf5c600e81e9e76fbd1bfe8..22bec6b1ab9722391cf82c04802308d2373ff45a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -8,6 +8,7 @@ stages:
   - deploy-special
 
 variables:
+  KUBESPRAY_VERSION: v2.12.5
   FAILFASTCI_NAMESPACE: 'kargo-ci'
   GITLAB_REPOSITORY: 'kargo-ci/kubernetes-sigs-kubespray'
   ANSIBLE_FORCE_COLOR: "true"
@@ -38,8 +39,6 @@ before_script:
 .job: &job
   tags:
     - packet
-  variables:
-    KUBESPRAY_VERSION: v2.12.5
   image: quay.io/kubespray/kubespray:$KUBESPRAY_VERSION
   artifacts:
     paths:
diff --git a/.gitlab-ci/vagrant.yml b/.gitlab-ci/vagrant.yml
index 0d92e19d56b492f7892d33cabeb1283f6b7f3abe..7d8c15b260a634578d1ffb97500bf69565e875d4 100644
--- a/.gitlab-ci/vagrant.yml
+++ b/.gitlab-ci/vagrant.yml
@@ -4,7 +4,7 @@ molecule_tests:
   tags: [vagrant]
   only: [/^pr-.*$/]
   except: ['triggers']
-  image: quay.io/miouge/kubespray-vagrant
+  image: quay.io/kubespray/vagrant:$KUBESPRAY_VERSION
   services: []
   stage: deploy-part1
   before_script:
@@ -24,7 +24,7 @@ molecule_tests:
   tags: [vagrant]
   only: [/^pr-.*$/]
   except: ['triggers']
-  image: quay.io/miouge/kubespray-vagrant
+  image: quay.io/kubespray/vagrant:$KUBESPRAY_VERSION
   services: []
   script:
     - vagrant up
diff --git a/RELEASE.md b/RELEASE.md
index e99e6f87efef86792f98d78c7fad121dd1fa7d44..d5322a6e56ac42fcc7c1c3dd9765c83db7d9cbdc 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -8,7 +8,7 @@ The Kubespray Project is released on an as-needed basis. The process is as follo
 4. Remove hashes for [EOL versions](https://github.com/kubernetes/sig-release/blob/master/releases/patch-releases.md) of kubernetes from `*_checksums` variables.
 5. An approver creates [new release in GitHub](https://github.com/kubernetes-sigs/kubespray/releases/new) using a version and tag name like `vX.Y.Z` and attaching the release notes
 6. An approver creates a release branch in the form `release-X.Y`
-7. The corresponding version of [quay.io/kubespray/kubespray:vX.Y.Z](https://quay.io/repository/kubespray/kubespray) docker image is built and tagged
+7. The corresponding version of [quay.io/kubespray/kubespray:vX.Y.Z](https://quay.io/repository/kubespray/kubespray) and [quay.io/kubespray/vagrant:vX.Y.Z](https://quay.io/repository/kubespray/vagrant) docker images are built and tagged
 8. The `KUBESPRAY_VERSION` variable is updated in `.gitlab-ci.yml`
 9. The release issue is closed
 10. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] Kubespray $VERSION is released`
diff --git a/test-infra/vagrant-docker/Dockerfile b/test-infra/vagrant-docker/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..1f7927c0a7bdaa22245eca8f3504387029576f9d
--- /dev/null
+++ b/test-infra/vagrant-docker/Dockerfile
@@ -0,0 +1,14 @@
+# Docker image published at quay.io/kubespray/vagrant
+
+ARG KUBESPRAY_VERSION=v2.12.5
+FROM quay.io/kubespray/kubespray:${KUBESPRAY_VERSION}
+
+ENV VAGRANT_VERSION=2.2.7
+ENV VAGRANT_DEFAULT_PROVIDER=libvirt
+
+RUN apt-get update && apt-get install -y wget libvirt-dev openssh-client rsync git
+
+# Install Vagrant
+RUN wget https://releases.hashicorp.com/vagrant/${VAGRANT_VERSION}/vagrant_${VAGRANT_VERSION}_x86_64.deb
+RUN dpkg -i vagrant_${VAGRANT_VERSION}_x86_64.deb
+RUN vagrant plugin install vagrant-libvirt
diff --git a/test-infra/vagrant-docker/README.md b/test-infra/vagrant-docker/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..36dcb9e96229efbb4b4d8d849e637c57771e9d6b
--- /dev/null
+++ b/test-infra/vagrant-docker/README.md
@@ -0,0 +1,24 @@
+# vagrant docker image
+
+This image is used for the vagrant CI jobs. It is using the libvirt driver.
+
+## Usage
+
+```console
+$ docker run --net host --rm -it -v /var/run/libvirt/libvirt-sock:/var/run/libvirt/libvirt-sock quay.io/kubespray/vagrant
+$ vagrant up
+Bringing machine 'k8s-1' up with 'libvirt' provider...
+Bringing machine 'k8s-2' up with 'libvirt' provider...
+Bringing machine 'k8s-3' up with 'libvirt' provider...
+[...]
+```
+
+## Cache
+
+You can set `/root/kubespray_cache` as a volume to keep cache between runs.
+
+## Building
+
+```shell
+./build.sh v2.12.5
+```
diff --git a/test-infra/vagrant-docker/build.sh b/test-infra/vagrant-docker/build.sh
new file mode 100755
index 0000000000000000000000000000000000000000..dcf54456b91766ac2da9627403594c12b7f0486f
--- /dev/null
+++ b/test-infra/vagrant-docker/build.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+set -euo pipefail
+
+if [ "$#" -ne 1 ]; then
+  echo "Usage: $0 tag" >&2
+  exit 1
+fi
+
+VERSION="$1"
+IMG="quay.io/kubespray/vagrant:${VERSION}"
+
+docker build . --build-arg "KUBESPRAY_VERSION=${VERSION}" --tag "$IMG"
+docker push "$IMG"