A beginner's guide to auto-configure a Linux machine with Ansible

Networking, Cloud & Automation
5 min readAug 5, 2021

Do you want to configure a Linux machine automatically in a couple of minutes?

In this third part of this post series, we cover application deployment with Ansible, to automate installing and configuring the software required to make our environment available for use.

The overall goal is to get several cloud resources automatically provisioned and configured to deliver a reproducible Linux environment that supports a use case, which in this case is creating virtual network topologies for lab testing. This is a four-part blog post series that covers:

  1. Use-case description
  2. Automating Infrastructure Provisioning
  3. Delivering an Application Deployment Environment
  4. Releasing Cloud resources
original artwork Lenny Kuhne

Target Environment

We typically think of platform as a service (PaaS) for application deployment, where a third-party vendor provides an environment that bundles together network resources, databases, and software dependencies to run an application. However, you can alternatively take care of these yourself, which is what we aim to automate and present in this blog post.

While we are automating the installation and configuration of a software mix that might be specific for this scenario, the automation patterns are the same for other software combinations.

The goal is not to cover every aspect of Linux System roles, for example, but to provide a succinct list of Ansible tasks that can deliver a Linux environment to fulfill a particular purpose.

If you just want to see the code, you can go to the repository. Otherwise, here is the description of the Ansible tasks executed for this example.

Customize the Linux environment

We start with a couple of cosmetic examples. All tasks included in here support two different Linux distributions: Ubuntu and Fedora.

Configure the hostname

We use the hostname Ansible module to configure the name of the system. We take the hostname value in the Ansible inventory via the magic variable hostvars that has all the variables assigned to hosts.

Change the Bash prompt

Some people prefer to customize their setups using dotfiles to get a consistent look and feel across their systems. You can copy these files over using the Ansible copy module, and source them in either .bashrc or .bash_profile for example.

We only show a simple example to change the Bash prompt by copying over a file with the prompt variable (PS1) details to /etc/profile.d. This is enough for Fedora, however for Ubuntu, we need to source this file explicitly, hence we include an extra task with a conditional clause (when) to only execute it for hosts running that Linux distribution.

Installing Packages and Libraries

Install packages

The variable common_software provides a list of packages that are common across the Linux distributions options. You can overwrite its value — using Ansible Variable Precedence — with any list of packages of your preference.

Then the package Ansible module installs these.

The variable base_software provides a complimentary list of distribution-based packages. The facts variable ansible_distribution_file_variety determines which packages to install: For either Debian (Ubuntu) or RedHat (Fedora).

Install libraries

Following the same pattern, we can install Python libraries, for example, by listing them on a variable which you can overwrite (python_libraries).

The pip Ansible module takes care of installing these Python libraries.

Install special software

We can’t install every software application with a package manager, or maybe you prefer a customized installation. In this opportunity, we install a programming language (Go), Docker to run containers, and Containerlab to create virtual network topologies.

Go

The following tasks automate the instructions to install Go, making it a consistent installation across Linux distributions.

It installs Go Version (go_version) 1.16.5 by default. It gets the archive file from the download URL (go_download_url) https://golang.org/dl/go{{ go_version }}…. After downloading the archive file with the Ansible module get_url, it unarchives to /usr/local with the unarchive Ansible module.

Docker

Docker provides installation guides for Fedora and Ubuntu. They have different dependencies and package repositories that need to be added to the target system. In the code snippet below, we see the instructions that are specific to Fedora. The rpm_key Ansible module installs the GPG key of the repository, and then the Ansible module get_url adds the Docker repository for the same Linux distribution.

With the distribution-specific tasks out of the way, we can proceed with the installation tasks that are common for Fedora and Ubuntu.

Last, but not least, a trick to manage Docker as a non-root user.

Containerlab

The installation steps are very similar to what we did for Go and are Linux distribution agnostic. We additionally create a symlink with the file Ansible module to get a shorter executable name (clab).

Advanced Linux tasks

Some tasks might make changes that require a reboot. Following an example of how to handle these.

Check cgroups version

We want to make sure we run cgroups v1, as some containers we need to run only support this version. However, Fedora31+ comes with cgroups v2 as the default, so we revert Systemd configuration to use cgroups v1 with the next task using the command Ansible module.

After making the change, it notifies the handler Reboot machine to reboot the machine with the reboot Ansible module, and it resumes the Playbook execution when the managed node comes back online.

Execution

As stated in the first part of this series, to run this example you need to have Ansible installed on your computer and follow these steps to provision the testbed:

1. Clone the repository with git clone https://github.com/nleiva/aws-testbed.git

2. Make your AWS account credentials (AWS_ACCESS_KEY and AWS_SECRET_KEY) available as environment variables (export).

3. Run the Playbook: ansible-playbook create-EC2-testbed.yml.

Logging into the VM

The execution logs provide instructions to connect to the VM at the end. Something along the lines ssh -i testbed-private.pem fedora@ec2–54–175–179-XXX.compute-1.amazonaws.com.

ansible-playbook create-EC2-testbed.yml -v

<snip>

TASK [Print out SSH access details] ***********************************************************************************************************************************************************
ok: [testbed-fedora34] => {
"msg": "ssh -i testbed-private.pem fedora@ec2-54-175-179-XXX.compute-1.amazonaws.com"
}

RUNNING HANDLER [configure_instance : Reboot machine] *****************************************************************************************************************************************
changed: [testbed-fedora34] => {"changed": true, "elapsed": 22, "rebooted": true}

PLAY RECAP ************************************************************************************************************************************************************************************
localhost : ok=25 changed=7 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
testbed-fedora34 : ok=33 changed=22 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Running virtual networks

Once in the VM, you can run any of the topology examples in the lab folder. Change directory and run the clab command, pointing to the topology file.

cd lab/frr
sudo clab deploy --topo topology.yml
sample lab topology

To access router1 for example: docker exec -it clab-mylab-router1 vtysh.

More details in the lab readme file.

Conclusions

Ansible is a flexible and powerful platform that can perform a myriad of tasks on Linux systems that enable us to automate the delivery of environments that are ready to serve a purpose.

In the next post, we go through the details of how we can automatically release all the resources we just created. Stay tuned!

--

--

Networking, Cloud & Automation

Proud dad working at Red Hat (CCIE, CCDE). Sharing content I create about: networking, automation, programming, golang, ipv6, and open source software.