diff --git a/kayobe/ansible.py b/kayobe/ansible.py
index 9dc7cb4db8887a581f2dca0f64382e5395a74983..c1c26385817b4ed4a8a0aaf412e07b29f1a9c1cf 100644
--- a/kayobe/ansible.py
+++ b/kayobe/ansible.py
@@ -21,7 +21,6 @@ import subprocess
 import sys
 import tempfile
 
-import ansible.constants
 from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
 
 from kayobe import exception
@@ -220,7 +219,7 @@ def build_args(parsed_args, playbooks,
     return cmd
 
 
-def _get_environment(parsed_args):
+def _get_environment(parsed_args, external_playbook=False):
     """Return an environment dict for executing an Ansible playbook."""
     env = os.environ.copy()
     vault.update_environment(parsed_args, env)
@@ -240,34 +239,69 @@ def _get_environment(parsed_args):
     # Update various role, collection and plugin paths to include the Kayobe
     # roles, collections and plugins. This allows custom playbooks to use these
     # resources.
-    roles_paths = [
-        os.path.join(parsed_args.config_path, "ansible", "roles"),
-        utils.get_data_files_path("ansible", "roles"),
-    ] + ansible.constants.DEFAULT_ROLES_PATH
+    if external_playbook:
+        roles_paths = [
+            os.path.join(parsed_args.config_path, "ansible", "roles"),
+            utils.get_data_files_path("ansible", "roles"),
+        ]
+    else:
+        roles_paths = [
+            utils.get_data_files_path("ansible", "roles"),
+            os.path.join(parsed_args.config_path, "ansible", "roles"),
+        ]
+
     env.setdefault("ANSIBLE_ROLES_PATH", ":".join(roles_paths))
 
-    collections_paths = [
-        os.path.join(parsed_args.config_path, "ansible", "collections"),
-        utils.get_data_files_path("ansible", "collections"),
-    ] + ansible.constants.COLLECTIONS_PATHS
+    if external_playbook:
+        collections_paths = [
+            os.path.join(parsed_args.config_path, "ansible", "collections"),
+            utils.get_data_files_path("ansible", "collections"),
+        ]
+    else:
+        collections_paths = [
+            utils.get_data_files_path("ansible", "collections"),
+            os.path.join(parsed_args.config_path, "ansible", "collections"),
+        ]
+
     env.setdefault("ANSIBLE_COLLECTIONS_PATH", ":".join(collections_paths))
 
-    action_plugins = [
-        os.path.join(parsed_args.config_path, "ansible", "action_plugins"),
-        utils.get_data_files_path("ansible", "action_plugins"),
-    ] + ansible.constants.DEFAULT_ACTION_PLUGIN_PATH
+    if external_playbook:
+        action_plugins = [
+            os.path.join(parsed_args.config_path, "ansible", "action_plugins"),
+            utils.get_data_files_path("ansible", "action_plugins"),
+        ]
+    else:
+        action_plugins = [
+            utils.get_data_files_path("ansible", "action_plugins"),
+            os.path.join(parsed_args.config_path, "ansible", "action_plugins"),
+        ]
+
     env.setdefault("ANSIBLE_ACTION_PLUGINS", ":".join(action_plugins))
 
-    filter_plugins = [
-        os.path.join(parsed_args.config_path, "ansible", "filter_plugins"),
-        utils.get_data_files_path("ansible", "filter_plugins"),
-    ] + ansible.constants.DEFAULT_FILTER_PLUGIN_PATH
+    if external_playbook:
+        filter_plugins = [
+            os.path.join(parsed_args.config_path, "ansible", "filter_plugins"),
+            utils.get_data_files_path("ansible", "filter_plugins"),
+        ]
+    else:
+        filter_plugins = [
+            utils.get_data_files_path("ansible", "filter_plugins"),
+            os.path.join(parsed_args.config_path, "ansible", "filter_plugins"),
+        ]
+
     env.setdefault("ANSIBLE_FILTER_PLUGINS", ":".join(filter_plugins))
 
-    test_plugins = [
-        os.path.join(parsed_args.config_path, "ansible", "test_plugins"),
-        utils.get_data_files_path("ansible", "test_plugins"),
-    ] + ansible.constants.DEFAULT_TEST_PLUGIN_PATH
+    if external_playbook:
+        test_plugins = [
+            os.path.join(parsed_args.config_path, "ansible", "test_plugins"),
+            utils.get_data_files_path("ansible", "test_plugins"),
+        ]
+    else:
+        test_plugins = [
+            utils.get_data_files_path("ansible", "test_plugins"),
+            os.path.join(parsed_args.config_path, "ansible", "test_plugins"),
+        ]
+
     env.setdefault("ANSIBLE_TEST_PLUGINS", ":".join(test_plugins))
 
     return env
@@ -284,7 +318,12 @@ def run_playbooks(parsed_args, playbooks,
                      verbose_level=verbose_level, check=check,
                      ignore_limit=ignore_limit, list_tasks=list_tasks,
                      diff=diff)
-    env = _get_environment(parsed_args)
+    first_playbook = os.path.realpath(playbooks[0])
+    external_playbook = False
+    if not first_playbook.startswith(os.path.realpath(
+            utils.get_data_files_path("ansible"))):
+        external_playbook = True
+    env = _get_environment(parsed_args, external_playbook)
     try:
         utils.run_command(cmd, check_output=check_output, quiet=quiet, env=env)
     except subprocess.CalledProcessError as e:
diff --git a/kayobe/tests/unit/test_ansible.py b/kayobe/tests/unit/test_ansible.py
index 40b2437d8c42d05cd5abef287105fddc430d2a64..458373f9aae7a2dabc50167127d025a32177e270 100644
--- a/kayobe/tests/unit/test_ansible.py
+++ b/kayobe/tests/unit/test_ansible.py
@@ -54,39 +54,78 @@ class TestCase(unittest.TestCase):
             "playbook1.yml",
             "playbook2.yml",
         ]
-        home = os.path.expanduser("~")
+
         expected_env = {
             "KAYOBE_CONFIG_PATH": "/etc/kayobe",
             "ANSIBLE_ROLES_PATH": ":".join([
                 "/etc/kayobe/ansible/roles",
                 utils.get_data_files_path("ansible", "roles"),
-                home + "/.ansible/roles",
-                "/usr/share/ansible/roles",
-                "/etc/ansible/roles",
             ]),
             "ANSIBLE_COLLECTIONS_PATH": ":".join([
                 "/etc/kayobe/ansible/collections",
                 utils.get_data_files_path("ansible", "collections"),
-                home + "/.ansible/collections",
-                "/usr/share/ansible/collections",
             ]),
             "ANSIBLE_ACTION_PLUGINS": ":".join([
                 "/etc/kayobe/ansible/action_plugins",
                 utils.get_data_files_path("ansible", "action_plugins"),
-                home + "/.ansible/plugins/action",
-                "/usr/share/ansible/plugins/action",
             ]),
             "ANSIBLE_FILTER_PLUGINS": ":".join([
                 "/etc/kayobe/ansible/filter_plugins",
                 utils.get_data_files_path("ansible", "filter_plugins"),
-                home + "/.ansible/plugins/filter",
-                "/usr/share/ansible/plugins/filter",
             ]),
             "ANSIBLE_TEST_PLUGINS": ":".join([
                 "/etc/kayobe/ansible/test_plugins",
                 utils.get_data_files_path("ansible", "test_plugins"),
-                home + "/.ansible/plugins/test",
-                "/usr/share/ansible/plugins/test",
+            ]),
+        }
+        mock_run.assert_called_once_with(expected_cmd, check_output=False,
+                                         quiet=False, env=expected_env)
+        mock_vars.assert_called_once_with(["/etc/kayobe"])
+
+    @mock.patch.object(utils, "run_command")
+    @mock.patch.object(ansible, "_get_vars_files")
+    @mock.patch.object(ansible, "_validate_args")
+    def test_run_playbooks_internal(self, mock_validate, mock_vars, mock_run):
+        mock_vars.return_value = ["/etc/kayobe/vars-file1.yml",
+                                  "/etc/kayobe/vars-file2.yaml"]
+        parser = argparse.ArgumentParser()
+        ansible.add_args(parser)
+        vault.add_args(parser)
+        parsed_args = parser.parse_args([])
+        pb1 = utils.get_data_files_path("ansible", "playbook1.yml")
+        pb2 = utils.get_data_files_path("ansible", "playbook2.yml")
+        ansible.run_playbooks(parsed_args, [pb1, pb2])
+        expected_cmd = [
+            "ansible-playbook",
+            "--inventory", utils.get_data_files_path("ansible", "inventory"),
+            "--inventory", "/etc/kayobe/inventory",
+            "-e", "@/etc/kayobe/vars-file1.yml",
+            "-e", "@/etc/kayobe/vars-file2.yaml",
+            f"{pb1}",
+            f"{pb2}",
+        ]
+
+        expected_env = {
+            "KAYOBE_CONFIG_PATH": "/etc/kayobe",
+            "ANSIBLE_ROLES_PATH": ":".join([
+                utils.get_data_files_path("ansible", "roles"),
+                "/etc/kayobe/ansible/roles",
+            ]),
+            "ANSIBLE_COLLECTIONS_PATH": ":".join([
+                utils.get_data_files_path("ansible", "collections"),
+                "/etc/kayobe/ansible/collections",
+            ]),
+            "ANSIBLE_ACTION_PLUGINS": ":".join([
+                utils.get_data_files_path("ansible", "action_plugins"),
+                "/etc/kayobe/ansible/action_plugins",
+            ]),
+            "ANSIBLE_FILTER_PLUGINS": ":".join([
+                utils.get_data_files_path("ansible", "filter_plugins"),
+                "/etc/kayobe/ansible/filter_plugins",
+            ]),
+            "ANSIBLE_TEST_PLUGINS": ":".join([
+                utils.get_data_files_path("ansible", "test_plugins"),
+                "/etc/kayobe/ansible/test_plugins",
             ]),
         }
         mock_run.assert_called_once_with(expected_cmd, check_output=False,
@@ -182,40 +221,29 @@ class TestCase(unittest.TestCase):
             "playbook1.yml",
             "playbook2.yml",
         ]
-        home = os.path.expanduser("~")
+
         expected_env = {
             "KAYOBE_CONFIG_PATH": "/path/to/config",
             "KAYOBE_ENVIRONMENT": "test-env",
             "ANSIBLE_ROLES_PATH": ":".join([
                 "/path/to/config/ansible/roles",
                 utils.get_data_files_path("ansible", "roles"),
-                home + "/.ansible/roles",
-                "/usr/share/ansible/roles",
-                "/etc/ansible/roles",
             ]),
             "ANSIBLE_COLLECTIONS_PATH": ":".join([
                 "/path/to/config/ansible/collections",
                 utils.get_data_files_path("ansible", "collections"),
-                home + "/.ansible/collections",
-                "/usr/share/ansible/collections",
             ]),
             "ANSIBLE_ACTION_PLUGINS": ":".join([
                 "/path/to/config/ansible/action_plugins",
                 utils.get_data_files_path("ansible", "action_plugins"),
-                home + "/.ansible/plugins/action",
-                "/usr/share/ansible/plugins/action",
             ]),
             "ANSIBLE_FILTER_PLUGINS": ":".join([
                 "/path/to/config/ansible/filter_plugins",
                 utils.get_data_files_path("ansible", "filter_plugins"),
-                home + "/.ansible/plugins/filter",
-                "/usr/share/ansible/plugins/filter",
             ]),
             "ANSIBLE_TEST_PLUGINS": ":".join([
                 "/path/to/config/ansible/test_plugins",
                 utils.get_data_files_path("ansible", "test_plugins"),
-                home + "/.ansible/plugins/test",
-                "/usr/share/ansible/plugins/test",
             ]),
         }
         mock_run.assert_called_once_with(expected_cmd, check_output=False,
diff --git a/releasenotes/notes/improve-namespacing-for-internal-playbooks-baed54403608c3e7.yaml b/releasenotes/notes/improve-namespacing-for-internal-playbooks-baed54403608c3e7.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e74b2b3d357dc0f62538b2562b801811f499175d
--- /dev/null
+++ b/releasenotes/notes/improve-namespacing-for-internal-playbooks-baed54403608c3e7.yaml
@@ -0,0 +1,22 @@
+---
+fixes:
+  - |
+    The Ansible search paths, when running Kayobe internal playbooks, have been
+    modified so that collections, roles and plugins internal to the Kayobe
+    installation have precedence over those installed in Kayobe configuration.
+    This improves the usability as it is now possible to install a newer
+    version of an extension without affecting internal Kayobe playbooks.
+    `LP#2056473 <https://launchpad.net/bugs/2056473>`__
+upgrade:
+  - |
+    Ansible plugins, roles, and collections (collectively known as extensions)
+    installed in Kayobe configuration no longer have precedence over internal
+    Kayobe variants of the same extension. You can revert back to the previous
+    behaviour by manually exporting the relevant Ansible variables, e.g
+    ``ANSIBLE_COLLECTIONS_PATH``. It is not anticipated that this will affect
+    many users as it is still possible to supplement Kayobe with additional
+    plugins.
+  - |
+    System folders and home directories are no longer searched when looking for
+    Ansible extensions. It is recommended to install your collections using
+    ``$KAYOBE_CONFIG_PATH/ansible/requirements.yml``.