Sunday, 1 December 2024

Build server laravel using EC2 in AWS

Building a system for your Laravel application on AWS involves several steps, including configuring your VPC, launching EC2 instances, setting up MySQL and Redis, configuring security, and deploying the application. Here's a comprehensive guide to set up a full Laravel application system on AWS with a custom load balancer:

Step-by-Step Guide: Building a Laravel Application System on AWS


1. Set Up the VPC (Virtual Private Cloud)

The first step is to create a Virtual Private Cloud (VPC) where all your AWS resources will reside.

Create the VPC

  1. Navigate to the VPC Dashboard:

    • In the AWS Management Console, go to Services → VPC.
  2. Create VPC:

    • Click Create VPC.
    • For IPv4 CIDR block, choose something like 10.0.0.0/16.
    • For IPv6 CIDR block, choose No IPv6 CIDR Block unless you need IPv6.
    • Set Tenancy to Default (unless you need dedicated instances).
    • Name your VPC (e.g., laravel-vpc).
  3. Create Subnets:

    • Create at least two subnets:
      • Public Subnet (e.g., 10.0.1.0/24) for your load balancer and web server (Laravel).
      • Private Subnet (e.g., 10.0.2.0/24) for MySQL and Redis.
  4. Create an Internet Gateway:

    • Go to Internet Gateways and click Create Internet Gateway.
    • Attach it to your VPC (laravel-vpc).
  5. Route Tables:

    • Create and associate route tables for both public and private subnets:
      • Public Route Table should have a route to the Internet Gateway.
      • Private Route Table should have no route to the internet (for internal communication).

2. Set Up EC2 Instances

You’ll need to launch several EC2 instances, including the load balancer, Laravel application instances, MySQL, and Redis.

Launch EC2 Instance for Load Balancer (Optional)

If you want to create a custom load balancer using EC2 (instead of AWS ALB):

  1. Launch EC2 Instance for Load Balancer:

    • Go to EC2 Dashboard → Launch Instance.
    • Choose an AMI (e.g., Amazon Linux 2 or Ubuntu).
    • Choose an instance type (e.g., t2.micro for testing).
    • Set security group rules to allow HTTP (80)HTTPS (443), and SSH (22) from trusted IPs.
  2. Install and Configure Load Balancer Software (e.g., Nginx or HAProxy):

    • SSH into the instance and install a reverse proxy like Nginx or HAProxy.
      • Example for Nginx:
        bash
        sudo yum install -y nginx sudo systemctl start nginx sudo systemctl enable nginx
    • Configure it to load balance between your backend Laravel instances.

Launch EC2 Instances for Laravel Application

  1. Launch Two EC2 Instances for Laravel:

    • These will run your Laravel application and handle incoming traffic.
    • Follow the same steps as for the load balancer, but choose the public subnet for these instances.
    • Set security group rules to allow HTTP (80) and HTTPS (443) from your load balancer's IP or security group.
  2. Install Laravel Dependencies:

    • SSH into the Laravel EC2 instances and install PHP, Composer, and other dependencies:
      bash
      sudo yum update -y sudo yum install -y httpd php php-mysqlnd php-mbstring php-xml composer
    • Clone your Laravel project from your Git repository or upload the project files.
  3. Configure Apache/Nginx:

    • Set up Apache or Nginx to serve your Laravel app.
  4. Configure Laravel Environment:

    • Update the .env file in Laravel with your MySQL and Redis configurations:
      env
      DB_CONNECTION=mysql DB_HOST=private-ip-of-mysql DB_PORT=3306 DB_DATABASE=your_database DB_USERNAME=your_user DB_PASSWORD=your_password REDIS_HOST=private-ip-of-redis REDIS_PASSWORD=null REDIS_PORT=6379

Launch EC2 Instance for MySQL Database

  1. Launch EC2 Instance for MySQL:

    • Choose an Ubuntu or Amazon Linux 2 AMI for MySQL.
    • Assign it to the private subnet.
    • Set security group rules to only allow access from your Laravel instances (on port 3306).
  2. Install MySQL:

    • SSH into the MySQL instance and install MySQL:
      bash
      sudo yum install -y mysql-server sudo systemctl start mysqld sudo systemctl enable mysqld
  3. Create MySQL Database and User:

    • Connect to MySQL:
      bash
      sudo mysql -u root -p
    • Create a database and user:
      sql
      CREATE DATABASE your_database; CREATE USER 'your_user'@'%' IDENTIFIED BY 'your_password'; GRANT ALL PRIVILEGES ON your_database.* TO 'your_user'@'%'; FLUSH PRIVILEGES;

Launch EC2 Instance for Redis

  1. Launch EC2 Instance for Redis:

    • Launch another EC2 instance in the private subnet.
    • Set security group rules to allow access to port 6379 only from the Laravel instances.
  2. Install Redis:

    • SSH into the Redis instance and install Redis:
      bash
      sudo yum install -y redis sudo systemctl start redis sudo systemctl enable redis
  3. Configure Redis:

    • Edit the Redis configuration file (/etc/redis/redis.conf) to bind Redis to the private IP and set it to protected mode:
      bash
      bind 127.0.0.1 <private-ip-of-redis> protected-mode yes
  4. Start Redis:

    • Restart Redis to apply the changes:
      bash
      sudo systemctl restart redis

3. Set Up Security Groups

  1. Security Group for Load Balancer:

    • Open HTTP (80) and HTTPS (443) for public access.
    • Allow SSH (22) from trusted IPs for management.
  2. Security Group for Laravel EC2 Instances:

    • Allow HTTP (80) and HTTPS (443) from the load balancer’s security group.
    • Allow MySQL (3306) and Redis (6379) only from the private subnet or specific IPs.
  3. Security Group for MySQL and Redis EC2 Instances:

    • Allow MySQL (3306) from Laravel EC2 instances.
    • Allow Redis (6379) from Laravel EC2 instances.

4. Configure Load Balancer (Optional)

If you're using a custom EC2 instance for load balancing:

  1. Configure the Reverse Proxy (Nginx or HAProxy):
    • Point the reverse proxy to your Laravel EC2 instances.
    • Example for Nginx:
      nginx
      upstream backend { server private-ip-of-laravel-instance1; server private-ip-of-laravel-instance2; } server { listen 80; location / { proxy_pass http://backend; } }

5. Final Testing and Deployment

  1. Test Load Balancer:

    • Access the public IP of your load balancer (if using EC2-based load balancer) or your VPC’s public IP to check if Laravel is working.
  2. Test Database and Redis:

    • Ensure Laravel is able to connect to MySQL and Redis using the configured private IP addresses.
  3. Deploy SSL:

    • If you want to serve your Laravel application over HTTPS, consider setting up SSL on your load balancer or web server (e.g., using Let’s Encrypt for a free SSL certificate).

6. Auto-Scaling and Monitoring

  1. Set Up Auto Scaling:

    • Use AWS Auto Scaling to scale your Laravel EC2 instances based on traffic.
    • Set the desired capacity, minimum, and maximum instances in your Auto Scaling Group.
  2. Set Up Monitoring:

    • Use AWS CloudWatch to monitor the health and performance of your EC2 instances.
    • Set up alarms for key metrics (e.g., CPU usage, memory, disk space).

7. Backup and Security

  1. Backup MySQL:

    • Regularly back up your MySQL database using AWS RDS snapshots or EC2 instance backups.
  2. Ensure Security Best Practices:

    • Use IAM roles for EC2 instances for secure access to AWS services (e.g., S3, Secrets Manager).
    • Enable Multi-AZ for MySQL if using RDS or set up replication for fault tolerance.

Conclusion

This guide takes you through the full process of setting up a Laravel application system on AWS


Code Python

 Full Python Code to Build the System

python
import boto3
import time

# Initialize boto3 clients for EC2, VPC, and IAM
ec2_client = boto3.client('ec2')
vpc_client = boto3.client('ec2')
elb_client = boto3.client('elbv2')
rds_client = boto3.client('rds')
redis_client = boto3.client('elasticache')

# Function to create a VPC
def create_vpc():
    response = vpc_client.create_vpc(
        CidrBlock='10.0.0.0/16',
        InstanceTenancy='default'
    )
    vpc_id = response['Vpc']['VpcId']
    print(f"VPC created: {vpc_id}")
   
    # Create Subnets
    public_subnet = vpc_client.create_subnet(
        VpcId=vpc_id,
        CidrBlock='10.0.1.0/24',
        AvailabilityZone='us-east-1a'
    )
    private_subnet = vpc_client.create_subnet(
        VpcId=vpc_id,
        CidrBlock='10.0.2.0/24',
        AvailabilityZone='us-east-1a'
    )
   
    print(f"Public Subnet: {public_subnet['Subnet']['SubnetId']}")
    print(f"Private Subnet: {private_subnet['Subnet']['SubnetId']}")
   
    # Create Internet Gateway
    igw = vpc_client.create_internet_gateway()
    igw_id = igw['InternetGateway']['InternetGatewayId']
    vpc_client.attach_internet_gateway(
        VpcId=vpc_id,
        InternetGatewayId=igw_id
    )
    print(f"Internet Gateway created and attached: {igw_id}")

    return vpc_id, public_subnet['Subnet']['SubnetId'], private_subnet['Subnet']['SubnetId']

# Function to create EC2 instances
def create_ec2_instances(subnet_id, instance_type, ami_id, key_name, security_group_id):
    instances = ec2_client.run_instances(
        ImageId=ami_id,
        InstanceType=instance_type,
        MinCount=1,
        MaxCount=1,
        KeyName=key_name,
        SubnetId=subnet_id,
        SecurityGroupIds=[security_group_id]
    )
   
    instance_id = instances['Instances'][0]['InstanceId']
    print(f"EC2 instance created: {instance_id}")
    return instance_id

# Function to create a security group
def create_security_group(vpc_id, group_name, description):
    sg = ec2_client.create_security_group(
        GroupName=group_name,
        Description=description,
        VpcId=vpc_id
    )
    security_group_id = sg['GroupId']
    print(f"Security group created: {security_group_id}")
   
    return security_group_id

# Function to create Load Balancer
def create_load_balancer(vpc_id, public_subnet_id):
    response = elb_client.create_load_balancer(
        Name='laravel-load-balancer',
        Subnets=[public_subnet_id],
        SecurityGroups=[],
        Scheme='internet-facing',
        LoadBalancerType='application',
        Listeners=[
            {
                'Protocol': 'HTTP',
                'Port': 80,
                'DefaultActions': [
                    {
                        'Type': 'fixed-response',
                        'FixedResponseConfig': {
                            'StatusCode': 200,
                            'ContentType': 'text/plain',
                            'MessageBody': 'OK'
                        }
                    }
                ]
            }
        ]
    )
    lb_arn = response['LoadBalancers'][0]['LoadBalancerArn']
    print(f"Load balancer created: {lb_arn}")
    return lb_arn

# Function to create RDS MySQL instance
def create_rds_instance():
    response = rds_client.create_db_instance(
        DBInstanceIdentifier='laravel-db',
        DBInstanceClass='db.t2.micro',
        Engine='mysql',
        MasterUsername='admin',
        MasterUserPassword='password',
        AllocatedStorage=20,
        VpcSecurityGroupIds=[],
        DBSubnetGroupName='',
        PubliclyAccessible=False
    )
    db_instance_id = response['DBInstance']['DBInstanceIdentifier']
    print(f"MySQL RDS instance created: {db_instance_id}")
    return db_instance_id

# Function to create Redis instance
def create_redis_instance():
    response = redis_client.create_cache_cluster(
        CacheClusterId='laravel-redis',
        Engine='redis',
        CacheNodeType='cache.t2.micro',
        NumCacheNodes=1,
        SubnetGroupName='',
        VpcSecurityGroupIds=[]
    )
    redis_cluster_id = response['CacheCluster']['CacheClusterId']
    print(f"Redis instance created: {redis_cluster_id}")
    return redis_cluster_id

# Main function to create the complete architecture
def setup_laravel_system():
    # Step 1: Create VPC
    vpc_id, public_subnet_id, private_subnet_id = create_vpc()
   
    # Step 2: Create Security Groups
    security_group_id = create_security_group(vpc_id, 'laravel-security-group', 'Security group for Laravel app')
   
    # Step 3: Create EC2 instances for Load Balancer and Laravel App
    load_balancer_instance_id = create_ec2_instances(public_subnet_id, 't2.micro', 'ami-xxxxxxxx', 'your-key', security_group_id)
    laravel_app_instance_id = create_ec2_instances(private_subnet_id, 't2.micro', 'ami-xxxxxxxx', 'your-key', security_group_id)
   
    # Step 4: Create Load Balancer
    lb_arn = create_load_balancer(vpc_id, public_subnet_id)
   
    # Step 5: Create RDS MySQL instance
    db_instance_id = create_rds_instance()
   
    # Step 6: Create Redis instance
    redis_instance_id = create_redis_instance()

    print("Laravel system architecture setup is complete.")

# Run the setup
if __name__ == '__main__':
    setup_laravel_system()

Key Components in the Script

  1. VPC Setup: Creates a VPC, subnets, and an internet gateway.
  2. Security Groups: Creates a security group for EC2 instances.
  3. EC2 Instances: Creates EC2 instances for the Load Balancer and Laravel application.
  4. Load Balancer: Creates an Application Load Balancer (ALB).
  5. MySQL: Creates an RDS MySQL instance for the database.
  6. Redis: Creates an ElastiCache Redis instance.

Full Python Code to Delete Resources

python
import boto3

# Initialize boto3 clients for EC2, VPC, and other AWS services
ec2_client = boto3.client('ec2')
vpc_client = boto3.client('ec2')
elb_client = boto3.client('elbv2')
rds_client = boto3.client('rds')
redis_client = boto3.client('elasticache')

# Function to delete EC2 instances
def delete_ec2_instances(instance_ids):
    if instance_ids:
        ec2_client.terminate_instances(InstanceIds=instance_ids)
        print(f"Terminating EC2 instances: {instance_ids}")

# Function to delete Load Balancer
def delete_load_balancer(lb_arn):
    if lb_arn:
        elb_client.delete_load_balancer(
            LoadBalancerArn=lb_arn
        )
        print(f"Deleted Load Balancer: {lb_arn}")

# Function to delete RDS MySQL instance
def delete_rds_instance(db_instance_id):
    if db_instance_id:
        rds_client.delete_db_instance(
            DBInstanceIdentifier=db_instance_id,
            SkipFinalSnapshot=True
        )
        print(f"Deleted RDS MySQL instance: {db_instance_id}")

# Function to delete Redis cache cluster
def delete_redis_instance(redis_cluster_id):
    if redis_cluster_id:
        redis_client.delete_cache_cluster(
            CacheClusterId=redis_cluster_id
        )
        print(f"Deleted Redis instance: {redis_cluster_id}")

# Function to delete security group
def delete_security_group(security_group_id):
    if security_group_id:
        ec2_client.delete_security_group(
            GroupId=security_group_id
        )
        print(f"Deleted security group: {security_group_id}")

# Function to delete VPC
def delete_vpc(vpc_id):
    if vpc_id:
        # Detach and delete Internet Gateway (if exists)
        igws = vpc_client.describe_internet_gateways(Filters=[{'Name': 'attachment.vpc-id', 'Values': [vpc_id]}])
        for igw in igws['InternetGateways']:
            igw_id = igw['InternetGatewayId']
            vpc_client.detach_internet_gateway(
                InternetGatewayId=igw_id,
                VpcId=vpc_id
            )
            vpc_client.delete_internet_gateway(
                InternetGatewayId=igw_id
            )
            print(f"Deleted Internet Gateway: {igw_id}")
       
        # Delete subnets
        subnets = vpc_client.describe_subnets(Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
        for subnet in subnets['Subnets']:
            subnet_id = subnet['SubnetId']
            vpc_client.delete_subnet(SubnetId=subnet_id)
            print(f"Deleted Subnet: {subnet_id}")
       
        # Finally, delete the VPC
        vpc_client.delete_vpc(VpcId=vpc_id)
        print(f"Deleted VPC: {vpc_id}")

# Main function to delete all resources
def delete_all_resources():
    # Step 1: Delete EC2 instances (for Load Balancer and Laravel App)
    delete_ec2_instances([ 'i-xxxxxxxxxxxxxxxx', 'i-yyyyyyyyyyyyyyyy'])  # Replace with your instance IDs

    # Step 2: Delete Load Balancer
    delete_load_balancer('arn:aws:elasticloadbalancing:region:account-id:loadbalancer/app/your-load-balancer/xxxxxxxxxxxxxxx')  # Replace with your Load Balancer ARN

    # Step 3: Delete RDS MySQL instance
    delete_rds_instance('laravel-db')  # Replace with your RDS instance ID

    # Step 4: Delete Redis instance
    delete_redis_instance('laravel-redis')  # Replace with your Redis cluster ID

    # Step 5: Delete Security Group
    delete_security_group('sg-xxxxxxxx')  # Replace with your security group ID

    # Step 6: Delete VPC
    delete_vpc('vpc-xxxxxxxx')  # Replace with your VPC ID

    print("All resources have been deleted.")

# Run the cleanup process
if __name__ == '__main__':
    delete_all_resources()

Key Functions in the Code

  1. Delete EC2 Instances: Terminates all the EC2 instances (both Load Balancer and Laravel app instances).
  2. Delete Load Balancer: Deletes the Application Load Balancer (ALB) using its ARN.
  3. Delete RDS MySQL Instance: Deletes the MySQL RDS instance.
  4. Delete Redis Instance: Deletes the Redis ElastiCache cluster.
  5. Delete Security Group: Deletes the security group associated with the EC2 instances.
  6. Delete VPC: Deletes the VPC and all associated resources like subnets and Internet Gateway.

Thank you.

No comments:

Post a Comment

Golang Advanced Interview Q&A