Ansible tutorial part 1: Inventory files , vagrant and remote hosts

Per Wagner Nielsen
5 min readJan 5, 2018

--

In this tutorial series we will use Ansible to setup a Flask website with a database on an Ubuntu 16.04 server. We will go step by step from getting the Ubuntu server setup, installing and running our little Flask app on a Vagrant machine and deploying the same Flask app server on the internet (on Linode).

The local setup I will be using is a Linux Mint 18.1 machine with Vagrant 2.0.1 installed.

This is not a tutorial for complete beginners, so you might need to do some googling on some of the topics that I don’t cover.

Part 1 will cover how to deploy a simple playbook to both a local Vagrant VM and a remote server.

Additional resources

Run locally on Vagrant

installing Ansible

We will install Ansible in a virtualenv with pip. Create a folder to hold all our code:

$ mkdir ansible_tutorial
$ cd ansible_tutorial
$ virtualenv venv -p python3.6
$ source venv/bin/activate
$ pip install ansible flask

here is a one liner for it all:

mkdir ansible_tutorial;cd ansible_tutorial;virtualenv venv -p python3.6;source venv/bin/activate;pip install ansible flask

If you don’t have python3.6 installed, you can just do $ virtualenv venv -p python3 instead. I use Python 3.6 for most of my own stuff, but we won’t be using any specific 3.6 features in this tutorial.

Setting up Vagrant

Create the Vagrant file:

$ touch Vagrantfile

Add the following to the file

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.define "web01" do |web01|
web01.vm.box = "bento/ubuntu-16.04"
web01.vm.network "private_network", ip: "192.168.33.11"
web01.vm.hostname = "web01"
web01.ssh.forward_agent = true
web01.ssh.port = 2222
web01.vm.synced_folder ".", "/vagrant"
web01.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
web01.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
end
end
end

We are doing a few things here. First, we base ourselves on a Ubuntu 16.04 and sets the hostname to ‘web01’. We are also telling Vagrant that once we provision this box we want it to run the ‘playbook.yml’ playbook, which should be located in the same directory as the Vagrantfile.

Setting up an initial playbook

We need to create our playbook.yml file:

$ touch playbook.yml

In the playbook.yml add this

---
- name: Web01
hosts: all
become: yes
gather_facts: False
pre_tasks:
- name: Install python for Ansible
raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
changed_when: False
- setup: # aka gather_facts

This small playbook will only do one thing, install python on the box in case it is not already installed.

Activate Vagrant by typing:

$ vagrant up

It will take a bit of time (some minutes) for Vagrant to be ready, when it is, you should see something like:

web01: Running ansible-playbook...
______________
< PLAY [Web01] >
--------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
___________________________________
< TASK [Install python for Ansible] >
-----------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
ok: [web01]
______________
< TASK [setup] >
--------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
ok: [web01]
____________
< PLAY RECAP >
------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
web01 : ok=2 changed=0 unreachable=0 failed=0

So now we can see Ansible is actually working, the playbook was successfully run on the VM box.

Note: If you want to get rid of the ascii cow, create a file called ‘ansible.cfg’ and add this to it:

[defaults]nocows = 1

Deploy to a host on the internet

Add ssh key to remote host

In order to configure a host on the internet, we first need to have a place to host it. For this tutorial, I’ll go for the smallest Linode instance. First we need to add our public key file to the remote server as Ansible requires SSH in order to work.

Make sure you have a ssh key in ~/.ssh and run:

$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@123.123.123.123

where you insert the correct IP address of your remote server. This will copy your local public key to the remote server.

Create Inventory File

Inventory files hold information about how you connect to your servers and in our case will look like this:

---[web01]
123.123.123.123
[web01:vars]
ansible_ssh_user=root
ansible_ssh_private_key_file=/home/<USERNAME>/.ssh/id_rsa

We will be creating 2 different hosts files, one for our Vagrant box and one for our staging (Linode) server. Make two files called hosts_vagrant and hosts_staging:

touch hosts_vagrant hosts_staging

Add the following to hosts_vagrant:

[all:vars]
env=vagrant
[web]
127.0.0.1
[web:vars]
ansible_port=2222
ansible_user=vagrant
ansible_private_key_file="./.vagrant/machines/web01/virtualbox/private_key"

And this to hosts_staging:

[all:vars]
env=staging
[web]
123.123.123.123
[web:vars]
ansible_ssh_user=root
ansible_ssh_private_key_file=/home/perwagner/.ssh/id_rsa

Put the files in the same folder as the Vagrantfile. (substitute the IP of your remote host and the <USERNAME> with your username and insert whatever file path that points to your private key). It is important that the group name is the same in the hosts file and in the playbook.

The first line with [web] is the name of the group of servers which are specified below. In our case we have just one. If you wanted to, you can have several different groups in the inventory file, like servers for your web apps and servers for your databases. The [web:vars] specifies additional settings for the group.

Lets test our connection to the remote host:

$ ansible -i ./hosts_staging web -m ping

If all goes well, you should see this message:

123.123.123.123 | SUCCESS => {
"changed": false,
"ping": "pong"
}

Which shows that our Ansible successfully connected to our remote host.

The -i option tells ansible that the next argument (./hosts) is the inventory file and the web argument specifies which group in the inventory file Ansible should communicate with. The final -m ping is the module we want to execute (in this case a simple ping).

Run the playbook on the remote host

In order to have Ansible run the playbook on our remote host, we need to invoke a different Ansible command, the ansible-playbook command:

$ ansible-playbook -i ./hosts_staging playbook.yml

Again, the -i option specifies the inventory file while the last argument is the playbook we want to execute.

If all goes well, you should receive a similar success message as before when we had our Vagrant box run the playbook. Thus, we have successfully run the same playbook on both the local VM and the remote server.

Conclusion

I hope all went well and that you successfully managed to setup both the local Vagrant and remote host.

If you have any questions or suggestions on how to improve this tutorial, please reach out to me and leave a comment below.

--

--

Per Wagner Nielsen

Data Scientist with a master degree in Economics and a BA in Computing. I have a special interest in geopolitics, war and economics