Using Host Variables

Last Updated:

In the previous example, we installed the redis-server package and configured Redis with templates. As we left it, Redis listened only on the local machine (127.0.0.1), on the default port (6379). Let's take a look at the playbook from the last lesson:

---
- name: Install Redis
  hosts: all
  vars:
    redis_port: 6379
    redis_databases: 1
  tasks:

    - name: Ensure Redis is present
      apt: pkg=redis-server state=latest
      sudo: true

    - name: Ensure Redis is started
      service: name=redis-server state=started enabled=yes
      sudo: true

    - name: Ensure Redis Configuration
      template: src=redis.conf.j2 dest=/etc/redis/redis.conf owner=root group=root mode=0644
      sudo: true
      notify: Redis Restart

  handlers:

    - name: Redis Restart
      service: name=redis-server state=restarted enabled=yes
      sudo: true

We could bind Redis to a public, Internet-facing IP address so it can be accessed from anywhere, but that also opens it up for more attacks. Instead we can bind to the Local LAN network, since we anticipate to use the Redis machine with our other machines in the near future. This way, other machines can have access to Redis over the network, without us needing to expose it to the whole Internet. Let's edit our Vagrantfile slightly to give us a new private interface.
(Note: SysAdmin veterans are probably screaming “use a firewall!” by now, and we will in a future lesson).

# Add This Before "Provision with Ansible"
# in your Vagrantfile

# Redis
config.vm.define "redis" do |redis|
  redis.vm.network "private_network", ip: "192.168.10.10"
end

Run the following command to restart the machine and apply the changes.
(Note: Ansible will run as part of the “vagrant up” process since we listed it as the provisioner in the Vagrantfile.)

$ vagrant halt && vagrant up

Host Variables with Ansible

How can we possibly know the local IP address of the Redis machine? Well, we could parse some configuration files and extract it that way like in a shell script, but that's tedious and prone to errors. Ansible conveniently provides a lot of predefined variables of the machine and it makes our lives easier. To view all of the variables, add this task:

- name: Display Host Variables
  debug: var=hostvars

The output will have a bunch of data that you can use in your playbooks. I won't paste it here because it's so long. Instead, here's a snippet:

"ansible_eth1": {
    "active": true,
    "device": "eth1",
    "ipv4": {
        "address": "192.168.10.10",
        "netmask": "255.255.255.0",
        "network": "192.168.10.0"
    },
    "ipv6": [
        {
            "address": "fe80::a00:27ff:fe65:3d8d",
            "prefix": "64",
            "scope": "link"
        }
    ],
    "macaddress": "xx:xx:xx:xx:xx:xx",
    "module": "e1000",
    "mtu": 1500,
    "promisc": false,
    "type": "ether"
}

Putting Variables to Work

We're interested in the second interface (eth1), which listens on the local network, instead of eth0 which is the “public” interface (but not while we use Vagrant). This might feel a bit weird now, but will become more useful when we leave VirtualBox and Vagrant for a cloud provider. We can use the address we see above in our templates, but it's buried deep. Check out this part of the Redis configuration file from the previous lesson and edit it to be like the following:

# By default Redis listens for connections from all the network interfaces
# available on the server. It is possible to listen to just one or multiple
# interfaces using the "bind" configuration directive, followed by one or
# more IP addresses.
#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# DEFAULT: bind 127.0.0.1
bind 127.0.0.1 

Now we have Redis bound to the localhost and the private network.
We use a special host variable without quotes to select whichever machine we are currently provisioning.

Wrap Up

Hopefully using host variables makes more sense now. All we really did was explore built-in Ansible variables and use one in our template after we found out what it was named. We're ready to move on to the next lesson since Redis has been reconfigured to listen on the private network.