As a Cloud Engineer, automation has become a part of my daily life. Automatically deploying Infrastructure using Code has become a safe and fast way to provision servers in the Cloud. Initially, it takes more time to configure the infrastructure as code, but it’s reusable and minimizes configuration errors by human mistakes.
What if we could apply the same principle to our local development environment? This guide will show you how to automatically set up your Macbook or Linux machine using Ansible and dotfiles.
Table of Contents
Ensure Apple’s command-line tools are installed:
The first step is to download Homebrew for your Mac:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Homebrew allows you to easily install packages and applications on your machine without having to go to the download page of the vendor to install it from there. An added benefit is that you can easily update the packages using a simple command like:
brew update && brew upgrade
Ansible is a tool that automates provisioning, does configuration management, and is being used widely in the Cloud.
It uses no agents and no additional custom security infrastructure, so it’s easy to deploy – and most importantly, it uses a very simple language (YAML, in the form of Ansible Playbooks) that allow you to describe your automation jobs in a way that approaches plain English.
So the next step is to install Ansible using Homebrew:
brew install python ansible
An important note when installing Python with Homebrew is that we need to change the PATH on our system for Python, otherwise MacOS will use the system default Python.
We want to avoid using the system default for many reasons, but the most important one is that it still comes with Python2.7 (which is deprecated).
Download the mac-dev-playbook
Ansible is the orchestration tool and uses Playbooks to record and execute Ansible’s configuration and deployment on the system.
Playbooks can be seen as an instruction manual at which the system is guided to execute the instructions that you have written. The benefit of using this is that you can apply the same set of instructions to different machines and expect the same outcome every time.
These Playbooks can be shared. So before we proceed with the installation, you need to clone or fork the mac-dev-playbook repository.
Configure your Homebrew packages
Every development environment is unique, so you can create a
config.yml that contains a list of packages and configuration settings that you want to apply to your environment. As an example you can have a look at the
default.config.yml in the root of the folder which contains a list of packages and configurations, as shown below:
--- downloads: ~/.ansible-downloads/ configure_dotfiles: true configure_terminal: true configure_osx: true configure_sudoers: false sudoers_custom_config: '' # Example: # sudoers_custom_config: | # # Allow users in admin group to use sudo with no password. # %admin ALL=(ALL) NOPASSWD: ALL dotfiles_repo: https://github.com/geerlingguy/dotfiles.git dotfiles_repo_accept_hostkey: true dotfiles_repo_local_destination: ~/Development/GitHub/dotfiles dotfiles_files: - .zshrc - .gitignore - .inputrc - .osx - .vimrc homebrew_installed_packages: # - ansible # Installed via Pip. - autoconf - bash-completion - doxygen - gettext - gifsicle - git - github/gh/gh - go - gpg - httpie - iperf - libevent - sqlite - mcrypt - nmap - node - nvm - php - ssh-copy-id - cowsay - readline - openssl - pv - wget - wrk homebrew_taps: - homebrew/core - homebrew/cask homebrew_cask_appdir: /Applications homebrew_cask_apps: - chromedriver - docker - dropbox - firefox - google-chrome - handbrake - licecap - sequel-pro - slack - sublime-text - transmit - vagrant # See `geerlingguy.mas` role documentation for usage instructions. mas_installed_apps:  mas_email: '' mas_password: '' osx_script: '~/.osx --no-restart' # Install packages from other package managers. # Note: You are responsible for making sure the required package managers are # installed, eg. through homebrew. composer_packages:  # - name: drush # state: present # present/absent, default: present # version: "^8.1" # default: N/A gem_packages:  # - name: bundler # state: present # present/absent/latest, default: present # version: "~> 1.15.1" # default: N/A npm_packages:  # - name: webpack # state: present # present/absent/latest, default: present # version: "^2.6" # default: N/A pip_packages:  # - name: mkdocs # state: present # present/absent/latest, default: present # version: "0.16.3" # default: N/A # Glob pattern to ansible task files to run after all other tasks are finished. post_provision_tasks: 
This playbook is pretty versatile and allows you to install Homebrew, Mac Application Store (mas) packages, composer, gem, npm, and pip packages.
Once you’ve created your own config file with your preferred packages, it’s time to add your own Dotfiles repository to set up custom configurations for your software.
So what are dotfiles? Dotfiles are text-based configuration files that store settings of almost every application, or tool that runs in your environment. In communities like Github, people share their application preferences so others can use them to set up their systems faster by restoring these “dotfile” configuration files. The biggest advantage is that you can backup your application preferences and make sure you’re always using the same preferences, irrespective of the machine that you’re using.
If you’re new to dotfiles you can read more about it in this helpful guide on dotfiles. I’ll also share a few links below which contain pre-configured dotfiles for your favorite tools:
Note: dotfiles contain personal preferences, so it’s good to review these files and apply changes where necessary before you copy them to your own repository
Once you have your own repository filled with dotfiles, you can update the
dotfiles_repo variable in the
config.yml with your own dotfiles repository. Below I’ve shown an example of what it looks like when I set up my own dotfiles:
configure_dotfiles: true dotfiles_repo_accept_hostkey: false dotfiles_repo_local_destination: ~/Github/dotfiles dotfiles_repo_version: master dotfiles_repo: [email protected]:dsteenman/dotfiles.git dotfiles_files: - .aliases.zsh - .aws - .eslintignore - .eslintrc - .fzf.zsh - .gitconfig - .gitconfig.user - .gitignore - .iterm2 - .macos - .starship - .zprofile - .zsh_plugins.txt - .zshenv - .zshrc
dotfiles_repo_local_destination is the location where ansible downloads your dotfiles repository. Remember that location, because that’s where you’ll manage changes in your dotfiles.
Ansible automatically creates symlinks of the dotfiles that you enabled in the parameter dotfiles_files and links them to your home folder on your Mac or Ubuntu machine. The advantage of this construction is that when you make adjustments in your dotfiles over time, it will automatically update the repository. You only have to commit and push the changes to update it remotely.
Run Ansible to install all the Homebrew packages that you’ve configured
Once the requirements have been fulfilled, we can proceed with the actual installation and let Ansible perform its magic!
In the root of the folder
mac-dev-playbook repository that you forked or cloned run the command
ansible-galaxy install -r requirements.yml to install the required ansible roles.
Now you can run the playbook and install your packages and dotfiles with the command
ansible-playbook main.yml -u [username] --ask-become-pass (substitute
[username] for your username). Enter your account password when prompted.
Your Macbook should be fully customized and ready for development! Having automated provisioning of your development machine is very useful if you use lots of different development tools, each with its own unique settings.
If you need to manage these tools then it’s a must to keep track of any changes in preferences. By using this playbook solution we save our configurations in Github. That way we have a backup and we’re able to reuse these settings irrespective of any machine we use.
Once you’ve set up your playbook, it takes approximately 30 minutes to install all the development packages and preferred configuration settings.