Written by Alex de Sousa
When developers get tired of configuring again and again our machines, we tend to create a dotfiles repository.
Dotfiles are commonly used for storing user preferences or preserving the state of a utility, and are frequently created implicitly by using various utilities.
It all starts with a small repository that contains configuration files for common tools e.g. .zshrc
, .vimrc
, etc. However, every time we configure a new machine, we need to copy those files by hand.
We pride ourselves with our ability to automate any task. Therefore, the next logical step for a dotfiles repository is to create a "small" shell script for automating tool installation and machine configuration.
All is well at first, but that "small" script ends up being hundreds of lines long and hard to maintain.
Ansible is an configuration management tool. It provides its own language to describe system configuration.
This is not a new idea, but it feels like one: configure your own machine the same way you configure your servers... With Ansible.
Note: I'm using Debian throughout this tutorial, though the same can be accomplished with any architecture and operative system as long as Ansible is available for it.
For installing and configuring stuff with Ansible, we need to first install Ansible. We can use a small shell script to accomplish this. Some of the variables like $HOSTS
and $PLAYBOOK
will make sense in the next sections:
#!/usr/bin/env bash
set -e
# Dotfiles' project root directory
ROOTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Host file location
HOSTS="$ROOTDIR/hosts"
# Main playbook
PLAYBOOK="$ROOTDIR/dotfiles.yml"
# Installs ansible
apt-get update && apt-get install -y ansible
# Runs Ansible playbook using our user.
ansible-playbook -i "$HOSTS" "$PLAYBOOK" --ask-become-pass
exit 0
Running the previous script as our sudoer user will effectively install Ansible and run our main playbook with all our roles.
Playbook: A file that defines several tasks to be executed in a target machine. Role: Organizes multiple, related tasks with the data needed to run those tasks (variables, files, templates).
Once we have our bootstrap script in place, we can start writing Ansible configuration files.
In our dotfiles repository, our target is our own machine. This is very easy to define in our hosts
file (with local connection so it doesn't require an ssh key):
# file: hosts
[local]
localhost
[local:vars]
ansible_connection=local
Note: In our
bootstrap.sh
script, this file is found in the variable$HOSTS
.
Then we need a playbook that lists every role we want to deploy and configure in our machine.
# file: dotfiles.yml
- name: Set up local workstation
hosts: local
roles:
- role: zsh
tags:
- zsh
In our example, we'll install zsh
role.
Note: In our
bootstrap.sh
script, this files is found in the variable$PLAYBOOK
.
In general, our folder structure would look something like:
â”” dotfiles
- bootstrap.sh
- dotfiles.yml
- hosts
â”” roles
â”” zsh
â”” files
- zshrc.link
â”” tasks
- main.yml
The following would be our zsh
role tasks for:
zsh
..zshrc
configuration file to our home folder.Finally, we can run our script:
~/dotfiles $ chmod +x bootstrap.sh
~/dotfiles $ sudo bootstrap.sh
This script will:
zsh
.There are more cool features you can use to customize your system using Ansible. You can check my dotfiles repository if you want to see a fully working example.
Additionally, if you want to know more about Ansible, you can check this amazing tutorial.
I hope you find this useful :)
Happy coding!
Alex de Sousa
Elixir alchemist. Tech enthusiast.