Ansible 2.0 introduced a great set of features (ansible_*_args), and glances over using it in the documentation.

However, my personal preference is to do it directly in the inventory. This means you can do things like bake it into a dynamic inventory, or use [all:vars] to keep your inventory nice and DRY.

To do this directly in an inventory:

[all:vars] ansible_ssh_common_args=' -o ProxyCommand="ssh -W %h:%p bastion.host.tld"' [proxy] 10.0.0.2 [application] 10.0.0.3 [database] 10.0.0.4

If you only have, say, one bastion per host:

[proxy] 10.0.0.2 ansible_ssh_common_args=' -o ProxyCommand="ssh -W %h:%p proxy-bastion.host.tld"' [application] 10.0.0.3 ansible_ssh_common_args=' -o ProxyCommand="ssh -W %h:%p app-bastion.host.tld"' [database] 10.0.0.4 # Also acceptable [database:vars] ansible_ssh_common_args=' -o ProxyCommand="ssh -W %h:%p db-bastion.host.tld"'

However, ansible_ssh_common_args is not the only useful thing here. If you’re using sftp or scp (say, for jailed users) you can use it in exactly the same way. Looking at the most recent manpages for sftp and scp all above examples will work, right down to the same -o line.

Doing the above I locate my bastion and put it into my dynamic inventory.

To do this with a dynamic inventory you’d want something like the following:

$./inventory.py --list { ... "proxy": { "hosts": ["10.0.0.2"] "vars": { "ansible_ssh_common_args":"-o ProxyCommand='ssh -W %h:%p bastion.host.tld'" } }, ... }

Doing this makes accessing hosts on private networks through Ansible an absolute snap.