I've got an Ansible role with several tasks that I run for several virtual hosts. My playbook works, and it looks like this:


- name: Create vhost configuration
  # action
  with_items: vhosts

- name: Ensure vhost is enabled
  # action  
  notify: restart apache2
  with_items: vhosts

# (Many more actions)

Is there a way to avoid having to write with_items for every action? Can I iterate over the vhost items for the whole playbook rather than running each command for all vhosts sequentially? (as I am with the above code)

  • I deleted my answer, because, as you pointed out, it was not applicable. If this code runs on the host system rather than on the virtual machines themselves, I don't know how you can do it without with_items. However, a real example instead of "# action" would have made your question clearer and it might make others think of alternative ways to do what you are trying. Oct 26, 2014 at 19:47
  • I tried to do that with include and with_dict. But unfortunatly thats deprecated. Now I'm searching for a solution, too.
    – Subito
    Feb 23, 2015 at 9:19

2 Answers 2


From what you're asking, it sounds like you just want to specify the vhosts group as the hosts to run a specific role on. So your playbook should start something like this:

- hosts: vhosts
  name: Tasks run on vhosts
    - { role: somerole }

Keep in mind that you can have multiple plays in your playbook, so it's perfectly fine to do something like this:

- hosts: all
  name: Run roles for all servers
    - { role: role1 }
    - { role: role2 }
    - etc.

- hosts: vhosts
  name: Run roles specific to vhosts
    - { role: vhost-role }

- hosts: all
  name: Post-vhost roles for all servers
    - { role: role3 }
    - etc.

If you have a single playbook that you want to run on different host groups at different times then you can use a variable for the hosts entry:

- hosts: "{{ somevar }}"
  name: Run roles against a user specified set of hosts
    - { role: foo }

And then you'd invoke this last one in one of these ways:

$ ansible-playbook playbook.yml --extra-vars "somevar=vhosts"

$ ansible-playbook playbook.yml --extra-vars "somevar=host1,host2"

It's nowadays possible to include a role for each item in a list, using include_role in a loop. (Since Ansible 2.5, it is advised to use loop instead of with_items.)

First, create a role which iterates over a sub-role for each item in the vhosts list:

# vhosts/tasks/main.yml

- name: Iterate over all vhosts
  loop: "{{ vhosts }}"
    name: vhost
    vhost: "{{ item }}"

For each vhost, the vhost role will be called, with a variable called vhost containing its data.

You can then write a sequence of tasks which operate on this, like so:

# vhost/tasks/main.yml

- name: Create vhost html directory
    path: "/var/www/vhosts/{{ vhost.domain }}/html"
    state: directory

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.