An Introduction to Web Server Provisioning: Configure and Set Up Your AWS VM Automatically Using Ansible
In this article, we will explore ways to automate the configuration of our Cloud VM. Setting up our machine in the Cloud can quite be a pain in the ass, especially if it’s done manually. Today, we will see how we can use Ansible to automate the configuration process so that it can be done in a single command. This is going to be especially useful for developers who wish to automate their deployment process in order to accelerate shipping high-quality software.
Software engineers are nowadays adopting more agile methods for shipping software. The reason for that is the better quality of software due to the increasing number of production builds. When a fully working version of a web application is deployed on a regular basis, it becomes easier:
- for developers to spot bugs and resolve them
- for product managers to introduce changes in the application functionalities, and become very flexible when it comes to developing or eliminating features
The production cycles are becoming shorter which will enable more feedback from the clients, the users and the market in general. This constant feedback will ensure that the final product is market-fit.
To be able to accelerate the development cycles, web developers need to automate the configuration of the deployment server. The process of setting up the server before deployment is called Provisioning. This is where Ansible comes in. Ansible is a tool that allows you to write a playbook file, select hosts, and automate the configuration on the selected hosts using a single command.
In this article, we will use Ansible to automate the provisioning of an Nginx web server on an AWS Ubuntu Virtual Machine (EC2). We will also automate the deployment of a simple web page on the same VM. The page will be server by the Nginx web server to the clients.
1- Creating an AWS Ubuntu VM
For the purpose of this tutorial, we will pick an Ubuntu server, and a flavour that is within their free-tier.
To connect to our VM, we will use SSH or Secure Shell. The protocol will allow you to control the VM using a remote shell spawned on your terminal and connected to your VM. To authenticate to the VM you’ve created, you will need to have a SSH keys. When you create your AWS account, they will ask you for your SSH keys, if you don’t have any, Amazon will help you create them online before. If you are not familiar with SSH, it is worthwhile to read this documentation.
I made sure to use a key I had already created to access the server, and set up the security group so that I could have the port 22 (SSH) and 80 (HTTP) open. We need to enable these ports since Ansible will use SSH to access our VM and Nginx, once installed, will listen on port 80.
The AWS documentation is pretty good, and with a few clicks, you have it up and running in the cloud.
2- SSH to the instance to make sure we can access it
At this point, you should have a Ubuntu instance up and running. To verify this, let us SSH it from the command line.
ssh -i path_to_my_key/my_key.pem ubuntu@DNS_name_of_the_EC2_instance
Usually your SSH keys should be stored in
/Users/yourusername/.ssh/my_key.pem . If the connection is successful, a shell connected to the VM will be spawned in your terminal.
whoami command to verify that you are truly
3- Setting up Ansible on a Mac
If you are using another operating system like ubuntu, you can apt-get install ansible. It takes a second!
For Mac, you can install Ansible with Homebrew (but you could use pip as well).
brew install ansible
You will then want to create an ansible directory in /etc/:
In that ansible directory:
Create a basic config file (ansible.cfg) that allows you to specify some parameters, such as the path to the private key (instead of having to type it while launching the playbook) and the remote user on the remote server.
remote_user = ubuntu
This is needed because Ansible will use SSH to connect to the EC2 instance.
You also need to create a hosts file with the Public IP of the server:
Public_IP_of_remote_server <-- Something like that: 'http://ec2-xx-xxx-xxx-xx.us-east-2.compute.amazonaws.com/'
It should now be possible to ping the remote host if you execute the following command in a terminal.
ansible all -m ping
If you receive the pong back from the instance, it means that Ansible was able to connect to the remote instance. We can now move further!
4- Creating the Playbook
The playbook file is where the developers write Infrastructure as Code. Remember, our goal is to set up the right infrastructure in our remote instance. We are going to do that using commands written in the playbook file. Ansible will then process our playbook code and deploy the corresponding infrastructure on the AWS instance.
In this playbook, you can see that we referred to
myServers , defined in the
/etc/ansible/hosts file we have created in the previous paragraph. For these hosts we have defined, we want Ansible to complete several tasks (lines 4–26) to set up our desired environment. The first two tasks are updating apt-get, because we have chosen a ubuntu instance, and installing the Nginx web server on the machine. Next, we want to upload two local documents to the Nginx root html directory, an html file to be served by the web server and a css file for formatting purposes (it is not important at this stage, you can skip the css file). We will next create these files locally under
~/Documents/nginx-install-dir . Lines 29–33 tell the nginx service to start once provisioning and deployment are completed.
Go ahead and create the directory:
~/Documents/nginx-install-dir/ where we will add a dumb HTML file to be uploaded to the server.
You can create an empty CSS file in the same directory as well.
5- Launching Provisioning and Deployment
Go the the directory where you have created your
install_nginx.yml playbook file and run the following on the command line:
If all goes well, you should see no errors and could then open the below link in your browser.
Congratulations, you have successfully automated the provisioning of an AWS instance using Ansible!