I wanted to use both ansible and terraform in a project for practice purposes and came up with a simple infrastructure to host my website in a ec2 instance using nginx.Terraform is used to provision infrastructure ie create an ec2 instance while ansible is used for configuration management ie installing all the software in the ec2 instance

prerequisites

install the following using your distro package manager

  • terraform
  • ansible
  • set up aws credentials

main

  • use the aws provider
provider "aws" {
  region = var.aws_region

}

  • create ec2 instance

resource "aws_instance" "server" {
  ami                         = var.ami
  instance_type               = var.aws_instance_type
  key_name                    = aws_key_pair.admin_key.key_name
  security_groups             = ["${aws_security_group.base_security_group.name}"]
  associate_public_ip_address = true

  tags = { Name = "nginx instance" }



  provisioner "local-exec" {
    command = "ansible-playbook -u root -i '${aws_instance.server.public_dns},' ansible/provision_nginx.yaml"
  }
}
  • create a security group to allow traffic through ssh this is how you get access to the ec2 instance
resource "aws_security_group" "base_security_group" {
  name        = "base_security_group"
  description = "Base security group"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "base_security_group"
  }

}
  • create ssh keys and send them to the ec2 instance

  • use local-exec provisioner to execute ansible playbooks

 provisioner "local-exec" {
    command = "ansible-playbook -u root -i '${aws_instance.server.public_dns},' ansible/provision_nginx.yaml"
  }
}
  • nginx config

server {
    listen 80;

    root {{ document_root }}/{{ app_root }};
    index index.html index.htm;

    server_name {{ server_name }};

    location / {
        default_type "text/html";
        try_files $uri.html $uri $uri/ =404;
    }
}
  • ansible to install, start and copy website files to the approriate folders

---
- name: configure nginx
  hosts: localhost
  become: yes
  vars:
    server_name: "{{ ansible_default_ipv4.address }}"
    document_root: /var/www
    app_root: public
  tasks:
    - name: install nginx
      apt:
        update_cache: yes
        name: nginx 

    - name: start nginx
      shell: sudo systemctl start nginx

    - name: copy files to the server
      synchronize:
        src: "{{ app_root }}"
        dest: "{{ document_root }}"

    - name: apply nginx template
      template:
        src: ../nginx.conf.j2
        dest: /etc/nginx/sites-available/default
      notify: Restart nginx

    - name: Enable new site
      file:
        src: /etc/nginx/sites-available/default
        dest: /etc/nginx/sites-enabled/default
        state: link
      notify: Restart nginx

    - name: allow acces to port 80
      ufw:
        rule: allow
        port: '80'
        proto: tcp

  handlers:
    - name: Restart nginx
      service:
        name: nginx
        state: restarted

  • variables
variable "aws_region" {
  default     = "af-south-1"
  description = "AWS region"
}

variable "aws_ssh_admin_key_file" {}

variable "ami" {
  default = "ami-08a4b40f2fe1e4b35"
}

variable "aws_instance_type" {
  default = "t3.micro"
}

  • keys.tf
resource "aws_key_pair" "admin_key" {
  key_name   = "admin_key"
  public_key = file("${var.aws_ssh_admin_key_file}.pub")

}

Summary

i used ansible by calling it inside of terraform using local-exec provisioner to configure my ec2 instance