This is a text-only version of the following page on https://raymii.org:
---
Title       : 	Ansible: access group vars for groups the current host is not a member of
Author      : 	Remy van Elst
Date        : 	27-01-2017
URL         : 	https://raymii.org/s/tutorials/Ansible_access_other_groups_group_vars.html
Format      : 	Markdown/HTML
---



![ansible logo][1]

This guide shows you how to access group variables for a group the current host
is not a member of. In Ansible you can access other host variables using
`hostvars['hostname']` but not group variables. The way described here is
workable, but do I consider it a dirty hack. So why did I need this? I have a
setup where ssl is offloaded by haproxy servers, but the virtual hosts and ssl
configuration are defined in Apache servers. The loadbalancers and appservers
are two different hostgroups, the ssl settings are in the appserver group_vars,
which the hosts in the loadbalancer group need to access. The best way to do
this is change the haproxy playbooks and configuration and define the
certificates there, but in this specific case that wasn't a workable solution.
Editing two yaml files (one for the appservers and one for the loadbalancers)
was not an option in this situation.

<p class="ad"> <b>Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics. Please, if you found this content useful, consider a small donation using any of the options below:</b><br><br> <a href="https://leafnode.nl">I'm developing an open source monitoring app called  Leaf Node Monitoring, for windows, linux & android. Go check it out!</a><br><br> <a href="https://github.com/sponsors/RaymiiOrg/">Consider sponsoring me on Github. It means the world to me if you show your appreciation and you'll help pay the server costs.</a><br><br> <a href="https://www.digitalocean.com/?refcode=7435ae6b8212">You can also sponsor me by getting a Digital Ocean VPS. With this referral link you'll get $100 credit for 60 days. </a><br><br> </p>


This is applicable for other scenario's as well. In templates this can be worked
around by looping over all the groups, then over all the hosts in the specific
group, then if the host is the first in the loop, go over all the hostvars for
that host and then access the group var you want. [This stackoverflow][3] post
goes over that. In my case I needed to access it in a playbook, the looping
construction woudln't work there.

### The inventory

In the inventory file I created a new group. This group has the two other
groups, `appservers` and `loadbalancers` in them and nothing else. Like so:

    
    
    [appserver]
    app1.cluster   
    app2.cluster   
    
    [loadbalancer]
    lb1.cluster   
    lb2.cluster   
    
    [ssl:children]
    loadbalancer
    appserver
    

The shortnames expand to specifc SSH configuration. The `ssl` hostgroup
effectively includes the following hosts:

  * app1
  * app2
  * lb1
  * lb2

However, we do need to modify the playbook that modifies the vhosts to only
place the certificates on the loadbalancers, and do nothing with the
certificates on the appservers. The playbook should still do it's normal thing,
configuring the vhosts, on the appservers, but not on the loadbalancers.

[The documentation][4] has more information on hostgroups based on other groups.

### The playbook

The playbook (`deploy-vhosts.yml`) first was this:

    
    
    ---
    
    - hosts: appserver
      roles:
        - apache-vhost
    

After changing the hostgroup we need to add the specific role that deploys the
certificates. We also put a `when` in place to make sure the two roles only run
on the hosts where they should and not the other hosts:

    
    
    ---
    
    - hosts: ssl
      roles:
        - {role: apache-vhost, when: "'appserver' in group_names" }
        - {role: sslcerts, when: "'loadbalancer' in group_names " }
    

### The group vars

The group vars for the appservers contain the following information to configure
the virtual hosts:

    
    
    ---
    apache_vhost:
      example.cluster.nl:
        name: example.cluster.nl
        docroot: /home/example-cluster/domains/example.cluster.nl/public-html/
        webuser: example-cluster
        ssl_name: example.cluster.nl
        serveraliases:
          - www.example.cluster.nl
    
      example2.cluster.nl:
        name: example2.cluster.nl
        docroot: /home/example2-cluster/domains/example2.cluster.nl/public-html/
        webuser: example2-cluster
        ssl_name: example2.cluster.nl
        serveraliases:
          - www.example2.cluster.nl
    

The problem is that, when the deploy vhosts playbook in run on the
loadbalancers, they cannot access these variables since they are not in the same
group.

### The role

The role `sslcerts` has one task file and one handler (`restart haproxy`). It
makes sure the folder for the certificates exists and it places the certificate
files there. There are extra when statements to make sure it only runs on the
loadbalancers.

    
    
    - name: create ssl folder
      file:
        path: /etc/ssl/cluster/
        state: directory
        owner: root
        group: root
      when: "'loadbalancer' in group_names"
      tags: ssl
    
    - name: place certificates
      copy:
        src: files/ssl/{{ item.value.ssl_name }}.pem
        dest: /etc/ssl/cluster/{{ item.value.ssl_name }}.pem
      with_dict: '{{ apache_vhost }}'
      when: "'loadbalancer' in group_names"
      notify: restart haproxy
      tags: ssl
    

### The crux

Even after configuring the special playbook that runs on all the hosts, the
loadbalancers still cannot access the group variables from the appservers. The
dirty hack part is that we symlink the group vars from the `appserver` folder to
the `loadbalancer` folder:

    
    
    ln -s /home/deploy/ansible/group_vars/appserver/apache-vhost.yml 
    /home/deploy/ansible/group_vars/loadbalancer/apache-vhost-symlink.yml
    

Now, the loadbalancers have the group variable `apache_vhost` as well, and when
the file in the `appserver` folder is changed, the `loadbalancer` file is as
well because it's a symlink.

### haproxy

haproxy in this case has one frontend where all traffic comes into, the
appservers handle the different virtual hosts:

    
    
    frontend https-in
          mode http
          bind 1.2.3.4:443 ssl crt /etc/ssl/cluster/ no-sslv3
          acl secure dst_port eq 443
          rsprep ^Set-Cookie:\ (.*) Set-Cookie:\ \1;\ Secure if secure
          rspadd Strict-Transport-Security:\ max-age=31536000 if secure
          option httplog
          option forwardfor
          option http-server-close
          option httpclose
          reqadd X-Forwarded-Proto:\ https
          default_backend appserver
    

haproxy handles `sni` transparantly based on the requested hostname, if it finds
the certificate in the folder `/etc/ssl/cluster/`. The files there are a
concatenation of the public key, the private key and if needed the certificate
chain.

### Conclusion

In this case it might be better to change the haproxy playbook to handle this,
or to change the group_vars to `all`. However, this environment has certain
constraints set, so this 'suboptimal' workaround works.

   [1]: https://raymii.org/s/inc/img/ansible-logo.png
   [2]: https://www.digitalocean.com/?refcode=7435ae6b8212
   [3]: https://stackoverflow.com/questions/34614337/ansible-get-other-group-vars
   [4]: https://docs.ansible.com/ansible/intro_inventory.html#groups-of-groups-and-group-variables

---

License:
All the text on this website is free as in freedom unless stated otherwise. 
This means you can use it in any way you want, you can copy it, change it 
the way you like and republish it, as long as you release the (modified) 
content under the same license to give others the same freedoms you've got 
and place my name and a link to this site with the article as source.

This site uses Google Analytics for statistics and Google Adwords for 
advertisements. You are tracked and Google knows everything about you. 
Use an adblocker like ublock-origin if you don't want it.

All the code on this website is licensed under the GNU GPL v3 license 
unless already licensed under a license which does not allows this form 
of licensing or if another license is stated on that page / in that software:

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Just to be clear, the information on this website is for meant for educational 
purposes and you use it at your own risk. I do not take responsibility if you 
screw something up. Use common sense, do not 'rm -rf /' as root for example. 
If you have any questions then do not hesitate to contact me.

See https://raymii.org/s/static/About.html for details.