Ansible

If you are looking to automate your OS configuration and application deployment for virtual machines labs, onboarding computers or disaster recovery, consider Ansible.
How does Ansible work?

Ansible uses YAML files as playbooks that provide instructions on how to deploy to your systems. The deployment is done through SSH (for Linux) or WinRM (for Windows) which needs to be setup beforehand.
Walkthrough: Deploying my home server
Let's take a look at a simple example of installing OpenVPN server in my home server (taken from my ansible-home-server repository).
The project directory is as follows:
- inventory.yml
- site.yml
- roles
- mainservers
- tasks
- main.yml
- openvpn.yml
- ...
- handlers
- main.yml
- defaults
- main.yml
- vars
- main.yml
- files
- openvpn
- ...
inventory.yml
The inventory file contains a list of hosts (or control nodes) that I am going to deploy to. The main01 host is grouped under myserver.
By default, Ansible looks at your ssh-agent to search for any SSH keys, unless the directory of the key file is specified, or password authentication is used.
myserver:
hosts:
main01:
ansible_host: 192.168.10.129
ansible_port: 22
ansible_ssh_private_key_file: ~/.ssh/ansible
site.yml
The site file specifies the roles of each host, where each role consists of tasks, handlers, defaults, vars and files. Roles can be reused on multiple groups.
- hosts: myserver
roles:
- mainservers
In each folder (tasks, handlers, defaults, vars, etc.), there is a main.yml file that Ansible will first look into.
mainservers/tasks
Tasks define what are the actions to be applied to the hosts.
I usually refer to the Ansible Documentation to find a specific action (e.g. install apt package, starting a service, etc.)
main.yml
I organised my tasks into different files for easier readability.
- name: Update and upgrade apt packages
apt:
upgrade: yes
update_cache: yes
cache_valid_time: 86400
- name: Setup openvpn
include_tasks: openvpn.yml
openvpn.yml
Tasks can also be added with conditionals (when) from registered results (register).
I have also declared variables ("{{common name}}") and handlers (notify), which will be explained below.
- name: Create new CA
expect:
command: /etc/openvpn/easy-rsa/easyrsa build-ca nopass
responses:
'Common Name': "{{ common_name }}"
- name: Copy server.conf to /etc/openvpn
copy:
src: openvpn/server.conf
dest: /etc/openvpn/
register:
server_conf_copied
- name: Enable IP forwarding and reload
ansible.posix.sysctl:
name: net.ipv4.ip_forward
value: '1'
sysctl_set: true
state: present
reload: true
notify:
- Start OpenVPN service
when: server_conf_copied is succeeded
mainserver/handlers
Similar to tasks, handlers are executed when a task has changed (modified the system).
A common use case is starting/restarting a service after an installation/update.
- name: Start OpenVPN service
systemd_service:
state: started
name: openvpn@server
mainserver/defaults
As I have multiple copy tasks with customised settings (changing file owner and permissions), I can override the default settings of a task in Defaults.
ansible.builtin.copy:
owner: testuser
group: testuser
mode: 0400
mainserver/vars
Variables can be used for easier modification and reusability (e.g. changing directory, secret key, etc.). For assigning different values for different machines, use group_vars.
# OpenVPN
common_name: 'testuser' # CA Common Name
mainserver/files
Files can be used to copy files from the ansible host (or control node) to your hosts.
Deploying to my host
After completing my playbook, I generated a ssh key using ssh-keygen, then copy the key to my host using ssh-copy-id.
index@ubuntu:~$ ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/index/.ssh/id_ed25519): ansible
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ansible
Your public key has been saved in ansible.pub
index@ubuntu:~$ ssh-copy-id -i ~/ansible [email protected]
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/index/ansible.pub"
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed
[email protected]'s password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh '[email protected]'"
and check to make sure that only the key(s) you wanted were added.
Finally, run the playbook using ansible-playbook:
index@ubuntu:/home/index/ansible$ ansible-playbook -i inventory.yml site.yml --ask-become-pass
BECOME password:
PLAY [main]
*********************************
TASK [Gathering Facts]
*********************************
ok: [main01]
TASK [mainservers : Update and upgrade apt packages]
*********************************
changed: [main01]
...
RUNNING HANDLER [mainservers : Start OpenVPN service]
*********************************
changed: [main01]
PLAY RECAP
*********************************
main01 : ok=16 changed=14 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Now, OpenVPN server is installed in my home server!
Summary
In summary, you have seen an example of using Ansible to install a OpenVPN server in my home server.
An ansible playbook usually consists of:
- inventory.yml: List of hosts
- site.yml: Specifies roles of host group
- role/tasks: Actions be applied to the hosts
- role/handlers: Executed when a task has changed
- role/defaults: Override default settings of a task
- role/vars: For easier modification and reusability
- role/files: Copy files from ansible host to hosts
There are other components in Ansible, but this is a simple example to get you started 😉
Hope you learned something new!