Probably one of the easiest and most straight forward things we can do using Ansible is to install and configure a web server. Specifically Nginx.

Let's log in to our management machine and use curl on the command line to check if the web server on our server is accessible:

curl http://192.168.56.11

The response is

curl: (7) Failed to connect to 192.168.56.11 port 80: Connection refused

because there is no web server on that box.

Install Nginx on Ubuntu

We need to have inventory file that lists all the boxes we would like to manage.

[web]
192.168.56.11

[web:vars]
ansible_python_interpreter=/usr/bin/python3

Here we have a group called "web" (you can have any arbitrary name there) and the single remote machine is listed in that group. The ansible_python_interpreter=/usr/bin/python3 is there so Ansible will use Python 3 on the remote machine.

We create an Ansible Playbook which is just a YAML file:

examples/ansible/nginx_install.yml

---
- hosts: all
  tasks:
    - name: ensure nginx is at the latest version
      apt: name=nginx state=latest
    - name: start nginx
      service:
          name: nginx
          state: started

In this playbook we have one task that has two steps. The "- name: ...." are only there for the humans, to make sense of the commands. The first step apt: name=nginx state=latest tells the apt module that we want the latest version of the nginx package to be installed. The next step tells Linux to make sure the service called nginx is started. (The name: nginx is part of the command.) Interestingly on the current version of Ubuntu you don't need the latter as Ubuntu takes care of it, but it is better to explicitly say what is that state you require. Especially if you will ever want to uninstall and then re-install nginx.

I assume you've already set up passwordless sudo so we don't need to supply the -K or --ask-become-pass flags.

$ ansible-playbook -i inventory.cfg nginx_install.yml -b

The -b tells ansible to become root on the remote server using sudo. The output looks like this:

PLAY [all] *******************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************
ok: [192.168.56.11]

TASK [ensure nginx is at the latest version] *********************************************************************
changed: [192.168.56.11]

PLAY RECAP *******************************************************************************************************
192.168.56.11              : ok=2    changed=1    unreachable=0    failed=0

Then we can try curl again. This time we get some HTML output that I have trimmed for brevity. Apparently the default page.

$ curl http://192.168.56.11

<!DOCTYPE html>
....

Uninstall Nginx

In order to allow us to see the full cycle we would like to check how to uninstall Nginx. This is the playbook we are going to use.

examples/ansible/nginx_uninstall.yml

---
- hosts: all
  tasks:
    - name: stop nginx
      service:
          name: nginx
          state: stopped
    - name: ensure nginx is not installed
      apt: name=nginx state=absent

Setting state=absent and running the playbook reported changed=1 but the web server was still installed and running. In order to fix that, first we need to stop the nginx service. That's what you see in the above playbook.

Configure Nginx

It is not enough to install Nginx we also need to configure it. This involves a couple of steps.

1) Creating a configuration file.

examples/ansible/static_site.cfg

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /home/foo/static-site;
        server_name _;
        location / {
                try_files $uri $uri/ =404;
        }
}

2) Putting it /etc/nginx/sites-available/.

3) Creating a symbolic link from /etc/nginx/sites-enabled/ to that file.

4) Creating a directory where we put the pages of the website. For simplicity we are going to create a static web site. Without an application behind it. Just an HTML file and an image.

Locally they look like this:

static-site-src/
   index.html
   ansible-logo.jpg

examples/ansible/static-site-src/index.html

<h1>Welcome to Ansible</h1>
<img src="/ansible-logo.jpg" />

On the servers I'd like to put them in the static-site directory of user "foo". That is in /home/foo/static-site.

5) Tell nginx to reload its configuration files.

The Ansible Playbook to set up Nginx

examples/ansible/nginx.yml

---
- hosts: all
  tasks:
    - name: ensure nginx is at the latest version
      apt: name=nginx state=latest
      become: yes
    - name: start nginx
      service:
          name: nginx
          state: started
      become: yes
    - name: copy the nginx config file and restart nginx
      copy:
        src: /home/foo/static_site.cfg
        dest: /etc/nginx/sites-available/static_site.cfg
      become: yes
    - name: create symlink
      file:
        src: /etc/nginx/sites-available/static_site.cfg
        dest: /etc/nginx/sites-enabled/default
        state: link
      become: yes
    - name: copy the content of the web site
      copy:
        src: /home/foo/static-site-src/
        dest: /home/foo/static-site
    - name: restart nginx
      service:
        name: nginx
        state: restarted
      become: yes

Then I run this command:

$ ansible-playbook -i inventory.cfg  --limit 192.168.56.11 nginx.yml

Note, this time I have not supplied the -b flag to become root. Instead for each step where I wanted the command to be executed with sudo I've added the become: yes parameter.

The output looked like this:

PLAY [all] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [192.168.56.11]

TASK [ensure nginx is at the latest version] ********************************************************
changed: [192.168.56.11]

TASK [start nginx] **********************************************************************************
changed: [192.168.56.11]

TASK [copy the nginx config file and restart nginx] *************************************************
changed: [192.168.56.11]

TASK [create symlink] *******************************************************************************
changed: [192.168.56.11]

TASK [copy the content of the web site] *************************************************************
changed: [192.168.56.11]

TASK [restart nginx] ********************************************************************************
changed: [192.168.56.11]

PLAY RECAP ******************************************************************************************
192.168.56.11              : ok=7    changed=6    unreachable=0    failed=0

Then I could go ahead and check

$ curl http://192.168.56.11

That printed:

<h1>Welcome to Ansible</h1>
<img src="/ansible-logo.jpg" />

When I visited the http://192.168.56.11/ from my desktop machine, it showed me the web page as I expected it, with the logo of Ansible.