Run an Ansible playbook in a remote chroot
Running a playbook in a remote chroot or container is not supported by Ansible, but I have invented a good workaround to do it anyway.
The first step is to install Mitogen for Ansible (ansible-mitogen in Debian) and then configure ansible.cfg to use it:
[defaults] strategy = mitogen_linear
But everybody should use Mitogen anyway, because it makes Ansible much faster.
The trick to have Ansible operate in a chroot is to make it call a wrapper script instead of Python. The wrapper can be created manually or by another playbook, e.g.:
vars: - fsroot: /mnt tasks: - name: Create the chroot wrapper copy: dest: "/usr/local/sbin/chroot_{{inventory_hostname_short}}" mode: 0755 content: | #!/bin/sh -e exec chroot {{fsroot}} /usr/bin/python3 "$@" - name: Continue with stage 2 inside the chroot debug: msg: - "Please run:" - "ansible-playbook therealplaybook.yaml -l {{inventory_hostname}} -e ansible_python_interpreter=/usr/local/sbin/chroot_{{inventory_hostname_short}}"
This works thanks to Mitogen, which funnels all remote tasks inside that single call to Python. It would not work with standard Ansible, because it copies files to the remote system with SFTP and would do it outside of the chroot.
The same principle can also be applied to containers by changing the wrapper script, e.g:
#!/bin/sh -e exec systemd-run --quiet --pipe --machine={{container_name}} --service-type=exec /usr/bin/python3 "$@"
After the wrapper has been installed then you can run the real playbook by setting the ansible_python_interpreter variable, either on the command line, in the inventory or anywhere else that variables can be defined:
ansible-playbook therealplaybook.yaml -l {{inventory_hostname}} -e ansible_python_interpreter=/usr/local/sbin/chroot_{{inventory_hostname_short}}