diff --git a/playbooks/roles/update_ssh_config/tasks/main.yml b/playbooks/roles/update_ssh_config/tasks/main.yml
new file mode 100644
index 000000000000..583d006c85c3
--- /dev/null
+++ b/playbooks/roles/update_ssh_config/tasks/main.yml
@@ -0,0 +1,106 @@
+---
+- name: Set the pathname of the controller's .ssh directory
+  ansible.builtin.set_fact:
+    sshdir: "{{ lookup('ansible.builtin.env', 'HOME') }}/.ssh"
+  tags:
+    - vars
+
+- name: Check that the user's ssh config file exists
+  delegate_to: localhost
+  run_once: true
+  ansible.builtin.stat:
+    path: "{{ sshdir }}/config"
+  register: ssh_config
+  tags:
+    - deps
+
+- name: Check that the kdevops Include directive is present
+  delegate_to: localhost
+  run_once: true
+  ansible.builtin.lineinfile:
+    path: "{{ sshdir }}/config"
+    regexp: "Include ~/.ssh/config_kdevops_*"
+    state: absent
+  check_mode: true
+  changed_when: false
+  register: kdevops_ssh_include
+  when:
+    - ssh_config.stat.exists
+  tags:
+    - deps
+
+- name: Check that the Include directive has a kdevops_version comment
+  delegate_to: localhost
+  run_once: true
+  ansible.builtin.lineinfile:
+    path: "{{ sshdir }}/config"
+    regexp: "^#(.*)kdevops_version(.*)"
+    state: absent
+  check_mode: true
+  changed_when: false
+  register: fixed_ssh_entry
+  when:
+    - ssh_config.stat.exists
+  tags:
+    - deps
+
+- name: Check if the correct Include directive is present
+  ansible.builtin.meta: end_play
+  when:
+    - ssh_config.stat.exists
+    - kdevops_ssh_include.found
+    - fixed_ssh_entry.found
+  tags:
+    - deps
+
+- name: Remove the stale Include directive
+  delegate_to: localhost
+  run_once: true
+  ansible.builtin.lineinfile:
+    path: "{{ sshdir }}/config"
+    line: "Include ~/.ssh/config_kdevops_*"
+    state: absent
+  when:
+    - ssh_config.stat.exists
+  tags:
+    - deps
+
+- name: Remove stale kdevops comments
+  delegate_to: localhost
+  run_once: true
+  ansible.builtin.lineinfile:
+    path: "{{ sshdir }}/config"
+    regexp: "^#(.*)kdevops(.*)"
+    state: absent
+  when:
+    - ssh_config.stat.exists
+  tags:
+    - deps
+
+- name: Remove extraneous new lines
+  delegate_to: localhost
+  run_once: true
+  ansible.builtin.replace:
+    path: "{{ sshdir }}/config"
+    regexp: '(^\s*$)'
+    replace: ''
+  when:
+    - ssh_config.stat.exists
+  tags:
+    - deps
+
+- name: Add a proper Include directive to ~/.ssh/config
+  delegate_to: localhost
+  run_once: true
+  ansible.builtin.blockinfile:
+    path: "{{ sshdir }}/config"
+    insertbefore: BOF
+    marker: "{mark}"
+    marker_begin: "# Automatically added by kdevops\n# kdevops_version: {{ kdevops_version }}"
+    marker_end: ""
+    create: true
+    mode: "u=rw,g=r,o=r"
+    block: |
+      Include ~/.ssh/config_kdevops_*
+  tags:
+    - deps
diff --git a/playbooks/roles/update_ssh_config_guestfs/tasks/main.yml b/playbooks/roles/update_ssh_config_guestfs/tasks/main.yml
deleted file mode 100644
index 98c86f164612..000000000000
--- a/playbooks/roles/update_ssh_config_guestfs/tasks/main.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-- name: Check if the ssh config file exists
-  stat:
-    path: "~/.ssh/config"
-  register: ssh_config
-
-# Check if the include directive is already presetn
-- name: Check if the kdevops include directive was used
-  lineinfile:
-    path: ~/.ssh/config
-    regexp: "Include ~/.ssh/config_kdevops_*"
-    state: absent
-  check_mode: yes
-  changed_when: false
-  register: kdevops_ssh_include
-  when: ssh_config.stat.exists
-
-# Check if the the kdevops_version was added in a comment
-- name: Check if the new include directive was used with a kdevops_version comment
-  lineinfile:
-    path: ~/.ssh/config
-    regexp: "^#(.*)kdevops_version(.*)"
-    state: absent
-  check_mode: yes
-  changed_when: false
-  register: fixed_ssh_entry
-  when: ssh_config.stat.exists
-
-# If both the include directive was found and kdevops version comment was found
-# we bail right away to avoid updating the ssh config file always.
-- name: Check if the new fixed include directive was used
-  meta: end_play
-  when:
-    - ssh_config.stat.exists
-    - kdevops_ssh_include.found
-    - fixed_ssh_entry.found
-
-# If we're still running it means the correct include directive following a new
-# line was not found. So remove old stale include directives which may be
-# buggy.
-- name: Remove buggy stale include directive to ~/.ssh/config without a new line
-  lineinfile:
-    path: ~/.ssh/config
-    line: "Include ~/.ssh/config_kdevops_*"
-    state: absent
-  when: ssh_config.stat.exists
-
-- name: Remove any stale kdevops comments
-  lineinfile:
-    path: ~/.ssh/config
-    regexp: "^#(.*)kdevops(.*)"
-    state: absent
-  when: ssh_config.stat.exists
-
-- name: Remove any extra new lines
-  replace:
-    path: ~/.ssh/config
-    regexp: '(^\s*$)'
-    replace: ''
-  when: ssh_config.stat.exists
-
-# ssh include directives must follow a new line.
-- name: Add Include directive to ~/.ssh/config
-  blockinfile:
-    path: ~/.ssh/config
-    insertbefore: BOF
-    marker: "{mark}"
-    marker_begin: "# Automatically added by kdevops\n# kdevops_version: {{ kdevops_version }}"
-    marker_end: ""
-    create: true
-    block: |
-      Include ~/.ssh/config_kdevops_*
diff --git a/playbooks/update_ssh_config.yml b/playbooks/update_ssh_config.yml
new file mode 100644
index 000000000000..e2603df526d4
--- /dev/null
+++ b/playbooks/update_ssh_config.yml
@@ -0,0 +1,5 @@
+---
+- hosts: all
+  gather_facts: false
+  roles:
+    - role: update_ssh_config
diff --git a/playbooks/update_ssh_config_guestfs.yml b/playbooks/update_ssh_config_guestfs.yml
deleted file mode 100644
index 346b90245637..000000000000
--- a/playbooks/update_ssh_config_guestfs.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-- hosts: localhost
-  roles:
-    - role: update_ssh_config_guestfs
diff --git a/scripts/guestfs.Makefile b/scripts/guestfs.Makefile
index 03909641aac4..8d3f01c35758 100644
--- a/scripts/guestfs.Makefile
+++ b/scripts/guestfs.Makefile
@@ -62,11 +62,6 @@ libvirt_pcie_passthrough_permissions:
 
 $(KDEVOPS_PROVISIONED_SSH):
 	$(Q)if [[ "$(CONFIG_KDEVOPS_SSH_CONFIG_UPDATE)" == "y" ]]; then \
-		ansible-playbook $(ANSIBLE_VERBOSE) --connection=local \
-			--inventory localhost, \
-			playbooks/update_ssh_config_guestfs.yml \
-			--extra-vars=@./extra_vars.yaml \
-			-e 'ansible_python_interpreter=/usr/bin/python3' ;\
 		LIBVIRT_DEFAULT_URI=$(CONFIG_LIBVIRT_URI) $(TOPDIR)/scripts/update_ssh_config_guestfs.py; \
 	fi
 	$(Q)ansible $(ANSIBLE_VERBOSE) -i hosts all -e 'ansible_python_interpreter=/usr/bin/python3' -m wait_for_connection
diff --git a/scripts/ssh.Makefile b/scripts/ssh.Makefile
index 3ee9437b1b4c..aee58e4bcef3 100644
--- a/scripts/ssh.Makefile
+++ b/scripts/ssh.Makefile
@@ -21,3 +21,16 @@ $(KDEVOPS_SSH_PRIVKEY): .config
 	$(NQ) Generating new private key: $(KDEVOPS_SSH_PRIVKEY)
 	$(NQ) Generating new public key: $(KDEVOPS_SSH_PUBKEY)
 	$(Q)$(TOPDIR)/scripts/gen_ssh_key.sh
+
+PHONY += update-ssh-config
+update-ssh-config:
+	$(Q)ansible-playbook $(ANSIBLE_VERBOSE) --connection=local \
+		--inventory localhost, \
+		playbooks/update_ssh_config.yml \
+		--extra-vars=@./extra_vars.yaml \
+		-e 'ansible_python_interpreter=/usr/bin/python3' \
+		--tags vars,deps
+
+ifeq (y,$(CONFIG_KDEVOPS_SSH_CONFIG_UPDATE))
+LOCALHOST_SETUP_WORK += update-ssh-config
+endif
