summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromagdy7 <omar.professional8777@gmail.com>2024-04-29 01:20:53 +0300
committeromagdy7 <omar.professional8777@gmail.com>2024-04-29 01:20:53 +0300
commiteab060df8cfde1137d24f372a2396963c69b5965 (patch)
treee9753d0f435eae980954a49619ae7aaae7c76a45
downloadcloudrender-infra-eab060df8cfde1137d24f372a2396963c69b5965.tar.xz
cloudrender-infra-eab060df8cfde1137d24f372a2396963c69b5965.zip
Intial IaC code and setting up deployment using ansible
-rw-r--r--.gitignore5
-rw-r--r--ansible/gunicorn.service.j213
-rw-r--r--ansible/hosts.ini2
-rw-r--r--ansible/nginx.conf.j213
-rw-r--r--ansible/setup-deployment.yml108
-rw-r--r--ansible/setup-docker.yml27
-rw-r--r--terraform/main.tf283
7 files changed, 451 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f2504ac
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.hosts.ini
+.terraform
+.terraform.lock.hcl
+terraform.tfstate
+terraform.tfstate.backup
diff --git a/ansible/gunicorn.service.j2 b/ansible/gunicorn.service.j2
new file mode 100644
index 0000000..fe9c69c
--- /dev/null
+++ b/ansible/gunicorn.service.j2
@@ -0,0 +1,13 @@
+[Unit]
+Description=gunicorn daemon
+After=network.target
+
+[Service]
+User=ec2-user
+Group=nginx
+WorkingDirectory=/opt/image_processor
+ExecStart=/opt/image_processor/venv/bin/gunicorn --workers 3 --bind unix:{{ app_directory }}/myapp.sock -m 007 wsgi:app
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/ansible/hosts.ini b/ansible/hosts.ini
new file mode 100644
index 0000000..c3896e7
--- /dev/null
+++ b/ansible/hosts.ini
@@ -0,0 +1,2 @@
+[ec2_instances]
+44.202.210.65 ansible_user=ec2-user ansible_ssh_private_key_file=~/keypair_amazon/deployer_key
diff --git a/ansible/nginx.conf.j2 b/ansible/nginx.conf.j2
new file mode 100644
index 0000000..a890814
--- /dev/null
+++ b/ansible/nginx.conf.j2
@@ -0,0 +1,13 @@
+server {
+ listen 80;
+ ec2_user {{ server_ip }};
+
+ location / {
+ proxy_pass http://unix:/opt/image_processor/myapp.sock;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+}
+
diff --git a/ansible/setup-deployment.yml b/ansible/setup-deployment.yml
new file mode 100644
index 0000000..feb42c5
--- /dev/null
+++ b/ansible/setup-deployment.yml
@@ -0,0 +1,108 @@
+---
+- name: Deploy Flask Application on Amazon Linux
+ hosts: all
+ become: yes
+
+ vars:
+ app_directory: "/opt/image_processor"
+ requirements:
+ - Flask==2.0.1
+ - flask-cors
+ - boto3
+ - opencv-python-headless
+ - numpy
+ - gunicorn
+
+ tasks:
+ - name: Update all system packages
+ yum:
+ name: "*"
+ state: latest
+ update_cache: yes
+
+ - name: Install essential packages
+ yum:
+ name:
+ - gcc
+ - gcc-c++
+ - git
+ state: present
+
+ - name: enable Nginx using amazon-linux-extras
+ command: amazon-linux-extras enable nginx1.12
+
+ - name: Install nginx
+ yum:
+ name: nginx
+ state: present
+
+ - name: Upgrade pip
+ command: pip3 install --upgrade pip
+
+ - name: Install virtualenv using pip
+ command: pip3 install virtualenv
+
+ - name: Create application directory
+ file:
+ path: "{{ app_directory }}"
+ state: directory
+ mode: '0755'
+
+ - name: Remove existing virtual environment
+ file:
+ path: "{{ app_directory }}/venv"
+ state: absent
+
+ - name: Create a virtual environment using virtualenv
+ command: virtualenv -p python {{ app_directory }}/venv
+
+ - name: Install Python packages in the virtual environment
+ pip:
+ name: "{{ item }}"
+ virtualenv: "{{ app_directory }}/venv"
+ loop: "{{ requirements }}"
+
+ - name: Copy application files to the server
+ copy:
+ src: "{{ item }}"
+ dest: "{{ app_directory }}"
+ mode: '0644'
+ with_fileglob:
+ - "../../CloudRender/backend/*.py"
+
+ - name: Setup Gunicorn systemd service
+ template:
+ src: gunicorn.service.j2
+ dest: /etc/systemd/system/gunicorn.service
+ notify:
+ - Reload systemd
+ - Restart Gunicorn
+
+ - name: Setup Nginx configuration
+ template:
+ src: nginx.conf.j2
+ dest: /etc/nginx/conf.d/my_flask_app.conf
+ notify:
+ - Restart nginx
+
+ - name: Ensure nginx is running and enabled
+ systemd:
+ name: nginx
+ state: started
+ enabled: true
+
+ handlers:
+ - name: Restart nginx
+ systemd:
+ name: nginx
+ state: restarted
+
+ - name: Reload systemd
+ systemd:
+ daemon_reload: yes
+
+ - name: Restart Gunicorn
+ systemd:
+ name: gunicorn
+ state: restarted
+
diff --git a/ansible/setup-docker.yml b/ansible/setup-docker.yml
new file mode 100644
index 0000000..e4cac93
--- /dev/null
+++ b/ansible/setup-docker.yml
@@ -0,0 +1,27 @@
+- name: Install Docker on EC2 instances
+ hosts: ec2_instances
+ become: yes
+
+ tasks:
+ - name: Update yum package manager
+ yum:
+ name: '*'
+ state: latest
+
+ - name: Install Docker
+ yum:
+ name: docker
+ state: present
+
+ - name: Start and enable Docker service
+ service:
+ name: docker
+ state: started
+ enabled: yes
+
+ - name: Add ec2-user to the docker group
+ user:
+ name: ec2-user
+ groups: docker
+ append: yes
+
diff --git a/terraform/main.tf b/terraform/main.tf
new file mode 100644
index 0000000..d956ad3
--- /dev/null
+++ b/terraform/main.tf
@@ -0,0 +1,283 @@
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws" // Defines the provider source
+ version = "~> 5.0"
+ }
+ }
+}
+
+# Configure the AWS Provider
+provider "aws" {
+ region = "us-east-1"
+}
+
+data "aws_ami" "amazon-linux-2" {
+ most_recent = true
+
+
+ filter {
+ name = "owner-alias"
+ values = ["amazon"]
+ }
+
+
+ filter {
+ name = "name"
+ values = ["amzn2-ami-hvm*"]
+ }
+}
+
+# Create a VPC
+resource "aws_vpc" "my_vpc" {
+ cidr_block = "10.0.0.0/16"
+
+ tags = {
+ Name = "DistribtedImageProcessing VPC"
+ }
+}
+
+# Create an Internet Gateway
+resource "aws_internet_gateway" "my_igw" {
+ vpc_id = aws_vpc.my_vpc.id
+
+ tags = {
+ Name = "myigw"
+ }
+}
+
+# Create a Public Subnet
+resource "aws_subnet" "public_subnet" {
+ vpc_id = aws_vpc.my_vpc.id
+ cidr_block = "10.0.1.0/24"
+ availability_zone = "us-east-1a"
+
+ tags = {
+ Name = "mysubnet"
+ }
+}
+
+# Create a Route Table
+resource "aws_route_table" "public_rt" {
+ vpc_id = aws_vpc.my_vpc.id
+
+ route {
+ cidr_block = "0.0.0.0/0"
+ gateway_id = aws_internet_gateway.my_igw.id
+ }
+
+ tags = {
+ Name = "myrt"
+ }
+}
+
+# Associate the Route Table with the Public Subnet
+resource "aws_route_table_association" "public_rt_assoc" {
+ subnet_id = aws_subnet.public_subnet.id
+ route_table_id = aws_route_table.public_rt.id
+}
+
+# Create a Security Group for the EC2 instance
+resource "aws_security_group" "ec2_sg" {
+ name = "EC2 Security Group"
+ description = "Allow inbound SSH, HTTP and HTTPS traffic"
+ vpc_id = aws_vpc.my_vpc.id
+
+ # Allow SSH
+ ingress {
+ from_port = 22
+ to_port = 22
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+
+
+ # Allow HTTP
+ ingress {
+ from_port = 80
+ to_port = 80
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+
+
+ # Allow HTTPS
+ ingress {
+ from_port = 443
+ to_port = 443
+ 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 = "EC2 Security Group"
+ }
+}
+
+# Create an EC2 instance
+resource "aws_instance" "my_instance1" {
+ ami = "${data.aws_ami.amazon-linux-2.id}"
+ instance_type = "t2.micro"
+ subnet_id = aws_subnet.public_subnet.id
+ vpc_security_group_ids = [aws_security_group.ec2_sg.id, aws_security_group.ec2_sg.id]
+ associate_public_ip_address = true
+ key_name = aws_key_pair.deployer_key.key_name
+ iam_instance_profile = aws_iam_instance_profile.ec2_s3_access_profile.name
+
+ tags = {
+ Name = "image_manipulator1"
+ }
+}
+
+resource "aws_instance" "my_instance2" {
+ ami = "${data.aws_ami.amazon-linux-2.id}"
+ instance_type = "t2.micro"
+ subnet_id = aws_subnet.public_subnet.id
+ vpc_security_group_ids = [aws_security_group.ec2_sg.id, aws_security_group.ec2_sg.id]
+ associate_public_ip_address = true
+ key_name = aws_key_pair.deployer_key.key_name
+ iam_instance_profile = aws_iam_instance_profile.ec2_s3_access_profile.name
+
+ tags = {
+ Name = "image_manipulator2"
+ }
+}
+
+resource "aws_key_pair" "deployer_key" {
+ key_name = "deployer-key"
+ public_key = file("~/keypair_amazon/deployer_key.pub")
+}
+
+
+# IAM role for the EC2 instance
+resource "aws_iam_role" "ec2_s3_access_role" {
+ name = "ec2_s3_access_role"
+
+ assume_role_policy = jsonencode({
+ Version = "2012-10-17",
+ Statement = [
+ {
+ Action = "sts:AssumeRole",
+ Effect = "Allow",
+ Principal = {
+ Service = "ec2.amazonaws.com"
+ }
+ },
+ ]
+ })
+}
+
+# IAM policy to grant S3 read and write permissions
+resource "aws_iam_policy" "s3_read_write_policy" {
+ name = "s3_read_write_policy"
+ description = "Policy that allows S3 read and write access"
+
+ policy = jsonencode({
+ Version = "2012-10-17",
+ Statement = [
+ {
+ Action = [
+ "s3:GetObject",
+ "s3:PutObject",
+ "s3:DeleteObject",
+ "s3:ListBucket",
+ ],
+ Effect = "Allow",
+ Resource = [
+ "${aws_s3_bucket.original_images.arn}/*",
+ "${aws_s3_bucket.processed_images.arn}/*"
+ ]
+ },
+ ]
+ })
+}
+
+# Attach the IAM policy to the role
+resource "aws_iam_role_policy_attachment" "ec2_s3_access_policy_attachment" {
+ role = aws_iam_role.ec2_s3_access_role.name
+ policy_arn = aws_iam_policy.s3_read_write_policy.arn
+}
+
+# Create an IAM instance profile for the EC2 instance
+resource "aws_iam_instance_profile" "ec2_s3_access_profile" {
+ name = "ec2_s3_access_profile"
+ role = aws_iam_role.ec2_s3_access_role.name
+}
+
+resource "aws_s3_bucket" "original_images" {
+ bucket = "original-images-${random_pet.name.id}" // Ensures global uniqueness
+
+ tags = {
+ Purpose = "Original Image Uploads"
+ }
+}
+
+
+resource "aws_s3_bucket" "processed_images" {
+ bucket = "processed-images-${random_pet.name.id}" // Ensures global uniqueness
+
+ tags = {
+ Purpose = "Processed Image Downloads"
+ }
+}
+
+resource "aws_s3_bucket_public_access_block" "original_images_public_acssess" {
+ bucket = aws_s3_bucket.original_images.id
+
+ block_public_acls = false
+ block_public_policy = false
+}
+resource "aws_s3_bucket_public_access_block" "processed_images_public_acssess" {
+ bucket = aws_s3_bucket.processed_images.id
+
+ block_public_acls = false
+ block_public_policy = false
+}
+
+
+resource "aws_s3_bucket_policy" "processed_images_allow_read_policy" {
+ bucket = aws_s3_bucket.processed_images.id
+
+ policy = jsonencode({
+ Version = "2012-10-17",
+ Statement = [
+ {
+ Effect = "Allow",
+ Principal = "*",
+ Action = "s3:GetObject",
+ Resource = [
+ "${aws_s3_bucket.processed_images.arn}/*"
+ ]
+ },
+ ]
+ })
+}
+
+resource "aws_s3_bucket_policy" "original_images_allow_read_policy" {
+ bucket = aws_s3_bucket.original_images.id
+
+ policy = jsonencode({
+ Version = "2012-10-17",
+ Statement = [
+ {
+ Effect = "Allow",
+ Principal = "*",
+ Action = "s3:GetObject",
+ Resource = [
+ "${aws_s3_bucket.original_images.arn}/*"
+ ]
+ },
+ ]
+ })
+}
+
+resource "random_pet" "name" {
+ length = 2
+}