diff --git a/ansible/group_vars/all/apt b/ansible/group_vars/all/apt
index 46d26de1854ce74444f57029a0b2716727ea67c4..904e05176e5fd42589b87c8e3be71a044cbb4d65 100644
--- a/ansible/group_vars/all/apt
+++ b/ansible/group_vars/all/apt
@@ -30,7 +30,7 @@ apt_keys: []
 # * types: whitespace-separated list of repository types, e.g. deb or deb-src
 #   (optional, default is 'deb')
 # * url: URL of the repository
-# * suites: whitespace-separated list of suites, e.g. focal (optional, default
+# * suites: whitespace-separated list of suites, e.g. jammy (optional, default
 #   is ansible_facts.distribution_release)
 # * components: whitespace-separated list of components, e.g. main (optional,
 #   default is 'main')
diff --git a/ansible/group_vars/all/globals b/ansible/group_vars/all/globals
index f84c60c34c7dd29024607471d8a0a57d031656ce..f3d4cdd3f2f0f7850422c7c1aef8f02bcd3a2c25 100644
--- a/ansible/group_vars/all/globals
+++ b/ansible/group_vars/all/globals
@@ -49,12 +49,12 @@ kayobe_ansible_user: "stack"
 os_distribution: "centos"
 
 # OS release. Valid options are "8-stream" when os_distribution is "centos", or
-# "8" when os_distribution is "rocky", or "focal" when os_distribution is
+# "8" when os_distribution is "rocky", or "jammy" when os_distribution is
 # "ubuntu".
 os_release: >-
   {{ '8-stream' if os_distribution == 'centos'
   else '8' if os_distribution == 'rocky'
-  else 'focal' }}
+  else 'jammy' }}
 
 ###############################################################################
 # Ansible configuration.
diff --git a/ansible/group_vars/all/infra-vms b/ansible/group_vars/all/infra-vms
index 859eb046eb1a1b2a3660d2973ba77a2b360243ff..beacc89d46bcfa60eaa167dcea1c85d439cc4da1 100644
--- a/ansible/group_vars/all/infra-vms
+++ b/ansible/group_vars/all/infra-vms
@@ -41,7 +41,7 @@ infra_vm_root_capacity: 50G
 infra_vm_root_format: qcow2
 
 # Base image for the infra VM root volume. Default is
-# "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img"
+# "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
 # when os_distribution is "ubuntu", or
 # http://dl.rockylinux.org/pub/rocky/8.5/images/Rocky-8-GenericCloud-8.5-20211114.2.x86_64.qcow2
 # when os_distribution is "rocky",
@@ -50,7 +50,7 @@ infra_vm_root_format: qcow2
 # otherwise.
 infra_vm_root_image: >-
   {%- if os_distribution == 'ubuntu' %}
-  https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img
+  https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
   {%- elif os_distribution == 'rocky' %}
   http://dl.rockylinux.org/pub/rocky/8.5/images/Rocky-8-GenericCloud-8.5-20211114.2.x86_64.qcow2
   {%- else -%}
diff --git a/ansible/group_vars/all/seed-vm b/ansible/group_vars/all/seed-vm
index fb86584053969eb1ec46b23db66b1bdbf2f6e99a..678285cdee03a1433f271973398fee73f1a86c0d 100644
--- a/ansible/group_vars/all/seed-vm
+++ b/ansible/group_vars/all/seed-vm
@@ -41,7 +41,7 @@ seed_vm_root_capacity: 50G
 seed_vm_root_format: qcow2
 
 # Base image for the seed VM root volume. Default is
-# "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img"
+# "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
 # when os_distribution is "ubuntu",
 # http://dl.rockylinux.org/pub/rocky/8.5/images/Rocky-8-GenericCloud-8.5-20211114.2.x86_64.qcow2
 # when os_distribution is "rocky",
@@ -50,7 +50,7 @@ seed_vm_root_format: qcow2
 # otherwise.
 seed_vm_root_image: >-
   {%- if os_distribution == 'ubuntu' %}
-  https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img
+  https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
   {%- elif os_distribution == 'rocky' %}
   http://dl.rockylinux.org/pub/rocky/8.5/images/Rocky-8-GenericCloud-8.5-20211114.2.x86_64.qcow2
   {%- else -%}
diff --git a/ansible/roles/apt/defaults/main.yml b/ansible/roles/apt/defaults/main.yml
index f818381d7d37e30646fe284f127c274e59049296..39013cd67cb2946d54aed8a0d1bb1c2736dc5e57 100644
--- a/ansible/roles/apt/defaults/main.yml
+++ b/ansible/roles/apt/defaults/main.yml
@@ -33,7 +33,7 @@ apt_keys: []
 # * types: whitespace-separated list of repository types, e.g. deb or deb-src
 #   (optional, default is 'deb')
 # * url: URL of the repository
-# * suites: whitespace-separated list of suites, e.g. focal (optional, default
+# * suites: whitespace-separated list of suites, e.g. jammy (optional, default
 #   is ansible_facts.distribution_release)
 # * components: whitespace-separated list of components, e.g. main (optional,
 #   default is 'main')
diff --git a/ansible/roles/apt/tasks/repos.yml b/ansible/roles/apt/tasks/repos.yml
index 8f48f2b925997788f24f5ea96d44825ecc20d760..b63139e7fa0dcb5f31567402e4efd82978a091d5 100644
--- a/ansible/roles/apt/tasks/repos.yml
+++ b/ansible/roles/apt/tasks/repos.yml
@@ -1,4 +1,13 @@
 ---
+- name: Ensure the Apt sources.list.d directory exists
+  file:
+    path: "/etc/apt/sources.list.d"
+    state: directory
+    owner: root
+    group: root
+    mode: 0755
+  become: true
+
 # NOTE(mgoddard): Use the modern deb822 repository format rather than the old
 # format used by the apt_repository module.
 - name: Configure apt repositories
diff --git a/doc/source/configuration/reference/hosts.rst b/doc/source/configuration/reference/hosts.rst
index 4cb6e57a0ae91a171980f85630f21210690ae372..660141cb9dd0d0e8d10a3aa6dec3156a17a7376e 100644
--- a/doc/source/configuration/reference/hosts.rst
+++ b/doc/source/configuration/reference/hosts.rst
@@ -366,7 +366,7 @@ items:
 * ``types``: whitespace-separated list of repository types, e.g. ``deb`` or
   ``deb-src`` (optional, default is ``deb``)
 * ``url``: URL of the repository
-* ``suites``: whitespace-separated list of suites, e.g. ``focal`` (optional,
+* ``suites``: whitespace-separated list of suites, e.g. ``jammy`` (optional,
   default is ``ansible_facts.distribution_release``)
 * ``components``: whitespace-separated list of components, e.g. ``main``
   (optional, default is ``main``)
@@ -385,10 +385,10 @@ For example, the following configuration defines a single Apt repository:
    apt_repositories:
      - types: deb
        url: https://example.com/repo
-       suites: focal
+       suites: jammy
        components: all
 
-In the following example, the Ubuntu Focal 20.04 repositories are consumed from
+In the following example, the Ubuntu Jammy 22.04 repositories are consumed from
 a local package mirror. The ``apt_disable_sources_list`` variable is set to
 ``true``, which disables all repositories in ``/etc/apt/sources.list``,
 including the default Ubuntu ones.
@@ -398,10 +398,10 @@ including the default Ubuntu ones.
 
    apt_repositories:
      - url: http://mirror.example.com/ubuntu/
-       suites: focal focal-updates
+       suites: jammy jammy-updates
        components: main restricted universe multiverse
      - url: http://mirror.example.com/ubuntu/
-       suites: focal-security
+       suites: jammy-security
        components: main restricted universe multiverse
 
    apt_disable_sources_list: true
@@ -438,7 +438,7 @@ that is signed by the key.
    apt_repositories:
      - types: deb
        url: https://example.com/repo
-       suites: focal
+       suites: jammy
        components: all
        signed_by: example-key.asc
 
diff --git a/doc/source/configuration/reference/os-distribution.rst b/doc/source/configuration/reference/os-distribution.rst
index f73524f35c166f74dc3c55b78b5e98dba29901f8..a64fd23c234d2d43685f5d39b0531f24e575f430 100644
--- a/doc/source/configuration/reference/os-distribution.rst
+++ b/doc/source/configuration/reference/os-distribution.rst
@@ -16,7 +16,7 @@ or ``rocky`` or ``ubuntu``, and defaults to ``centos``.
 The ``os_release`` variable in ``etc/kayobe/globals.yml`` can be used to set
 the release of the OS. When ``os_distribution`` is set to ``centos`` it may be
 set to ``8-stream``, and this is its default value. When ``os_distribution`` is
-set to ``ubuntu`` it may be set to ``focal``, and this is its default value.
+set to ``ubuntu`` it may be set to ``jammy``, and this is its default value.
 When ``os_distribution`` is set to ``rocky`` it may be set to ``8``, and this
 is its default value.
 
diff --git a/doc/source/installation.rst b/doc/source/installation.rst
index acf86eace98a422365e418d6b11d75ccddb5f79c..0d0ebeea8a9ef72703e6b01540a5f822d2f2b288 100644
--- a/doc/source/installation.rst
+++ b/doc/source/installation.rst
@@ -17,7 +17,7 @@ control host:
 
 - CentOS Stream 8 (since Wallaby 10.0.0 release)
 - Rocky Linux 8 (since Yoga 12.0.0 release)
-- Ubuntu Focal 20.04 (since Wallaby 10.0.0 release)
+- Ubuntu Jammy 22.04 (since Zed 13.0.0 release)
 
 See the :doc:`support matrix <support-matrix>` for details of supported
 Operating Systems for other hosts.
diff --git a/doc/source/resources.rst b/doc/source/resources.rst
index c3011b740a18f32fd6385d5c464a895de3ff70be..bb41396ea36172d970a821a7323b4d135ad4a003 100644
--- a/doc/source/resources.rst
+++ b/doc/source/resources.rst
@@ -22,7 +22,7 @@ OpenStack using Kolla, Ansible and Kayobe. The guide makes use of
 baremetal environment running on a single hypervisor.
 
 To complete the walkthrough you will require a baremetal or VM hypervisor
-running CentOS 8 or Ubuntu Focal 20.04 (since Wallaby 10.0.0) with at least
+running CentOS 8 or Ubuntu Jammy 22.04 (since Zed 13.0.0) with at least
 32GB RAM & 80GB disk space.  Preparing the deployment can take some time -
 where possible it is beneficial to snapshot the hypervisor. We advise making a
 snapshot after creating the initial 'seed' VM as this will make additional
diff --git a/doc/source/support-matrix.rst b/doc/source/support-matrix.rst
index 3b18d665e78f9bd8145471118095a289a87a113a..35ec7765cab18a71fcc4f9b043bf7d8f514a18eb 100644
--- a/doc/source/support-matrix.rst
+++ b/doc/source/support-matrix.rst
@@ -11,7 +11,7 @@ Kayobe supports the following host Operating Systems (OS):
 
 * CentOS Stream 8 (since Wallaby 10.0.0 release)
 * Rocky Linux 8 (since Yoga 12.0.0 release)
-* Ubuntu Focal 20.04 (since Wallaby 10.0.0 release)
+* Ubuntu Jammy 22.04 (since Zed 13.0.0 release)
 
 .. note::
 
diff --git a/etc/kayobe/apt.yml b/etc/kayobe/apt.yml
index 34bfdd2efd52c03cbfc1696448ef11855284ef7b..9a9d8853862867bad88303499a3ece66a0f881c2 100644
--- a/etc/kayobe/apt.yml
+++ b/etc/kayobe/apt.yml
@@ -30,7 +30,7 @@
 # * types: whitespace-separated list of repository types, e.g. deb or deb-src
 #   (optional, default is 'deb')
 # * url: URL of the repository
-# * suites: whitespace-separated list of suites, e.g. focal (optional, default
+# * suites: whitespace-separated list of suites, e.g. jammy (optional, default
 #   is ansible_facts.distribution_release)
 # * components: whitespace-separated list of components, e.g. main (optional,
 #   default is 'main')
diff --git a/etc/kayobe/globals.yml b/etc/kayobe/globals.yml
index b926fc9be10b7ad8014fb58f813d1ce6199bf952..85f668d1da6e2b35fee555b2e3f4a97435244842 100644
--- a/etc/kayobe/globals.yml
+++ b/etc/kayobe/globals.yml
@@ -50,7 +50,7 @@
 #os_distribution:
 
 # OS release. Valid options are "8-stream" when os_distribution is "centos", or
-# "8" when os_distribution is "rocky", or "focal" when os_distribution is
+# "8" when os_distribution is "rocky", or "jammy" when os_distribution is
 # "ubuntu".
 #os_release:
 
diff --git a/etc/kayobe/infra-vms.yml b/etc/kayobe/infra-vms.yml
index 3274ed806051bd17af48ac67761c3876898f6fdb..1ec28d9de4c38ad80cb761bf24f1ef428e549b6d 100644
--- a/etc/kayobe/infra-vms.yml
+++ b/etc/kayobe/infra-vms.yml
@@ -30,7 +30,7 @@
 #infra_vm_root_format:
 
 # Base image for the infra VM root volume. Default is
-# "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img"
+# "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
 # when os_distribution is "ubuntu", or
 # http://dl.rockylinux.org/pub/rocky/8.5/images/Rocky-8-GenericCloud-8.5-20211114.2.x86_64.qcow2
 # when os_distribution is "rocky",
diff --git a/etc/kayobe/seed-vm.yml b/etc/kayobe/seed-vm.yml
index f8c2ab8a9c8d55749f7daae6383587b2dde485ea..4b82649745a757be98db5fb00deb134ad6d5ee04 100644
--- a/etc/kayobe/seed-vm.yml
+++ b/etc/kayobe/seed-vm.yml
@@ -24,7 +24,7 @@
 #seed_vm_root_format:
 
 # Base image for the seed VM root volume. Default is
-# "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img"
+# "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
 # when os_distribution is "ubuntu",
 # http://dl.rockylinux.org/pub/rocky/8.5/images/Rocky-8-GenericCloud-8.5-20211114.2.x86_64.qcow2
 # when os_distribution is "rocky",
diff --git a/playbooks/kayobe-overcloud-host-configure-base/overrides.yml.j2 b/playbooks/kayobe-overcloud-host-configure-base/overrides.yml.j2
index fed315141efcc1888d105fff0007ce9df3da3ff1..7e9265134b4c674f0f40d12be758f3cd53791a17 100644
--- a/playbooks/kayobe-overcloud-host-configure-base/overrides.yml.j2
+++ b/playbooks/kayobe-overcloud-host-configure-base/overrides.yml.j2
@@ -123,15 +123,15 @@ apt_keys:
   - url: https://packages.treasuredata.com/GPG-KEY-td-agent
     filename: td-agent.asc
 apt_repositories:
-  # Ubuntu focal repositories.
+  # Ubuntu jammy repositories.
   - url: "http://{{ zuul_site_mirror_fqdn }}/ubuntu/"
-    suites: focal focal-updates
+    suites: jammy jammy-updates
     components: main restricted universe multiverse
   - url: "http://{{ zuul_site_mirror_fqdn }}/ubuntu/"
-    suites: focal-security
+    suites: jammy-security
     components: main restricted universe multiverse
   # Treasuredata repository.
-  - url:  http://packages.treasuredata.com/4/ubuntu/focal/
+  - url:  http://packages.treasuredata.com/4/ubuntu/jammy/
     components: contrib
     signed_by: td-agent.asc
 apt_disable_sources_list: true
diff --git a/releasenotes/notes/ubuntu-jammy-515047cd1ae85151.yaml b/releasenotes/notes/ubuntu-jammy-515047cd1ae85151.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e937d6662c0ec3fa2112bb43ede803e01e62caa8
--- /dev/null
+++ b/releasenotes/notes/ubuntu-jammy-515047cd1ae85151.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    Adds support for Ubuntu Jammy Jellyfish (22.04) LTS as a host and
+    container Operating System for seed, seed hypervisor and overcloud hosts.
diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml
index 66042c067114a98056cc41328242c2bfb0a22f82..6d2c63ee8e34609e59b235a3cc8f8b5876694e37 100644
--- a/zuul.d/jobs.yaml
+++ b/zuul.d/jobs.yaml
@@ -124,9 +124,9 @@
     nodeset: kayobe-rocky8
 
 - job:
-    name: kayobe-overcloud-ubuntu-focal
+    name: kayobe-overcloud-ubuntu-jammy
     parent: kayobe-overcloud-base
-    nodeset: kayobe-ubuntu-focal
+    nodeset: kayobe-ubuntu-jammy
 
 - job:
     name: kayobe-overcloud-tls-base
@@ -186,9 +186,9 @@
     nodeset: kayobe-rocky8
 
 - job:
-    name: kayobe-seed-ubuntu-focal
+    name: kayobe-seed-ubuntu-jammy
     parent: kayobe-seed-base
-    nodeset: kayobe-ubuntu-focal
+    nodeset: kayobe-ubuntu-jammy
 
 - job:
     name: kayobe-seed-images-base
@@ -212,9 +212,9 @@
     nodeset: kayobe-rocky8
 
 - job:
-    name: kayobe-seed-images-ubuntu-focal
+    name: kayobe-seed-images-ubuntu-jammy
     parent: kayobe-seed-images-base
-    nodeset: kayobe-ubuntu-focal
+    nodeset: kayobe-ubuntu-jammy
 
 - job:
     name: kayobe-overcloud-host-configure-base
@@ -238,9 +238,9 @@
     nodeset: kayobe-rocky8
 
 - job:
-    name: kayobe-overcloud-host-configure-ubuntu-focal
+    name: kayobe-overcloud-host-configure-ubuntu-jammy
     parent: kayobe-overcloud-host-configure-base
-    nodeset: kayobe-ubuntu-focal
+    nodeset: kayobe-ubuntu-jammy
 
 - job:
     name: kayobe-seed-upgrade-base
@@ -287,9 +287,9 @@
     nodeset: kayobe-rocky8
 
 - job:
-    name: kayobe-seed-vm-ubuntu-focal
+    name: kayobe-seed-vm-ubuntu-jammy
     parent: kayobe-seed-vm-base
-    nodeset: kayobe-ubuntu-focal
+    nodeset: kayobe-ubuntu-jammy
 
 - job:
     name: kayobe-infra-vm-base
@@ -314,6 +314,6 @@
     nodeset: kayobe-rocky8
 
 - job:
-    name: kayobe-infra-vm-ubuntu-focal
+    name: kayobe-infra-vm-ubuntu-jammy
     parent: kayobe-infra-vm-base
-    nodeset: kayobe-ubuntu-focal
+    nodeset: kayobe-ubuntu-jammy
diff --git a/zuul.d/nodesets.yaml b/zuul.d/nodesets.yaml
index b20e1bdeaa4f78076913f8ca5e0a805e5ba9e30a..697c6c10d5b8bdb281e669480e541d80035afc4c 100644
--- a/zuul.d/nodesets.yaml
+++ b/zuul.d/nodesets.yaml
@@ -13,7 +13,7 @@
         label: rockylinux-8
 
 - nodeset:
-    name: kayobe-ubuntu-focal
+    name: kayobe-ubuntu-jammy
     nodes:
       - name: primary
-        label: ubuntu-focal
+        label: ubuntu-jammy
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 7975ef3ec75ff33b52bd27458b531a2cd0c27061..2b843ff9b92ef43ade5c29837edfe483a44e4d34 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -13,25 +13,25 @@
         - kayobe-tox-molecule
         - kayobe-overcloud-centos8s
         - kayobe-overcloud-rocky8
-        - kayobe-overcloud-ubuntu-focal
+        - kayobe-overcloud-ubuntu-jammy
         - kayobe-overcloud-tls-centos8s
         - kayobe-overcloud-host-configure-centos8s
         - kayobe-overcloud-host-configure-rocky8
-        - kayobe-overcloud-host-configure-ubuntu-focal
+        - kayobe-overcloud-host-configure-ubuntu-jammy
         - kayobe-overcloud-upgrade-centos8s
         - kayobe-overcloud-upgrade-ubuntu-focal
         - kayobe-seed-centos8s
         - kayobe-seed-rocky8
-        - kayobe-seed-ubuntu-focal
+        - kayobe-seed-ubuntu-jammy
         - kayobe-seed-images-centos8s
         - kayobe-seed-upgrade-centos8s
         - kayobe-seed-upgrade-ubuntu-focal
         - kayobe-seed-vm-centos8s
         - kayobe-seed-vm-rocky8
-        - kayobe-seed-vm-ubuntu-focal
+        - kayobe-seed-vm-ubuntu-jammy
         - kayobe-infra-vm-centos8s
         - kayobe-infra-vm-rocky8
-        - kayobe-infra-vm-ubuntu-focal
+        - kayobe-infra-vm-ubuntu-jammy
 
     gate:
       jobs:
@@ -40,26 +40,26 @@
         - kayobe-tox-molecule
         - kayobe-overcloud-centos8s
         - kayobe-overcloud-rocky8
-        - kayobe-overcloud-ubuntu-focal
+        - kayobe-overcloud-ubuntu-jammy
         - kayobe-overcloud-tls-centos8s
         - kayobe-overcloud-host-configure-centos8s
         - kayobe-overcloud-host-configure-rocky8
-        - kayobe-overcloud-host-configure-ubuntu-focal
+        - kayobe-overcloud-host-configure-ubuntu-jammy
         - kayobe-overcloud-upgrade-centos8s
         - kayobe-overcloud-upgrade-ubuntu-focal
         - kayobe-seed-centos8s
         - kayobe-seed-rocky8
-        - kayobe-seed-ubuntu-focal
+        - kayobe-seed-ubuntu-jammy
         - kayobe-seed-upgrade-centos8s
         - kayobe-seed-upgrade-ubuntu-focal
         - kayobe-seed-vm-centos8s
         - kayobe-seed-vm-rocky8
-        - kayobe-seed-vm-ubuntu-focal
+        - kayobe-seed-vm-ubuntu-jammy
         - kayobe-infra-vm-centos8s
         - kayobe-infra-vm-rocky8
-        - kayobe-infra-vm-ubuntu-focal
+        - kayobe-infra-vm-ubuntu-jammy
 
     experimental:
       jobs:
         - kayobe-seed-images-rocky8
-        - kayobe-seed-images-ubuntu-focal
+        - kayobe-seed-images-ubuntu-jammy