Since the moment i started using SSH to manually configure my servers i noticed the issues with this approach. I was going over and over to my servers to perform the same tasks.

If i am doing the same thing every time, why can’t i just write a script to automate the process?

Well, you can always create bash scripts, however writing stable scripts with bash is not trivial, as there are a lot of situations that can arise and you would need to take into account to avoid doing what you intended to avoid by writing those scripts: SSH into your server to manually fix things.

If bash is not a good option for automation, what can i do instead?

Meet Ansible. From their docs:

Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.

One of the most important concepts in Ansible is idempotency. From the ansible glossary:

The concept that change commands should only be applied when they need to be applied, and that it is better to describe the desired state of a system than the process of how to get to that state. As an analogy, the path from North Carolina in the United States to California involves driving a very long way West, but if I were instead in Anchorage, Alaska, driving a long way west is no longer the right way to get to California. Ansible’s Resources like you to say “put me in California” and then decide how to get there. If you were already in California, nothing needs to happen, and it will let you know it didn’t need to change anything.

Most of Ansible core modules are idempotent, so we can just describe the state we want for the system, feed it to a system on any state and Ansible will change it to satisfy our demands.

Ok, ok, i got it. How do i get started with Ansible? Will it take a lot of work to configure?

Unlike other automation tools like chef and puppet, Ansible does not require an agent installed on the target machines, so to get started all we need is to be able to connect using SSH.

To start working with Ansible, we need to install it first. It is a python module, and the recommended way to install it is with pip/virtualenv because system packages may be outdated:

pip install ansible

Ansible requires an inventory file to work. By default it is stored in /etc/ansible/hosts, but we can put it anywhere and use the -i flag to tell ansible where to find it. The syntax for the inventory file is pretty straightforward:

[my-servers]
192.168.0.1

[my-servers:vars]
server_name='server_name.xyz'
ansible_ssh_user=ubuntu
ansible_ssh_private_key_file=some/path/to/a/key/file.pem

It describes groups, and other things related to groups, like variables (vars). You can change the IP for a domain name or list several servers there. It can be loaded dynamically when you are using cloud providers like AWS.

We can check if everything is ok by using the ping module:

$ ansible my-servers -i my-inventory-file -m ping

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

If it is not a success, check that your settings are correct.

I can do a ping with bash, with even less lines. Is that all Ansible can do?

Of course not. The ping module is a way to verify that Ansible can communicate to your instances, not just a plain ping like the one in bash.

Once that everything is in place we can start doing more complex things. For example let’s install redis-server on some ubuntu server:

$ ansible my-servers -i my-inventory-file -m apt -a "update-cache=yes name=redis-server state=present" -b
192.168.0.1 | SUCCESS => {
 "cache_update_time": 1453490171, 
 "cache_updated": true, 
 "changed": true, 
 "stderr": "", 
 "stdout": "..."

I used the module apt (-m) to perform the installation. There are other modules for other distributions(yum, pacman, etc).
The flag -b tells Ansible to use sudo for that operation, because it requires more privileges than normal user. It is a shorthand for becomes. Check the docs for Ansible if you need a password for that.
Finally the -a flag is used to pass arguments to the module. In this case we tell it that we need to refresh the cache and we need a package named redis-server installed (present). We can also use absent or latest for the state argument.

Notice the “changed” key on the response. It let’s you know if the command actually modified something. If you run the command a second time, changed will be equals to false, because Ansible won’t install anything. If something is on the required state, there is no need to!

Well, it does look easier and faster than plain bash now, but how can i create “ansible scripts”?

There is no such thing as “ansible scripts”. Instead we use the concept of playbooks, a file with a bunch of plays that we can put together to orchestrate about anything we need on our servers. Ansible playbooks use yml syntax and jinja2 templates, so you could read a little about the to make your life easier.

Playbooks are a topic that could cover a mid sized book easily, so i won’t even try to cover it here, instead i will leave a simple example that installs some system packages and copy files from my computer to the server.

Create a file named playbook.yml and put this inside:

---
- hosts: all

  pre_tasks:
    - name: Update apt cache if needed
      become: yes
      apt: update_cache=yes cache_valid_time=86400
  tasks:
    - name: Install redis.
      become: yes
      apt: name=redis-server state=present
    - name: Install system packages.
      become: yes
      apt: name=mysql-server state=present
    - name: Copy some file to server
      copy: 
        src: ~/local/path/to/file
        dest: /some/path/on/server

To run the playbook we just need to use the ansible-playbook command:

ansible-playbook playbook.yml

That playbook may not be very useful, but should serve as a basis if you are interested in Ansible by now.

I think that i may give it a try, but can Ansible do anything else?

Ansible has hundreds of modules and a lot of features. You may be interested in ansible-vault, which let’s you encrypt files that can hold sensitive variables that you want to use on your playbooks, allowing you to save those files in your repositories safely.

You can explore the great collection of Ansible’s modules. You can use git, create configuration files on the fly, use handlers for your tasks, etc.