Configure Environment

Configure Environment

Ansible’s environment consists of a collection of files, including playbooks, plays, variables, and roles, all organized into a directory structure suitable for Ansible to work within.

Looking at Ansible’s documentation, two best practice layouts are recommended. Feel free to use what you prefer but for this guide, we’ll be working with the first recommendation.

Here’s the structure we’ll be creating:

production                # Inventory file for production environment.
development               # Inventory file for staging environment.

group_vars/
   group1.yml             # For any variables we would like to assign to a group of hosts.
   group2.yml
host_vars/
   hostname1.yml          # For any variables we would like to assign directly to a host.
   hostname2.yml

library/                  # For storing custom modules.
module_utils/             # For storing custom module_utils to support modules.
filter_plugins/           # For storing custom filters.
roles/                    # For storing ansible roles.

Directory Creation

Before setting up our environment, create the directory which will hold it. As we want this directory to be managed by multiple users, we’ll use ACLs again to ensure read/write access to any member of the ansible group.

Create Directory

Create the /opt/ansible directory.

sudo mkdir /opt/ansible

Group Membership

ℹ️
Skip this step if you previously completed the installation section.

Create a new group called ansible.

sudo groupadd ansible

Add all user’s who will be using Ansible on the host.

sudo usermod -a -G ansible username

Configure Permissions

Update the permissions so the ansible group will have read, write and execute permissions on the /opt/ansible directory.

sudo setfacl -m g:ansible:rwx /opt/ansible

Rerun the command, now with the -d flag (for default). This applies new default ACLs so all future sub-directories/files created within /opt/ansible ahve the same permissions as our top-level directory.

sudo setfacl -d -m g:ansible:rwx /opt/ansible

Restart Shell

Restart the shell to see these changes take effect.

exec bash

Create Environment

With our permissions configured, move under /opt/ansible and create our Ansible structure.

cd /opt/ansible
mkdir {group_vars,host_vars,library,module_utils,filter_plugins,roles}
touch production development

Structure Overview

Congrads, we now have a basic Ansible environment we can start filling out with hosts, variables and roles. Before moving on to the next step, let’s quickly go through and outline the purpose of each folder and how they work together in managing an environment.

Inventory File

The production and development files will be our inventory files. This is where we tell Ansible about the hosts we’d like managed and assign those hosts to various groups.

For example, here is an inventory file which lists three groups: linux_hosts, web and db. Under these groups, we list our hosts, indicating that these hosts are members of said group.

As shown, you’re welcome to have hosts be apart of multiple groups.

production
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

linux_hosts:
  hosts:
    web01.prod.twobyte.blog:
    web02.prod.twobyte.blog:
    db01.prod.twobyte.blog:

web:
  hosts:
    web01.prod.twobyte.blog:
    web02.prod.twobyte.blog:

db:
  hosts:
    db01.prod.twobyte.blog:

The reason that we have both a production and development inventory file is to allow for testing before deployment. Typically both environments would match so testing could occur on our development environment and then, when confident, be deployed against our production environment.

Here’s an example where you can see identical setups but under different sub-domains to differentiate between the production and development environments.

development
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
linux_hosts:
  hosts:
    web01.dev.twobyte.blog:
    web02.dev.twobyte.blog:
    db01.dev.twobyte.blog:

web:
  hosts:
    web01.dev.twobyte.blog:
    web02.dev.twobyte.blog:

db:
  hosts:
    db01.dev.twobyte.blog:
production
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
linux_hosts:
  hosts:
    web01.prod.twobyte.blog:
    web02.prod.twobyte.blog:
    db01.prod.twobyte.blog:

web:
  hosts:
    web01.prod.twobyte.blog:
    web02.prod.twobyte.blog:

db:
  hosts:
    db01.prod.twobyte.blog:

Variable Files

Moving down a little we have two folders used for defining variables across our environment called group_vars and host_vars.

group_vars is for assigning variables against a collection or group of hosts. host_vars is its antithetical; when you want to assign a variaible against a specific host.

Group Example

Continuing with the example above, say we want to apply a variable to all web servers. To do this, we wouold create file called web within group_vars (notice how the filename matches the group name). Inside we define a variable that applies to all members of this group, for example the apache version we want installed.

groups_vars/linux_hosts
1
apache_version: 2.4.1

Host Example

Say instead we want to apply a hostname to each host using hostnamectl. To do this, we would create a file for each host under host_vars matching the host’s name. Starting with web01.prod.twobyte.blog, we would run the following command:

touch host_vars/web01.prod.twobyte.blog

Next within the host_vars/web01.prod.twobyte.blog file, we would specfy the host’s hostname as a variable.

host_vars/web01.prod.twobyte.blog
1
hostname: web01.prod.twobyte.blog

All Hosts

What if we wanted to apply a setting to every host? Thats doable under a the special file group_vars/all.yaml. Any variable set within this file is applied to all hosts.

group_vars/all.yaml
1
timezone: America/Vancouver

Modules & Plugins

For now ignore library,module_utils,filter_plugins as these are for more advanced features of Ansible that are best learned later.

Roles

Lastly, we have our roles directory. roles are similar in idea to functions in programming. This is aruguble a larger topic best handled with a more indepth article.

Configuring Our Environment

Understanding the basics, lets start filling in all the details in our Ansible environment.

Inventory File

First lets add all of our Linux-based hosts so Ansible is aware of them. Open your production inventory file and create a group called linux_hosts. Underneath, list all of your Linux-based hosts.

production
1
2
3
4
5
linux_hosts:
  hosts:
    web01.prod.twobyte.blog:
    web02.prod.twobyte.blog:
    db01.prod.twobyte.blog:

Next, if applicable, do the same for Windows hosts.

production
1
2
3
4
windows_hosts:
  hosts:
    dc01.ad.twobyte.blog:
    fs01.ad.twobyte.blog:

In anticipation of needing to assign host-specific variables, lets create a file for each host under host_vars. We’ll fill in the details later.

# Linux Hosts
touch host_vars/web01.prod.twobyte.blog
touch host_vars/web02.prod.twobyte.blog
touch host_vars/db01.prod.twobyte.blog

# Windows Hosts
touch host_vars/dc01.ad.twobyte.blog
touch host_vars/fs01.ad.twobyte.blog
...

Congraduations, you now have a basic folder/file structure for housing your Ansible plays, playbooks, roles, inventories etc.

Below is what your structure should look like after finishing this article.

production
development

group_vars/
  linux_hosts.yml
  windows_hosts.yml
host_vars/
  web01.prod.twobyte.blog
  web02.prod.twobyte.blog
  db01.prod.twobyte.blog

library/
module_utils/
filter_plugins/
roles/