I’ve been managing servers for some years, mostly for simple client web site deployments and personal use (read static content, Wordpress or drupal). Cloud VPS companies like Linode or Digital Ocean make this cheap and desirable, specially if one likes to setup and maintain his own machines.

Setting up a new Linux server can be fun in the beginning and a great learning experience, but after a while it gets repetitive and boring. Moreover, when administering more than one server, one starts to think about automation, how beautiful it should be (even if in practice I’ll spend a lot of time learning it). For provisioning shell scripts work, and it is a base skill that every so called sysadmin/developer/kid-with-a-server should have. But we can do better.

I tried some of the more well known provisioning tools such as Puppet and Salt. These are very interesting and robust, and (at least Puppet) widely employed. However, they seem very complex for simple use cases, configuration is not so trivial, push you to rely on a master provisioning node and, childish point, provisioning language syntaxes are ugly and confusing.

Then i found Ansible. It’s written in Python, uses YAML for provisioning tasks description, Jinja2 for templatting configuration files (and more) and only needs a client SSH machine to function. This is not intended to be a tutorial or whatever about Ansible, its documentation is awesome. Ansible playbooks are really easy to understand, and roles provide a very nice way to organize reusable ansible code.

The following example contains part of my role to install Nginx. First the tasks:

- name: Installs nginx ppa
apt_repository: repo=ppa:nginx/stable state=present
- name: Installs nginx package
apt: name=nginx-extras state=latest
- name: Remove nginx default site
file: path=/etc/nginx/sites-enabled/default state=absent
notify: Restart nginx # See bellow for the definition
# Bellow variables come from specific host / definition files:
- name: Create site directories for defined sites
file: state=directory owner={{item.owner}} group={{item.group}} path={{webserver_sites_root}}/{{item.directory}}
with_items: webserver_sites
# Opens 80 and 443 ports using UFW
- name: Opens http and https ports
ufw: rule=allow port={{item}} proto=tcp
- http
- https

And now the handler to restart nginx, its only executed once, even if more than one task notify it:

- name: Restart nginx
service: name=nginx state=restarted

For this site configuration, I defined in a host variables file the following:

- name: www.ruiandrebatista.com
directory: www.ruiandrebatista.com/htdocs
owner: ragb
group: www-data

Probably the hardest part to get a long is YAML’s syntax (which is in the end very readable).

For a more complex example, I created a role to automate MySQlL backups that you can find on github. For lots and lots of more already made roes check ansible Galaxy. This project contains a full-fledged and secure mail server deployment using ansible (mail servers are hard, believe me) which I adapted for my own needs.

And that’s it for now. Hope you will check Ansible one of these days.


comments powered by Disqus