geerlingguy/ansible-for-devops

Chapter 2 - Ansible and Python mismatch

Opened this issue Β· 5 comments

I converted an old Macbook Pro to Linux Mint (Linux Mint 22.1
) and tried to follow the example in Chapter two of your book and ran into a nightmare. After a long chat with ChatGPT:

Here's a summary of our discussion and the key takeaways:


🧡 Problem Summary

You were trying to use Ansible with a Rocky Linux 8 Vagrant VM and ran into these issues:

  1. ❌ Ansible failed with:
    "MODULE FAILURE: No start of json char found"
    This occurred when using modules like dnf, indicating broken Python compatibility.

  2. ❌ Rocky Linux 8 default Python is 3.6 (platform-python), which:

    • Is too old for modern Ansible (v2.14+ requires Python β‰₯3.8)
    • Has system-specific behavior that can confuse Ansible
  3. ❌ You tried installing Ansible 2.12 (compatible with Python 3.6), but:

    • Your host system uses Python 3.12
    • Ansible 2.12 is incompatible with Python 3.12, resulting in _AnsiblePathHookFinder errors
  4. ❌ You tried installing Python 3.9 using apt, but Mint's base repos didn’t include it


βœ… Working Solution (Step-by-Step)

πŸ”§ 1. Install a compatible Python (3.9 or 3.10) on your host

Using the deadsnakes PPA, you can install Python 3.10 like so:

sudo apt install -y software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install -y python3.10 python3.10-venv

🐍 2. Create a virtual environment for Ansible 2.12

python3.10 -m venv ~/.venvs/ansible-2.12
source ~/.venvs/ansible-2.12/bin/activate
pip install ansible-core==2.12.3

πŸ“¦ 3. Run Ansible from that environment

This will allow Ansible to run against the Rocky Linux 8 VM using platform-python (3.6) without errors.

Use this in your Vagrantfile:

ansible.extra_vars = {
  ansible_python_interpreter: "/usr/libexec/platform-python"
}

And keep your Ansible version at 2.12.x, which supports Python 3.6.


βœ… Alternatives you considered:

  • Installing Python 3.9 in the Rocky guest β†’ failed due to missing dnf bindings
  • Using newer Ansible β†’ failed due to Python 3.6 on guest
  • Using raw commands instead of Ansible modules β†’ possible workaround

Here's the new working Vagrantfile that pairs perfectly with:

  • Ansible 2.12 (installed in a Python 3.10 virtual environment on your host)
  • Rocky Linux 8 guest
  • The system Python (platform-python, Python 3.6) on the guest VM β€” which is fully compatible with Ansible 2.12 for DNF, systemd, etc.

βœ… Final Working Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.box = "geerlingguy/rockylinux8"
  config.vm.hostname = "rockyvm"
  config.vm.network "private_network", type: "dhcp"

  # Optional: allocate more resources
  config.vm.provider "virtualbox" do |vb|
    vb.memory = 2048
    vb.cpus = 2
  end

  # βœ… Use the system Python that supports Ansible 2.12 modules (like dnf)
  config.vm.provision "ansible" do |ansible|
    ansible.compatibility_mode = "2.0"
    ansible.playbook = "playbook.yml"
    ansible.extra_vars = {
      ansible_python_interpreter: "/usr/libexec/platform-python"
    }
  end
end

βœ… Notes

  • This assumes you've activated your Python 3.10 virtual environment and installed Ansible 2.12:
source ~/.venvs/ansible-2.12/bin/activate
ansible --version  # should show 2.12.x
  • platform-python is Rocky 8's internal Python 3.6.8, which works only with Ansible 2.12 or earlier.

βœ… Matching playbook.yml Example

---
- hosts: all
  become: true
  gather_facts: true

  tasks:
    - name: Show which Python is being used
      raw: which python3
      register: python_path

    - name: Print Python path
      debug:
        var: python_path.stdout

    - name: Install chrony using dnf module
      dnf:
        name: chrony
        state: present

    - name: Ensure chronyd is running
      service:
        name: chronyd
        state: started
        enabled: yes

Thank you for this solution. its to bad this is an issue still. worked like a charm for me.

I typically ignore copy-paste dumps from AI, as it requires a massive amount of mental capacity (in comparison to a simple bug report with "here's the error message pasted, and here's what I did to fix it")β€”so this issue has kind of passed me by.

If someone can summarize what the actual issue is, that'd be quite helpful :)

Typically if you just start spoon feeding ChatGPT, it will lead you down some rabbit holes that are not at all idealβ€”even if they solve your problem. It sounds like it's a matter of an older version of Rocky Linux being used, and updating the example to use Rocky Linux 9 might solve it, but maybe there's something else going on?

I totally agree on feeding the AI, those answers often bring more trouble. to be honest I skipped past the bit at the top about the discussion with chatgpt and went straight to the response and didn't realize until you messaged back. I should have know from all the emojis and general vibes of the AI answer. In this case the answer helped me though and I did go though some slightly tweaked steps.

basically the answer for me was to

  1. after spinning up the vagrant box, ssh in and update packages manually, this got things closer to working
  2. install python3.10 on local system (sudo dnf install python3.10)
  3. setup a venv with python3.10
  4. activate the venv
  5. install ansible 2.12.x in the venv using pip
  6. add the lines for compatablity and extra args to the Vagrantfile
    ansible.compatibility_mode = "2.0"
    ansible.extra_vars = {
    ansible_python_interpreter: "/usr/libexec/platform-python"
    }
  7. I added my own readme to remind myself of these steps and to activate the .venv when inevitably I come back in a week and things dont work.

the issue here did seem (for my system at least) that a more recent linux os (fedora 42) with ansible installed as recommended in chapter 1 will run into the issue of python version incompatibility with the rockylinux8 vagrant box. I don't know enough about rocky9 to know if that would fix things though it is likely that it would. I was trying to stick pretty close to the book as I have experience with ansible but Ive got no prior experience with vagrant right now. I typically spin up test systems using proxmox or terraform with libvirt/qemu.

I would summarize the issue like this

python versions newer than 3.10 on the host are incompatible with the geerlingguy/rockylinux8 vagrant guests without lots of tinkering

a quick summary of the fix could be either to replace with a rocky9 based vagrant box or setup an environment where you have ansible version 2 available.

I hope that helps, Im sure there are other ways to go about this but thats what I did/would do. Loving the book by the way Jeff! this version issue actually taught me a lot about working with older systems which is something I need to learn for work.

@kmatthews123 - Thank you!

And I definitely have encountered this fun Python versioning hell a bit as well. For a couple configurations, I actually pinned Ansible to 2.9 just to overcome the issue (that's the official recommendation if you're running in a corporate environment with older servers, heh).

But I will hopefully get the book updated to use newer Rocky Linux soon. Also, see #404 β€” I plan on moving examples over to something else for virtualization with IP addressing, still haven't made up my mind yet.

your welcome, and thanks for the reply. After some reflection its kinda the nature of technical books that things fall out of functionality as stuff moves on right away as soon as you publish. your continued care and attention while doing all the other youtube-y things is really appreciated. I'm continuing to enjoy the book, Learning more about ansible adhoc now and its great. ( getting past just using adhoc to ping all my stuff is gonna be big)
per #404 I did try playing around with vagrant targeting libvirt to create VM's but decided I didn't know enough with vagrant at this point to solve issues that popped up quickly. maybe Ill look into vagrant Tart and other solutions mentioned in the thread but I'm happy with the solution Ive got working now. If you think it would make sense to fork and PR to add a solution id be happy to contribute but I'm inexperienced working with projects at this scale so I'm not sure if it would be helpful/appropriate.