Learn How to Install Ansible and Run Playbooks

This is a Linode Community guide. If you’re an expert on something for which we need a guide, you too can get paid to write for us.

Getting started with Ansible: An Installation and Configuration Tutorial

Consider the monotony of administering a server fleet; keeping them all updated, pushing changes out to them, copying files, etc. Things can get complicated and time consuming very quickly, but it doesn’t have to be that way.

Ansible is a helpful tool that allows you to create groups of machines, describe how those machines should be configured or what actions should be taken on them, and issue all of these commands from a central location. It uses SSH, so nothing needs to be installed on the machines you are targeting. Ansible only runs on your main control machine, which can even be your laptop! It is a simple solution to a complicated problem.

This guide will introduce you to the basics of Ansible. By the end of this guide, you’ll have the tools needed to turn a brand new Linode into a simple web server (Apache, MySQL, PHP), easily replicable and adjustable.

Note

This guide is written for a non-root user. Commands that require elevated privileges are prefixed with sudo. If you’re not familiar with the sudo command, you can check our Users and Groups guide. Some systems may require you to run Ansible commands as root. If so, prefix the ansible commands in this guide with sudo.

Installing Ansible

Ansible only needs to be installed on the control machine, or the machine from which you will be running commands. This will likely be your laptop or other computer from which you frequently access your server, or it may be a centralized server in more complicated setups.

Make sure that you have Python 2.x available on the control machine. Ansible is not compatible with Python 3, nor can you use Windows as the control machine. You can build Ansible from source, or install the latest stable packages using the proper command below.

Mac OS X:

sudo easy_install pip sudo pip install ansible

CentOS/Fedora:

sudo yum install ansible

Note

The EPEL-Release repository may need to be added on certain versions of CentOS, RHEL, and Scientific Linux.

First Steps to Configuring Ansible

Now that you have Ansible installed, let’s test it out on a known server. All Ansible commands are executed via the command line (or batched in scripts), and follow the pattern:

ansible server_or_group -m module_name -a arguments

We’ll get to groups in just a moment, but for now, let’s try to make a simple connection to an existing server you have using the ping module. In place of server_or_group, type the name of a server that you can currently SSH into from your machine using key authentication. If you are using a non-standard SSH port, include that after a colon on the same line (myserver.com:2222).

By default Ansible will use the same username as your current machine’s username. If this will not match up, pass the proper username in using the -u username argument.

Note

If you don’t want to use SSH keys, you can add the --ask-pass switch.

To try an Ansible command without any additional setup, we’ll add a few extra arguments for now. Format a test command like the following:

ansible all -i myserver.com, -m ping

Note

The extra directives are the all -i and the comma after your server name. This is temporary, and is only there to tell Ansible to try connecting directly to the server without an inventory file, which we’ll learn about later.

If you are successful you should see output similar to the following:

myserver.com | success >> {
"changed": false,
"ping": "pong"
}

You were just able to get a valid connection to your server via Ansible!

Using Ansible’s Inventory File

You executed an Ansible command against one client, but it would be cumbersome to have to type the host’s address every single time, and what if you had several servers you wanted to apply the same configuration to? This is where Ansible’s inventory file comes into play.

By default, the inventory file is expected to be /etc/ansible/hosts. Create that path and file if it does not already exist.

Note

If you are running OS X, you may want to create your own Ansible directory elsewhere and then set the path in an Ansible configuration file:

Add an entry to your hosts file, pointing to a server that you connected to in the previous section. You can include multiple servers in this file, using either domains or IP addresses, and can even group them:

Use the all directive to ping all servers in your hosts file via Ansible:

ansible all -m ping

You should receive the same output as before, for each server in your hosts file. Note that instead of all, you could have substituted mailservers from the example file, and it would run just against those servers.

Ansible Configuration via Playbooks

Playbooks in Ansible define a series of actions to run, and address particular sets of servers. It’s important to note that, unlike some other configuration tools, a playbook does not describe a state of the machine, with Ansible determining all the changes that need to be made on its own. However, playbooks should be designed to be idempotent, meaning that they can be run more than once without negative effects. For example, a playbook might have a task that sets up a configuration file for a server and injects a few variables. The playbook should be written such that Ansible can take the template configuration file, compare it to the actual file, and create/update it only if necessary. Luckily, many Ansible modules take care of the heavy lifting for that.

You can write playbooks to perform initial server configurations, add users and directories, ensure certain software packages are installed or uninstalled, move files, etc. A playbook can also run a few commands on one set of machines, switch to a different set to run different commands, and then switch back to the original or a different set of machines. It is procedural, and tasks are run in order, top to bottom.

A playbook is a YAML file, and typically follows this structure:

Sample Playbook YAML file

123456

----hosts:[targethosts]remote_user:[yourname]tasks:-[task1]-[task2]

For example, the following playbook would log in to all servers in the marketingservers group and ensure Apache was started.

Every task should have a name, which is logged and can help you track progress. Following the name line is the module that will be run (in this case, the service module), and the other attributes provide more options, in this case instructing Ansible to use sudo privileges (which we will configure later).

Running Playbooks

Executing a playbook is even easier than running ad-hoc commands like we did earlier. Assuming you are in the same directory as a playbook file, you run the following command:

ansible-playbook myplaybook.yml

If you want to see what hosts this playbook will affect without having to open up the YAML file, you can run:

ansible-playbook myplaybook.yml --list-hosts

Types of Tasks You Can Run

Ansible ships with a large collection of modules that you can run as tasks or via ad-hoc commands. To see a listing of all available modules, run:

ansible-doc -l

A few common core modules you might be interested in learning first include:

Basic Web Server Setup via Ansible Playbooks

As an example, we’ll use Ansible to turn a freshly created Linode server into a web server, configured with Apache, MySQL, and PHP, ready to serve up dynamic sites and configured with the proper users and permissions. For brevity we won’t handle all of the features and configuration that might normally be involved, but will cover enough to get you started.

Caution

The following playbooks are for learning purposes only, and will NOT result in a hardened or secure server. Use them to learn from, but do not use them for production instances!

Prerequisites

This example will assume a brand new Ubuntu 14.04 LTS server, without any additional configuration already done to the box. The very first order of business will be to add in our public encryption keys so that we can connect without supplying passwords.

Because Ansible playbooks are idempotent and can be run repeatedly without error, the user task checks that a user exists and that the password on file (which the system stores hashed) matches the hash you are supplying. Therefore you cannot (and should not) just put in a plaintext password, you must pre-hash it.

Create a password hash for Ansible to use when communicating with the servers. An easy method is to use Python’s PassLib library, which can be installed with sudo pip install passlib.

Once installed, run the following command, replacing plaintextpassword with your actual password:

Create the System User

Add your new server’s IP address to your Ansible hosts file so that we can address it. Remove any previous entries you may have added in the test sections above. Give the new server a group name to make it easier to refer to later. In our example the group name is linode.

/etc/ansible/hosts

12

[linode]123.123.123.123

Write a playbook that creates a new normal user, adds in our public key, and adds the new user to the sudoers file.

We’re introducing a new aspect of Ansible here: variables. Note the vars: entry and the NORMAL_USER_NAME line. You’ll notice that it is reused twice in the file so that we only have to change it once. Replace yourusername with your choosen username, localusername in the path for the authorized_key, and the password hash.

Save the playbook file as initialize_basic_user.yml and run the playbook with the following command. Note how we specify the use of a particular user (-u root) and force Ansible to prompt us for the password (-ask-pass) since we don’t have key authentication set up yet:

ansible-playbook --ask-pass -u root initialize_basic_user.yml

You should see output from Ansible that reports that the three tasks all completed successfully with a status of “changed.” We can now work with new playbooks using our normal user account and keys.

Configure the Base System

Let’s take care of some common server setup tasks, such as setting the timezone, updating the hosts file, and updating packages. Here’s a playbook covering those steps:

As you run this playbook you will again see the steps come across as “changed.” Updating packages may take a few minutes, so don’t fret if it doesn’t return straight away.

Install the Stack

Finally, let’s get a very basic server set up with Apache and PHP, and a test MySQL database to use.

The following playbook downloads the appropriate packages, turns on the Apache and MySQL services, and creates a basic database and user.

setup_webserver.yml

1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930

----hosts:linoderemote_user:yourusernamebecome:yesbecome_method:sudotasks:-name:"Install Apache, MySQL, and PHP5"apt:name={{item}}state=presentwith_items:-apache2-mysql-server-python-mysqldb-php5-php-pear-php5-mysql-name:"Turn on Apache and MySQL and set them to run on boot"service:name={{item}}state=startedenabled=yeswith_items:-apache2-mysql-name:Createatestdatabasemysql_db:name=testDbstate=present-name:Createanewuserforconnectionsmysql_user:name=webapppassword=mypasswordpriv=*.*:ALLstate=present

Run the playbook from your control machine with the following command:

ansible-playbook setup_webserver.yml --ask-become-pass

When this playbook finishes, visit your Linode’s IP address or FQDN to see the default Ubuntu Apache index page.

Log in via SSH and check to see that the testDb has indeed been created:

mysql -u root -p
show databases;

You can even create a sample PHP page and place it in /var/www/html to test that PHP is active on the server. Ansible has done as we instructed it to, installing the appropriate packages and setting things up as we want.

Exploring Ansible Further

This is just the start of learning Ansible, and as you continue to learn and explore you will find it a truly powerful and flexible tool. Take a look at some of the example Ansible playbooks provided by the company itself.

Below are a few topics to explore that become important as you create playbooks of any complexity, and that you will see frequently in others’ playbooks.

More Information

You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.