User Tools

Site Tools


general:linux:ansible_on_remote_nspawn_container

How to target a remote nspawn container with ansible

After trying lots of things (using machinectl for example) and searching for a solution I finally found this:

Run an Ansible playbook in a remote chroot

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}}

Notes

Make sure python3 is installed in the container.

Requires that ansible-mitogen is installed and used on the machine you are issuing the ansible commands from.

Example usage with ini-style inventory.

[containers]
containername ansible_python_interpreter=/usr/local/sbin/containername_ansible_wrapper.sh ansible_host=hostname-that-container-resides-on

[containers:vars]
ansible_user=root
general/linux/ansible_on_remote_nspawn_container.txt · Last modified: 2025/02/20 11:14 by sunkan

Donate Powered by PHP Valid HTML5 Valid CSS Run on Debian Driven by DokuWiki