February 15, 2015

Ansible: Roles

Orchestrate more complex configurations with Ansible.

Use Ansible roles to orchestrate more complex configurations.Let's create a new directory named nginx, which will be a Role. Then we'll create the basic structure of a Role:

mkdir -p roles/nginx
cd roles/nginx
mkdir files handlers meta templates tasks vars

Meta

We'll start with the meta information:

This meta/main.yml file creates a dependency on the "sslcertificates" role:

---
dependencies:
 - { role: sslcertificates }

However we don't have a dependency currently, so our meta data file looks like this:

---
dependencies: []

Files

I grab Nginx configuration from H5Bp.

cd roles/nginx/files

# Get the H5BP Nginx repository
wget https://github.com/h5bp/server-configs-nginx/archive/master.zip

# Save the "h5bp" directory and discard the rest
unzip master.zip
rm master.zip
mv server-configs-nginx/h5bp ../
rm -rf server-configs

Now we have files roles/nging/files/h5bp.

Variables

Next we'll add some variables to be used in this role. Create roles/nginx/vars/main.yml.

---
domain: serversforhackers.com

Templates

We'll create an Nginx configuration file using templates. Templates let us create a file which contain variables, loops and other items as allowed in Python's Jinja2 template engine.

I create file roles/nginx/templates/serversforhackers.com.j2 to create the Jinja2 Nginx configuration template for the serversforhackers.com site.

server {
    listen 80;
    server_name *.{{ domain }};
    return 301 http://{{ domain }};
}

server {
    listen 80 default_server;

    root /var/www/{{ domain }};
    index index.html index.htm;

    access_log /var/log/nginx/{{ domain }}.log;
    error_log /var/log/nginx/{{ domain }}-error.log error;

    server_name {{ domain }};

    charset utf-8;

    include h5bp/basic.conf;

    location /favicon.ico { log_not_found off; access_log off;}
    location /robots.txt  { log_not_found off; access_log off;}

    location / {
        try_files $uri $uri =404;
    }
}

Handler

Create some handlers. Create file roles/nginx/handlers/main.yml:

---
- name: Start Nginx
  service: name=nginx state=started

- name: Reload Nginx
  service: name=nginx state=reloaded

Tasks

Finally we put everything together in our tasks file. Create file roles/nginx/tasks/main.yml:

---
- name: Add Nginx Repository
  apt_repository: repo='ppa:nginx/stable' state=present

- name: Install Nginx
  apt: pgk=nginx state=latest update_cache=true
  notify:
   - Start Nginx

- name: Add H5BP Config
  copy: src=h5bp dest=/etc/nginx owner=root group=root

- name: Disable Default Config
  file: dest=/etc/nginx/sites-enabled/defalt state=absent
  notify:
    - Reload Nginx

- name: Add SFH Site Config
  template: src=serversforhackers.com.j2 dest=/etc/nginx/sites-available/{{ domain }} owner=root group=root

- name: Enable SFH Site Config
  file: src=/etc/nginx/sites-available/{{ domain }} dest=/etc/nginx/sites-enabled/{{ domain }} state=link
  notify:
    - Reload Nginx

Test, Debug and Run Role

Finally we can try running this Role. In the same directory as the roles directory, create a new yaml file such as run.yml. In this video, I use file nginx.yml since we only use the Nginx role:

---
 - hosts: web
   sudo: yes
   user: root
   roles:
    - nginx

We can run this Playbook like so:

ansible-playbook --private-key=~/.ssh/id_ansible nginx.yml

Let's do a syntax check, which you should run before trying out a playbook or role:

ansible-playbook --syntax-check nginx.yml

We get some errors in the video, however I've corrected all of them in the above tasks/main.yml file.

Watch the video for some debugging steps I do in testing that everything on the server is working!

All Topics