Buy

Vagrant <3's Ansible

Our first big goal is to see if we can use Ansible to setup, or provision, an entire server that can run our MooTube app. To setup an empty VM, we'll use Vagrant with VirtualBox.

So before we start, make sure that you have VirtualBox installed: it's different for each OS, but should - hopefully - be pretty easy. Next, make sure you have Vagrant: it has a nice installer for every OS. On my Mac, surprise! I installed Vagrant via brew.

As long as you can type:

vagrant -v

you're good to go.

Vagrantfile Setup!

If you're new to Vagrant, it's a tool that helps create and boot different virtual machines, usually via VirtualBox behind the scenes. It works by reading a configuration file... which we don't have yet. Let's generate it!

vagrant init ubuntu/trusty64

That just created a file - Vagrantfile - at the root of our project that will boot a VM using an ubuntu/trusty64 image. That's not the newest version of Ubuntu, but it works really well. You're free to use a different one, but a few commands or usernames and passwords might be different!

Tip

If you want to use the latest Ubuntu 16.04 LTS release, you'll need a few tweaks:

1) Change the VM box in Vagrantfile:

# Vagrantfile
Vagrant.configure("2") do |config|
  # ...
  config.vm.box = "ubuntu/xenial64"
  # ...

2) This version of Ubuntu has a different default username to login via SSH, so you have to change it to ubuntu and specify the private SSH key file instead of the password - Ansible can't log in into the server using just a username and password pair. Also, Ubuntu 16.04 has the new pre-installed Python 3, so you have to specify a valid path to the python3 binary file, because Ansible can't find it by itself. You can specify all this information in hosts.ini file for the VirtualBox host:

# ...
[vb]
192.168.33.10 ansible_user=ubuntu ansible_ssh_private_key_file=./.vagrant/machines/default/virtualbox/private_key ansible_python_interpreter=/usr/bin/python3
# ...

3) Ubuntu 16.04 doesn't come with aptitude pre-installed, so you need to install it first if you want to use the safe upgrade option for installed packages. Just add one new task to your playbook before upgrading:

# ansible/playbook.yml
---
- hosts: vb
  # ...
  tasks:
    # ...
    - name: Install aptitude
      become: true
      apt:
        name: aptitude

    - name: Upgrade installed packages
      become: true
      apt:
        upgrade: safe
    # ...

Boot that VM!

With that file in place, let's boot the VM!

vagrant up

Then... go make a sandwich! Or run around outside! Unless you've run this command before, it'll need to download the Ubuntu image... which is pretty huge. So go freshen up your cup of coffee and come back.

Thanks to the power of video, we'll zoom to the end! Zooooom!

When it finishes, make sure you can SSH into it:

vagrant ssh

With any luck, you'll step right into your brand new, basically empty, but totally awesome, Ubuntu virtual machine.

By the way, Vagrant stores some info in a .vagrant directory. In a real project, you'll probably want to add this to your .gitignore file:

19 lines .gitignore
... lines 1 - 17
/.vagrant/

Setup an External IP Address

Our goal is to have Ansible talk to this new VM. For that, we need a dependable IP address for the VM. Check out the Vagrantfile that was generated automatically for us: it has a section about a "private network". Uncomment that!

72 lines Vagrantfile
... lines 1 - 7
Vagrant.configure("2") do |config|
... lines 9 - 26
# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network "private_network", ip: "192.168.33.10"
... lines 30 - 72

This will let us talk to the VM via 192.168.33.10.

For that to take effect, run:

vagrant reload

That should take just a minute or two. Perfect! And now we can ping that IP!

ping 192.168.33.10

Configuring the new Ansible Host

The VM represents a new host. And that means we need to add it to our hosts file! In hosts.ini, let's keep the local group and add another called vb, for VirtualBox. Under there, add the IP: 192.168.33.10:

7 lines ansible/hosts.ini
... lines 1 - 3
[vb]
192.168.33.10
... lines 6 - 7

We know that as soon as we make this change, we should be able to use the vb host:

ansible vb -m ping -i ansible/hosts.ini

That should work, right? It fails! The ping module does a bit more than just a ping, and in this case, it's detecting that Ansible can't SSH into the machine. The reason is that we haven't specified a username and password or key to use for SSH.

Configuring SSH Properly

To see what I mean, try SSH'ing manually - the machine is setup with a vagrant user:

ssh vagrant@192.168.33.10

Woh! Our first error looks awesome!

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

You may or may not get this error. Since I've used Vagrant in this same way in the past, it's telling me that last time I SSH'ed to this IP address, it was a different machine! We know that's ok - there's nothing nefarious happening. To fix it, I just need to find line 210 of my known_hosts file and remove the old fingerprint. I'll do that and save. Try it again:

ssh vagrant@192.168.33.10

It saves the fingerprint and then asks for a password. The password for the image that we're using is vagrant. That's pretty standard, but it might be different if you're using a different image.

We're inside! So, how can we tell Ansible to SSH with username vagrant and password vagrant? The answer is... not surprising! These are two more variables in your hosts inventory file: ansible_user set to vagrant and ansible_ssh_pass=vagrant:

7 lines ansible/hosts.ini
... lines 1 - 3
[vb]
192.168.33.10 ansible_user=vagrant ansible_ssh_pass=vagrant
... lines 6 - 7

Try the ping again:

ansible vb -m ping -i ansible/hosts.ini

Eureka! But, quick note about the SSH password. If this weren't just a local VM, we might not want to store the password in plain text. Instead, you can use a private key for authentication, or use the Ansible "vault" - a cool feature that lets us encrypt secret things, like passwords. More on that later.

But for now, our setup is done! We have a VM, and Ansible can talk to it. Next, we need to create a playbook that's capable of setting up the VM.

Leave a comment!

  • 2017-06-28 weaverryan

    Hey Roberto Briones Arg├╝elles!

    Good question :). And other people have had the same question - check out my answer here: https://knpuniversity.com/s...

    Cheers!

  • 2017-06-28 Roberto Briones Arg├╝elles

    It makes sense to use ansible with Docker, or the dockerfile is the same thing that ansible does?

  • 2017-04-25 Victor Bocharsky

    Haha, don't worry about spamming, we always welcome good comments! ;)

    That's great, we'll add a note with a few steps about how to use Ubuntu 16.04 box instead of 14.04 one - thanks to your comments.

    Cheers!

  • 2017-04-25 diego_disqus

    hahaha sorry for the spam in your comments section!

    ops :) I didn't think about that, probably the ssh key doesn't suit really well in the variables section with multiple hosts. :)

    Anyway, about ansible_python_interpreter, yes, it defines which python interpreter Ansible will use without installing anything.
    Obviously, it's not a 'portable' solution because it works just with distros that have python 3 installed but for tests purposes, I think that's fine :)

    thank you so much for your feedback!

  • 2017-04-25 Victor Bocharsky

    Hey diego_disqus ,

    You share awesome examples with us, thanks a lot! Yeah, "[vb:vars]" is nice solution, I like this way because we don't need to write all the parameters in a one line, so it increases readability! But keep in mind that all those variables apply to the all hosts listed in [vb], which is not a problem for now though.

    What about "ansible_python_interpreter" parameter - interesting idea! I haven't tested it yet, does it mean that we don't need to install "python-apt" package at all, right? If so - it's very sweet!

    P.S. Nice trick with "host_key_checking = False" ;)

    Cheers!

  • 2017-04-24 diego_disqus

    I don't know if is it right but at the end, I've solved in this way :)
    Tested on ubuntu 16.04 - ubuntu/xenial64


    [vb]
    192.168.113.100 ansible_user=ubuntu

    [vb:vars]
    # specifies which python interpreter Ansible needs to use
    ansible_python_interpreter=/usr/bin/python3
    # specifies the private key
    ansible_ssh_private_key_file=./.vagrant/machines/default/virtualbox/private_key

    Also, if you want to skip the prompting for confirmation of the ssh key ( that for a dev environment it's fine for me )
    On Mac OS
    edit or create the file ~/.ansible.cfg
    On Linux
    /etc/ansible/ansible.cfg
    and write


    [vb]
    host_key_checking = False

  • 2017-04-22 weaverryan

    Awesome, thank you for letting us know this was the right way! :)

  • 2017-04-21 A Maria

    This works great! The other way I was getting an error about sshpass not being installed. I'm doing this from the Unix subsystem in Windows 10.

  • 2017-04-18 Victor Bocharsky

    Hey diego_disqus ,

    Thank you for the kind words! Really, Ansible is much easier than Chef and quite fun )

    And yes, we'll do some interaction with AWS like creating EC2 instance with Ansible and deploy app to it at the end of this course, so stay tuned with us ;)

    Cheers!

  • 2017-04-18 diego_disqus

    Before, let me say thank you for this course, I was looking for something more easy than Chef and Ansible looks perfect!
    I need just to understand how it manages nodes in cloud ( like AWS Opsworks for Chef ) but probably, at the end of this course, I will understand :)

    Anyway back to your question. Yep it looks like that Python is not installed.
    But I've found this
    https://gist.github.com/gwi...
    That I think could be useful.

    Thank you for your tip about the private key :) it works!

  • 2017-04-17 weaverryan

    Yo diego_disqus!

    Thanks for the notes! I have a few questions:

    1) On Ubuntu 16.4, was python-apt not already installed (is that why you installed it)? If not, we can add that as one of the first tasks in our playbook :).

    2) You're right about there being a *slightly* better to use this :). We can set the private key in our hosts file:


    192.168.33.10 ansible_user=ubuntu ansible_ssh_private_key_file=./.vagrant/machines/default/virtualbox/private_key

    Try this out - let me know if it works! And based on your answers, I can add some notes to the tutorial! It would be nice to mention some of the important differences on other versions of Ubuntu.

    Cheers!

  • 2017-04-14 diego_disqus

    If you are in trouble with ssh and you are using ubuntu 16.4
    Log in vagrant with vagrant ssh
    type:


    sudo apt-get install --no-install-recommends --assume-yes python-apt

    then exit from the vm

    If you want to run ansible commands do something like:


    ansible --private-key=./.vagrant/machines/default/virtualbox/private_key vb -i ansible/hosts.ini -m command -a 'echo "hello!"'

    Probably there are smarter methods than this :)