Ansible: Automating server initialization tasks

Now that we have ansible working, we can do some housekeeping of the server. I took most of the playbook(with some modifications) from @jigarwala from his repo at github. He has also written a blog on the topic on medium

The kind of tasks that come under this are:

  • Update the apt package cache listing and installing some useful packages
  • Setting the hostname of server
  • Setting the locale & timezone
  • Tightening the SSH Server(disabling root login, disabling password login, enabling strict mode, etc)
  • Adding a user, giving him superuser access

Terraform already does add a user & grant ssh, but I am repeating that in ansible so that all servers, including those not terraformed, have the same user in the end.

The changes as usual is in this pull request, and the final code base is this.

Ansible Folder Structure

The Configuration of ansible can be broadly split into 3 sections

  1. Inventory - The list of servers that ansible provisions
  2. Roles - A self-contained list of instructions & assets that can configure a functionality or aspect of the server
  3. Playbooks - Mapping which roles to apply on which subset of the Inventory

All Ansible configuration is usually done with YAML syntax, except the inventory file which is usually done INI format.


The simplest example of an inventory file just contains the ip address of the server, like so

But inventories can be hierarchical, with aliases to servers and more tags to specifically configure each server. nsible has very clear documentation at Inventory Intro.

In our case, all that really matters here is that we are specifying 2 global variables.


This is later used within ansible configuration to set the user in the server and the ssh authorized_keys. Make sure to replace those if you are using my repository.


Right now, the playbook is really quite simple and just refers to common role that we defined. The file ansible/playbooks/provision.yml is as follows

- name: provision cloud resources
  hosts: all
    - role: common 
      become: true  
        - role-common

All Ansible tasks have a name, which hold no significance to the machine. It is purely used for logging, and in the rare occasion, start executing at a given task

The hosts map to the keys in Inventory. In this case, all refers to all the entries in the inventory, as you might have guessed.

Roles is an array which refers to the roles present in ansible/roles directory and the order in which to execute them. become allows the task to use privilege escalation(using sudo, or other native implementation).

Tags are just names that can be used to execute subsets of tasks within the playbook and like name, have no inherent meaning to ansible.


Roles contain the meat of the automation config. The folder structure has a pre-defined list of sub-folders out of at least one should be present. Ansible, again contains the full documentation on each of these folder here.

  • tasks/
  • handlers/
  • library/
  • files/
  • templates/
  • vars/
  • defaults/
  • meta/

Out of the above, we will be using

TasksMain list of tasks that the role executes
TemplatesAny template files that are to be copied over to the server
VarsRole-specific Variables
HandlersA special type of task that can be triggered to run after tasks(for example to reboot the system after upgrade)

In all the folders, main.yml will be the file that is picked up by ansible. Any other file in the folder must be included. In tasks folder, other files can be included with import_tasks.

Further Exploration

Explaining the structure like this will not fully make it clear how this all comes together.

I highly recommend that you clone the repo and view the ansible/roles/common folder. Its likely that by the time you read this, there are changes that make the code unrecognizable. In that case, use this

git checkout 82daffbbb9af07a2ade4e83e56cf31f8bb113a5e

Or, you can choose to view the pull request online.

Next Steps

In the next chapter, I will be installing tailscale, and configure it to connect all my instances together.

Project Page

Related Posts

2 thoughts on “Ansible: Automating server initialization tasks

Leave a Reply

%d bloggers like this: