How to Configure Remote Linux Servers Using Ansible
Tags: ansible, devops, linux
Published: 2022-10-18 09:04:55

Imagine that you were asked to install a piece of software (e.g apache2) on 250 different Linux servers. 

How would you go about it?

Well, you could decide to ssh (open a secure connection) into the servers one after the other, and install the software, but that would take an awefully long time to complete.

A more efficient approach will be to use a configuration management tool like Ansible to automate the process.

In this tutorial, you will learn how to use Ansible to target your servers and:

1. Install Apache web server and
2. Change the default timezone of your servers

Here, we will use two servers, but the procedure is similar when configuring 250 (or more) servers.

### Prerequisites:
- An AWS account
- A linux machine (could be a VM)

Let's go...

From an Architectural standpoint, this is how Ansible works:
![Ansible Architecture](https://res.cloudinary.com/practicaldev/image/fetch/s--N7bVEnyF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/33ympesmiwld52do90ji.png)


### Step 1: Install Dependencies
For Ansible to function properly you need to ensure you have Python and softwares-properties-common installed. Run the following commands to install them:

```
$ sudo apt install software-properties-common
```

```
$ sudo apt install python3
```

And then install ansible:

```
$sudo apt install ansible
```

Confirm Ansible installation:

```$ ansible-playbook -v```


### Step 2: Provision servers on AWS
For this tutorial, I will provision two Ubuntu servers(EC2 instances on AWS). If you don't already know how to do that, follow the instruction [here.](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EC2_GetStarted.html)

> **Important:** 
When you provision your servers, ensure that you download the privatekey file(the file with the ".pem" extension), and that you note down the *public ip addresses* of the provisioned EC2 instances. 
>Also, for ease, I like to move my privatekeys to my ~/.ssh/ folder. So mine is located at **~/.ssh/Davi-test.pem**

Also ensure that your security group allows ssh and web traffic into the server.


![security group settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1d381ovmhty8sv5l4fn.png)


### Step 3: Setup host-inventory
Create a directory for my this project

```
$ mkdir ansible_proj && cd ansible_proj
```

Then create your host-inventory file:

```
$ touch host-inventory
```

Next, using your favourite text editor (vi, nano or even VScode) add the ip addresses (or hostnames) of your servers. Like this:

![host-inventory image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ybl1pak7bz4jybrp2sg.png)
and save.

You would notice that I grouped all my servers under "webservers."

Grouping targets like this makes it easy to separate different groups of machines and this often comes in handy.

Next, you need to tell ansible how to locate your host-inventory file. If you don't, ansible will try to get it from /etc/ansible/hosts.

But since we have the file at ~/ansible_proj, go ahead and do:

```
export ANSIBLE_INVENTORY=~/ansible_proj/host-inventory
```
and we're ready to go.


### Step 4: Create the Ansible Playbook
```touch test.yaml```

And then, using your favourite text editor, paste in the following code in the test.yaml file:

``` yaml
---
  - name: Setup Web Server
    hosts: webservers
    become: true
    become_method: sudo
    tasks:
      - name: Install Apache Server
        apt: name=apache2 state=present

      - name: Set timezone to Africa/Lagos
        timezone:
          name: Africa/Lagos
```

and save.

In the yaml, we target the webserver group using ```hosts: webservers```, and we describe 2 tasks, using the apt and timezone modules respectively.


### Step 5: Test the connection
>Before proceeding with this step, ensure that your $ANSIBLE_INVENTORY variable is set in your current bash as describe previously.

Based on the location of the key you got earlier, you will need to run:
```
$ ansible --private-key PRIVATEKEY_FILE -u USER HOST_GROUP -m ping
```

I want to connect as the "ubuntu" user and target the servers under "webservers" host group. So that will be:
```
$ ansible --private-key ~/.ssh/Davi-test.pem -u ubuntu webservers -m ping
```

![ping success](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4h53w76woieyookdfqq5.png)


### Step 6: Test the Playbook
Before we run our ansible playbook, it is important to test using the "--check" flag along with the ansible-playbook command. Like this:
```
$ ansible-playbook --private-key ~/.ssh/Davi-test.pem -u ubuntu test.yaml --check
```
The output should look something like this:
![ansible playbook check successful](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etuh1y6wdbm283ppll75.png)

Before you go ahead to finally run the playbook, ssh into any of the servers and check whether apache2 is running and confirm the timezone. If you don't know how to ssh into your server, go [here](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html).

I checked inside one of my servers, and here is what I got:
![image showing apache2 is not installed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tasmhxow7ljra8l0pidh.png)

Apache2 was not not installed and timezone was Etc/UTC.

Now let's run the playbook:


### Step 7: Run the Ansible playbook

Apply the intended changes to the servers by running the command we used to check, but without the "--check" flag. i.e
```
$ ansible-playbook --private-key ~/.ssh/Davi-test.pem -u ubuntu test.yaml
```

If there are no errors and everything goes well, then ssh into any of the servers and try check apache2 and timezone again. Here's what I got:
![Ansible configured timezone and apache2 successfully](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/385an15sftkie3fxxxuu.png)

Awesome!, right? Ansible did it's thing again!.

Before you leave, here's a little exercise:
>Try adjusting the timezone to a different one within the test.yaml and run it again to see what happens.


### Step 8: Clean up
Finally, if you don't need the servers for other reasons, ensure that you terminate them from the AWS console to avoid racking up unnecessary bills.

![ec2 instances terminated](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1z6jyee07x3zuoec2hr.png)


### Conclusion
Hey,

I hope you enjoyed this tutorial, and I hope that you learned a thing or two about Ansible. 

As of the time of writing this tutorial, I just got started with Ansible myself, but I'll be using it a lot from now on because I think it's an awesome tool. 

If you have any questions, or comments, you can leave them below, or reach out to me on [LinkedIn](https://www.linkedin.com/in/davidomokhodion). Till we meet again...

Stay awesome!
~ David Omokhodion