One of the things that has been bugging me, and itch to be scratched if you will, is that I have been changing the inventory to set which host uses the local connection type. On my live network I have been running ansible-playbook on my laptop and in the lab environment on a “desktop” with different hardware and hostname. The lab host, specifically, has no ssh daemon running so does not work at all if the connection type is not local.

An alternative solution would be to have separate “live” and “lab” inventories, however I am reluctant to do this because I want to keep everything, including the Ansible configuration, as identical as possible for the lab to be kept representative of the live home network for testing.

I scratched this itch with a small play that uses the implicit localhost target to find the hostname of the current machine then sets the ansible_connection variable to local on that host. This presumes that the hostname reported by the machine is the same as that in the inventory. The host’s facts cannot be used to match the hostname as there is a catch-22 situation, in some case (e.g. the lab network), with not being able to connect to gather facts until the connection is correctly set.

The play looks like this:

- hosts: all:!dummy
  # Need correct ansible_connection value to gather facts, which is not
  # yet set for everything.
  gather_facts: no
  tasks:
    - block:
        - name: Find local hostname
          delegate_to: localhost
          ansible.builtin.command: /usr/bin/hostname
          register: local_hostname
          changed_when: false # A read-only command (in this form)
          check_mode: false # Always run as normal, even in check mode
        - name: Set connection to local for this machine
          # Magic to delegate to the inventory host that is the local
          # machine.
          delegate_to: "{{ local_hostname.stdout }}"
          # Magic to set this fact on the delegated host - which is the
          # local one.
          delegate_facts: yes
          ansible.builtin.set_fact:
            ansible_connection: local
      run_once: yes
      tags: ['always'] # Always want to correctly set the connection

One of the neat things is that this works, without connecting to the host, even if it has not been targetted by the current run of ansible-playbook (it even works, in my testing, if the host does not exist at all in the inventory) so it is a “set it up and forget it” snippet.