Unwrapping the Power of Ansible: A Practical Journey with Pi-hole (Part 4)

Translating Ansible theory into action through a guided playbook creation

Image by fabrikasimf on Freepik

Hello Muser!

In our last conversation, we demystified Ansible, the versatile IT configuration management tool. We dissected its core components, showing how they all come together to create an elegant, robust, and efficient IT automation framework.

This time, let's make things more tangible. Today, we are rolling up our sleeves and bringing Ansible theory to life with a real-world playbook, guiding you step-by-step through the process.

We'll create a comprehensive playbook that automates the installation and configuration of Pi-hole — a network-wide ad blocker that doubles as a DNS server. I've chosen Pi-hole because it's a powerful, yet light application that runs perfectly on small servers and even Raspberry Pis. It's a great example that demonstrates Ansible's power in a digestible package.

Let's dive right in!

Our playbook will incorporate all key Ansible components we've previously discussed. Don't worry, we'll also break down how each part correlates to our Ansible concepts. Along the way, we'll commit our progress to a GitHub repository, allowing you to keep track of each step.

----------

Make a Github Repository

First, let's set up our GitHub repository.

1. Log in to GitHub and create a new repository. For this demo, we'll name our repository "ansible-pihole".

2. Clone the repository to your local workstation. Replace [your-username] with your GitHub username:

git clone https://github.com/[your-username]/ansible-pihole.git
cd ansible-pihole

If this is feeling foreign to you, feel free to reference my series of posts on Git with the first part here!

----------

Setting up the Inventory

We'll begin by setting up our inventory. The inventory is a list of the nodes or "hosts" that Ansible will manage. For this demo, we'll manage one host.

Create a new file named hosts in the ansible-pihole directory:

nano hosts

Add your server's IP address to the file:

[pihole] # This is how you'll reference your hosts
192.168.1.10

This places our host in a group named "pihole". Save and close the file, then commit the file to Git:

git add hosts
git commit -m "Add Ansible inventory file"
----------

Update and Upgrade System Packages

For the "system" role, we'll update and upgrade all packages on the system. Create the respective directories and file:

mkdir -p roles/system/tasks
nano roles/system/tasks/main.yaml

Add the following tasks:

---
- name: Update all packages
  apt: # The apt module handles apt command line actions
    update_cache: yes

- name: Upgrade all packages
  apt:
    upgrade: 'yes'
----------

Install Dependencies

Pi-hole has some dependencies that need to be installed. For the "dependencies" role, create the respective directories and file:

mkdir -p roles/dependencies/tasks
nano roles/dependencies/tasks/main.yaml

Add the following tasks:

---
- name: Install dependencies
  apt:
    name:
      - curl
      - dnsutils
      - netcat
    state: present
----------

Install Pi-hole

Finally, for the "pihole" role, we'll install Pi-hole itself. Create the respective directories and file:

mkdir -p roles/pihole/tasks
nano roles/pihole/tasks/main.yaml

Add the following tasks to the file:

---
- name: Check if Pi-hole is already installed
  stat:
    path: /etc/.pihole
  register: pihole_directory

- name: Create /etc/pihole directory
  file:
    path: /etc/pihole
    state: directory
    mode: '0755'
  when: pihole_directory.stat.exists == false

- name: Create setupVars.conf file for Pi-hole configuration
  become: true
  copy:
    dest: /etc/pihole/setupVars.conf
    content: |
      PIHOLE_INTERFACE=eth1
      PIHOLE_DNS_1=8.8.8.8
      PIHOLE_DNS_2=8.8.4.4
      QUERY_LOGGING=true
      INSTALL_WEB_SERVER=true
      INSTALL_WEB_INTERFACE=true
      LIGHTTPD_ENABLED=true
      CACHE_SIZE=10000
      DNS_FQDN_REQUIRED=true
      DNS_BOGUS_PRIV=true
      DNSMASQ_LISTENING=local
      BLOCKING_ENABLED=true
  when: pihole_directory.stat.exists == false

- name: Install Pi-hole
  become: true
  shell: curl -sSL https://install.pi-hole.net | bash /dev/stdin --unattended
  when: pihole_directory.stat.exists == false

- name: Remove Web Admin Password
  become: true
  shell: echo "" | pihole -a -p

This uses

  • the stat module to check if Pi-hole is already installed

  • the file module to create the /etc/pihole directory

  • the copy module to set the contents of the /etc/pihole/setupVars.conf file

  • and the shell module to run the Pi-hole installation script & remove the web password if Pi-hole isn’t installed.

The register keyword stores the result of the stat command in a variable named pihole_directory, which we then use in the when condition. The become directives force the use of sudo for all the commands.

We now have three roles that we can include in our playbook.

----------

Adding Roles to the Playbook

Edit the pihole.yaml file:

nano pihole.yaml

And add the roles to the playbook:

---
- name: Install Pi-hole
  hosts: pihole # See the [pihole] section in hosts file
  become: yes
  roles:
    - system
    - dependencies
    - pihole

Save and close the file.

Then commit the changes to Git:

git add pihole.yaml roles/
git commit -m "Add roles to Ansible playbook"
----------

This playbook demonstrates Ansible's key concepts:

  • Inventory: We defined a single host that Ansible will manage.

  • Roles: We divided our playbook into three roles to modularize the Pi-hole installation process.

  • Tasks: Each role performs a task using Ansible's modules.

  • Playbooks: We defined a playbook to orchestrate the entire operation and use our roles.

  • Modules: We used the apt, stat, and command modules to manage packages, check the state of files, and run shell commands on the server.

Additionally, we committed our playbook to a Git repository on GitHub at each step of the process. This allows us to track changes to the playbook and collaborate with others.

In the next post, we'll look at how to run this playbook and what to expect!

Stay tuned, and happy cooking with Ansible!

Enjoyed this post? Don't miss our next one where we'll explore different tools available for configuration management. Subscribe now and share with your colleagues who might find this useful!

Have any questions or experiences to share about Ansible Playbooks? Leave a comment below. Also, your comments help me understand what you're curious about, and what topics you'd like to see covered next! I'd love to hear from you!

Keep learning and keep growing,

Darrell

Reply

or to participate.