diff --git a/ansible/compute-node-discovery.yml b/ansible/compute-node-discovery.yml
index dbc0d9d66..ee10488c6 100644
--- a/ansible/compute-node-discovery.yml
+++ b/ansible/compute-node-discovery.yml
@@ -11,6 +11,8 @@
       package:
         name: ipmitool
         state: present
+        cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+        update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
       become: True
       run_once: True
       delegate_to: "{{ controller_host }}"
diff --git a/ansible/group_vars/all/apt b/ansible/group_vars/all/apt
new file mode 100644
index 000000000..93e472604
--- /dev/null
+++ b/ansible/group_vars/all/apt
@@ -0,0 +1,6 @@
+---
+###############################################################################
+# Apt package manager configuration.
+
+# Apt cache TTL in seconds. Default is 3600.
+apt_cache_valid_time: 3600
diff --git a/ansible/idrac-bootstrap.yml b/ansible/idrac-bootstrap.yml
index 5ff65f183..8c6b2eb89 100644
--- a/ansible/idrac-bootstrap.yml
+++ b/ansible/idrac-bootstrap.yml
@@ -46,6 +46,8 @@
           package:
             name: wget
             state: present
+            cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+            update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
 
         - name: Ensure Dell srvadmin repository is installed
           shell: "wget -q -O - http://linux.dell.com/repo/hardware/latest/bootstrap.cgi | bash"
diff --git a/ansible/kayobe-target-venv.yml b/ansible/kayobe-target-venv.yml
index 37cfa4469..b464495ca 100644
--- a/ansible/kayobe-target-venv.yml
+++ b/ansible/kayobe-target-venv.yml
@@ -26,6 +26,8 @@
           package:
             name: python3-virtualenv
             state: present
+            cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+            update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
           become: True
 
         - name: Ensure global virtualenv directory exists
diff --git a/ansible/kolla-target-venv.yml b/ansible/kolla-target-venv.yml
index 4fadaca82..8abb5d920 100644
--- a/ansible/kolla-target-venv.yml
+++ b/ansible/kolla-target-venv.yml
@@ -27,6 +27,8 @@
           package:
             name: python3-virtualenv
             state: present
+            cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+            update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
           become: True
 
         - name: Ensure kolla-ansible virtualenv has the latest version of pip installed
diff --git a/ansible/roles/bootstrap/tasks/main.yml b/ansible/roles/bootstrap/tasks/main.yml
index 0c6221ba2..9da0fd151 100644
--- a/ansible/roles/bootstrap/tasks/main.yml
+++ b/ansible/roles/bootstrap/tasks/main.yml
@@ -6,6 +6,8 @@
   package:
     name: "{{ bootstrap_package_dependencies }}"
     state: present
+    cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+    update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
   become: True
 
 - name: Check whether an SSH key exists
diff --git a/ansible/roles/dev-tools/tasks/main.yml b/ansible/roles/dev-tools/tasks/main.yml
index 51dc00688..e45b40318 100644
--- a/ansible/roles/dev-tools/tasks/main.yml
+++ b/ansible/roles/dev-tools/tasks/main.yml
@@ -3,4 +3,6 @@
   package:
     name: "{{ dev_tools_packages }}"
     state: present
+    cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+    update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
   become: True
diff --git a/ansible/roles/disable-selinux/tasks/main.yml b/ansible/roles/disable-selinux/tasks/main.yml
index ca82edab5..68bedae52 100644
--- a/ansible/roles/disable-selinux/tasks/main.yml
+++ b/ansible/roles/disable-selinux/tasks/main.yml
@@ -3,6 +3,8 @@
   package:
     name: python3-libselinux
     state: present
+    cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+    update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
   become: True
 
 - name: Check if SELinux configuration file exists
diff --git a/ansible/roles/kolla-ansible/tasks/install.yml b/ansible/roles/kolla-ansible/tasks/install.yml
index 41453dc63..a39de9b89 100644
--- a/ansible/roles/kolla-ansible/tasks/install.yml
+++ b/ansible/roles/kolla-ansible/tasks/install.yml
@@ -16,6 +16,8 @@
     # NOTE(mgoddard): select non-empty packages.
     name: "{{ kolla_ansible_package_dependencies | select | list }}"
     state: present
+    cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+    update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
   become: True
 
 - name: Ensure source code checkout parent directory exists
diff --git a/ansible/roles/kolla-ansible/tests/test-defaults.yml b/ansible/roles/kolla-ansible/tests/test-defaults.yml
index a5c921868..3cf9f6efe 100644
--- a/ansible/roles/kolla-ansible/tests/test-defaults.yml
+++ b/ansible/roles/kolla-ansible/tests/test-defaults.yml
@@ -38,6 +38,7 @@
             kolla_enable_tls_internal: False
             kolla_enable_grafana: False
             kolla_openstack_logging_debug: False
+            apt_cache_valid_time: 3600
 
         - name: Verify kolla-ansible installation
           shell: ". {{ temp_path }}/venv/bin/activate && kolla-ansible -h"
diff --git a/ansible/roles/kolla-ansible/tests/test-extras.yml b/ansible/roles/kolla-ansible/tests/test-extras.yml
index d311a52ee..cde4b9f85 100644
--- a/ansible/roles/kolla-ansible/tests/test-extras.yml
+++ b/ansible/roles/kolla-ansible/tests/test-extras.yml
@@ -188,6 +188,7 @@
               custom-password-1: "custom-password-1"
               custom-password-2: "custom-password-2"
             kolla_nova_compute_ironic_host: "controller1"
+            apt_cache_valid_time: 3600
 
         - name: Verify kolla-ansible installation
           shell: ". {{ temp_path }}/venv/bin/activate && kolla-ansible -h"
diff --git a/ansible/roles/kolla-ansible/tests/test-requirements.yml b/ansible/roles/kolla-ansible/tests/test-requirements.yml
index b49585ff6..c9f8fdb43 100644
--- a/ansible/roles/kolla-ansible/tests/test-requirements.yml
+++ b/ansible/roles/kolla-ansible/tests/test-requirements.yml
@@ -37,6 +37,7 @@
             kolla_enable_tls_internal: False
             kolla_enable_grafana: False
             kolla_openstack_logging_debug: False
+            apt_cache_valid_time: 3600
 
         - name: List Python packages installed in virtualenv
           command: "{{ temp_path }}/venv/bin/pip list"
diff --git a/ansible/roles/kolla/tasks/install.yml b/ansible/roles/kolla/tasks/install.yml
index e81850204..1700ff4e4 100644
--- a/ansible/roles/kolla/tasks/install.yml
+++ b/ansible/roles/kolla/tasks/install.yml
@@ -18,6 +18,8 @@
       - python3-pip
       - python3-virtualenv
     state: present
+    cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+    update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
   become: True
 
 - name: Ensure source code checkout path exists
diff --git a/ansible/roles/pip/tasks/pip_conf.yml b/ansible/roles/pip/tasks/pip_conf.yml
index 3fa3493d6..8b1301762 100644
--- a/ansible/roles/pip/tasks/pip_conf.yml
+++ b/ansible/roles/pip/tasks/pip_conf.yml
@@ -4,6 +4,8 @@
 - name: Ensure acl package is installed
   package:
     name: acl
+    cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+    update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
   become: true
 
 - name: Create local .pip directory
diff --git a/ansible/roles/snat/tasks/main.yml b/ansible/roles/snat/tasks/main.yml
index ef9849ac4..3d1796e51 100644
--- a/ansible/roles/snat/tasks/main.yml
+++ b/ansible/roles/snat/tasks/main.yml
@@ -2,6 +2,8 @@
 - name: Ensure iptables is installed
   package:
     name: iptables
+    cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+    update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
   become: true
 
 # iptables -t nat -A POSTROUTING -o {{ interface }} -j SNAT --to-source {{ source_ip }}
diff --git a/ansible/roles/swift-block-devices/tasks/main.yml b/ansible/roles/swift-block-devices/tasks/main.yml
index 0fd1a4f10..8d21074f2 100644
--- a/ansible/roles/swift-block-devices/tasks/main.yml
+++ b/ansible/roles/swift-block-devices/tasks/main.yml
@@ -15,6 +15,8 @@
       - parted
       - xfsprogs
     state: present
+    cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+    update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
   become: True
   when: swift_block_devices | length > 0
 
diff --git a/ansible/roles/swift-block-devices/tests/test-bootstrapped.yml b/ansible/roles/swift-block-devices/tests/test-bootstrapped.yml
index f6cf8d2c3..d333e77d7 100644
--- a/ansible/roles/swift-block-devices/tests/test-bootstrapped.yml
+++ b/ansible/roles/swift-block-devices/tests/test-bootstrapped.yml
@@ -34,8 +34,9 @@
           include_role:
             name:  ../../swift-block-devices
           vars:
-              swift_block_devices:
-                 - device: "{{ loopback.stdout }}"
+            swift_block_devices:
+              - device: "{{ loopback.stdout }}"
+            apt_cache_valid_time: 3600
 
         - name: Get name of fake partition
           parted:
diff --git a/ansible/roles/swift-block-devices/tests/test-invalid-format.yml b/ansible/roles/swift-block-devices/tests/test-invalid-format.yml
index 05261da31..66eea7521 100644
--- a/ansible/roles/swift-block-devices/tests/test-invalid-format.yml
+++ b/ansible/roles/swift-block-devices/tests/test-invalid-format.yml
@@ -9,8 +9,9 @@
           include_role:
             name:  ../../swift-block-devices
           vars:
-              swift_block_devices:
-                 - /dev/fake
+            swift_block_devices:
+              - /dev/fake
+            apt_cache_valid_time: 3600
 
       rescue:
         - name: Flag that the error was raised
diff --git a/ansible/roles/swift-block-devices/tests/test-mount.yml b/ansible/roles/swift-block-devices/tests/test-mount.yml
index 1f5f9b244..bbeab1640 100644
--- a/ansible/roles/swift-block-devices/tests/test-mount.yml
+++ b/ansible/roles/swift-block-devices/tests/test-mount.yml
@@ -26,8 +26,9 @@
           include_role:
             name:  ../../swift-block-devices
           vars:
-              swift_block_devices:
-                 - device: "{{ loopback.stdout }}"
+            swift_block_devices:
+              - device: "{{ loopback.stdout }}"
+            apt_cache_valid_time: 3600
 
         - name: Get name of fake partition
           parted:
diff --git a/ansible/roles/wipe-disks/tasks/main.yml b/ansible/roles/wipe-disks/tasks/main.yml
index 1b88e88cb..e1a26ef5b 100644
--- a/ansible/roles/wipe-disks/tasks/main.yml
+++ b/ansible/roles/wipe-disks/tasks/main.yml
@@ -10,6 +10,8 @@
   package:
     name: lvm2
     state: present
+    cache_valid_time: "{{ apt_cache_valid_time if ansible_os_family == 'Debian' else omit }}"
+    update_cache: "{{ True if ansible_os_family == 'Debian' else omit }}"
   become: True
 
 - name: Check for unmounted block devices
diff --git a/etc/kayobe/apt.yml b/etc/kayobe/apt.yml
new file mode 100644
index 000000000..552a116cf
--- /dev/null
+++ b/etc/kayobe/apt.yml
@@ -0,0 +1,10 @@
+---
+###############################################################################
+# Apt package manager configuration.
+
+# Apt cache TTL in seconds. Default is 3600.
+#apt_cache_valid_time:
+
+###############################################################################
+# Dummy variable to allow Ansible to accept this file.
+workaround_ansible_issue_8743: yes