Friday, 27 December 2024

Docker interview questions

Basic Level
  1. What is Docker, and why is it used?
  2. Compare Docker with Virtual Machines.
  3. What is the difference between a Container and an Image?
  4. Which command is used to list all running containers?
  5. Which command is used to build a Docker image?
  6. How do you run a container from an image?
  7. What is a Dockerfile? What is its purpose?
  8. Explain the meaning of some basic Dockerfile instructions: FROM, RUN, CMD, EXPOSE.
  9. What is a Volume in Docker? Why is it needed?
  10. How do you remove an unused container or image?

Intermediate Level

  1. What is Docker Networking? What types of networks are available?
    • Compare bridge, host, and overlay networks.
  2. How do you check the logs of a running container?
  3. What is Docker Compose? When should you use Docker Compose?
  4. Which command is used to scale the number of containers in Docker Compose?
  5. How do you debug a container that fails to start?
  6. What is the difference between Bind Mount and Volume?
  7. Explain how docker build works and why caching is important.
  8. What is the Docker Restart Policy? What types of policies are available?
  9. How do you pass environment variables into a container?
  10. Explain the process of removing all unnecessary containers, images, and volumes.

Advanced Level

  1. What is Docker Swarm? Compare Docker Swarm with Kubernetes.
  2. What are Multistage Builds in Dockerfile? When should you use them?
  3. How can you optimize the size of a Docker image?
  4. What is Docker Registry? Compare Docker Hub with a Private Registry.
  5. How do you secure Docker containers?
  6. Explain how to deploy a microservices architecture using Docker Compose or Swarm.
  7. How do you manage state in Docker (stateful applications)?
  8. How does Overlay Networking work in Docker?
  9. How do you configure CPU and memory for a container?
  10. How do you monitor the performance of a container?

Situational Questions

  1. If your container fails to start, what steps would you take to troubleshoot and fix it?
  2. You have an application requiring Redis as a cache and MySQL as a database. Design a Docker Compose file for this setup.
  3. How do you deploy Docker in a production environment?
  4. A Docker container is running slower than usual. What steps would you take to analyze the cause?
  5. How do you update a container without disrupting the service?

Thursday, 12 December 2024

Set up a single EC2 instance running Nginx as a load balancer and SSL terminator using Let’s Encrypt

How to set up a single EC2 instance running Nginx as a load balancer and SSL terminator using Let’s Encrypt, directing traffic to three EC2 instances running a Laravel application. This guide assumes a standard AWS VPC environment and that you have control over DNS records for your domain.

Overview of the Architecture

  • Public-facing EC2 (Load Balancer):
    • Runs Nginx.
    • Terminates SSL using Let’s Encrypt certificates.
    • Proxies requests to the 3 backend Laravel application servers.
  • Three Backend EC2 Instances (Laravel App Servers):
    • Run Laravel (with PHP-FPM, Nginx, or Apache).
    • Accessible only within the same VPC, ideally in private subnets.
    • The load balancer communicates with them via private IP addresses.

Prerequisites

  1. AWS Setup:

    • A VPC with subnets. Assume:
      • One public subnet for the load balancer EC2.
      • Private subnets for the Laravel app servers.
    • Security groups properly set up so the load balancer can access the app servers on port 80 (or your chosen port).
  2. EC2 Instances:

    • Load Balancer EC2:
      • Public subnet.
      • Has a public IP or an Elastic IP (EIP) so it’s reachable from the internet.
    • Laravel App EC2s:
      • Typically in private subnets (recommended) or can be public if properly secured.
      • Each running a web server (Nginx/Apache) and PHP-FPM, serving the Laravel app on port 80 internally.
    • Ensure that DNS (e.g., example.com) points to the public IP of the load balancer EC2.
  3. DNS Configuration:

    • In your domain registrar or DNS provider, create an A record for example.com pointing to the load balancer EC2’s public IP.
    • If using a subdomain (e.g., app.example.com), point that subdomain to the load balancer.

Step-by-Step Setup

A. Set Up the Backend Laravel Instances

  1. Install and Run Laravel:

    • On each Laravel EC2 instance, ensure:
      • PHP, Composer, and a web server (Nginx or Apache) are installed.
      • The Laravel code is deployed in /var/www/html or a similar directory.
      • Nginx or Apache is configured to serve the application at http://localhost:80.
    • Test locally on each instance:
      bash
      curl http://localhost
      You should see the Laravel default page or your application’s output.
  2. Security Groups (Backend):

    • The backend servers’ security group should allow inbound traffic on port 80 only from the load balancer’s private IP or security group, not from the public internet.
    • Outbound traffic is usually unrestricted by default.

B. Set Up the Load Balancer EC2 (Nginx + Let’s Encrypt)

  1. Install Nginx: On a Ubuntu-based system:

    bash
    sudo apt-get update sudo apt-get install nginx -y

    Confirm Nginx is running:

    bash
    systemctl status nginx
  2. Open Ports in Security Group (Load Balancer):

    • Inbound: allow HTTP (80) and HTTPS (443) from 0.0.0.0/0 so the public can access the site.
    • Outbound: allow traffic to the backend servers on port 80.
  3. Configure Nginx Upstream for Load Balancing: Create an upstream configuration file:

    bash
    sudo nano /etc/nginx/conf.d/upstream.conf

    Add:

    nginx
    upstream laravel_app { server 10.0.1.10:80; # Private IP of Laravel app server 1 server 10.0.1.11:80; # Private IP of Laravel app server 2 server 10.0.1.12:80; # Private IP of Laravel app server 3 }

    Replace IPs with the actual private IPs of your Laravel servers.

  4. Create Nginx Server Block for HTTP:

    bash
    sudo nano /etc/nginx/sites-available/example.com

    Add:

    nginx
    server { listen 80; server_name example.com www.example.com; # Location for Let's Encrypt HTTP-01 challenge location /.well-known/acme-challenge/ { root /var/www/html; } # Proxy pass to backend location / { proxy_pass http://laravel_app; 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; } }

    Create the root directory for Let’s Encrypt challenges (if it doesn't exist):

    bash
    sudo mkdir -p /var/www/html/.well-known/acme-challenge sudo chown -R www-data:www-data /var/www/html

    Enable the site:

    bash
    sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx

    Now http://example.com should route to one of the backend Laravel servers. Test by visiting http://example.com.

C. Obtain and Install Let’s Encrypt SSL Certificate

  1. Install Certbot: On Ubuntu:

    bash
    sudo apt-get install certbot python3-certbot-nginx -y
  2. Run Certbot:

    bash
    sudo certbot --nginx -d example.com -d www.example.com

    Certbot will:

    • Place a challenge file in /.well-known/acme-challenge/ for domain verification.
    • Request an SSL certificate from Let’s Encrypt.
    • Update the Nginx configuration automatically to use HTTPS.
  3. Check the Nginx Configuration After Certbot: After Certbot finishes, it should create or update the example.com config to:

    • Redirect http:// to https://
    • Use ssl_certificate and ssl_certificate_key directives pointing to your Let’s Encrypt certificates.

    A typical final config might look like:

    nginx
    server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name example.com www.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_pass http://laravel_app; 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; } }

    Test:

    bash
    sudo nginx -t sudo systemctl reload nginx

    Now, https://example.com should serve the Laravel app over HTTPS.

D. Verify Load Balancing and SSL

  • Open https://example.com in a browser.
  • Confirm the SSL certificate is valid and secured (lock icon in the browser).
  • Refresh multiple times to ensure requests are distributed across the three backend servers (you can check logs on each server to confirm hits).

E. Certificate Renewal

  • Certbot sets up a systemd timer or cron job to auto-renew certificates.
  • Check:
    bash
    systemctl list-timers | grep certbot
    This ensures your SSL certificate is renewed automatically.

F. Additional Considerations

  1. Sticky Sessions / Session Storage: If your Laravel application uses session data (e.g., user logins), consider using a centralized session store such as Redis or a database. Without this, different requests may land on different app servers and cause issues if each server stores sessions locally. Configure SESSION_DRIVER in .env accordingly.

  2. Health Checks & Failover: Consider enabling health checks to ensure Nginx only routes requests to healthy backend servers. You can configure proxy_next_upstream or a specific health check endpoint.

  3. Logging and Monitoring:

    • Nginx logs:
      • Access logs: /var/log/nginx/access.log
      • Error logs: /var/log/nginx/error.log
    • Laravel logs on backend servers:
      Check storage/logs/laravel.log to ensure the requests are being served correctly.
  4. Scaling: If you need more backend servers in the future, just add their IPs to the upstream block and reload Nginx. This makes the system scalable.

Summary:

  • You set up an EC2 instance as a load balancer with Nginx and obtained an SSL certificate from Let’s Encrypt.
  • You pointed your domain name to the load balancer, which then routes traffic to three backend Laravel servers.
  • The setup terminates SSL at the load balancer and distributes requests over HTTP to the Laravel servers internally.
  • With proper DNS, security groups, and upstream configuration, you have a secure, load-balanced environment for your Laravel application.

Thank you

Send emails using Amazon SES with an IAM role

Allowing a Laravel application, running on an EC2 instance in a public subnet, to send emails using Amazon SES with an IAM role:

1. Prerequisites and Overvie

Before configuring your application, ensure that:

  • SES Setup:
    You have verified your sending domain or email address in Amazon SES. If your account is still in the SES sandbox, you need to verify every recipient email address as well. Once moved out of the sandbox by requesting production access, you can send to any email address.

  • Region Selection:
    SES is a regional service. Make sure you use the same region for SES and the IAM role policies. Also, ensure that your .env and mail configuration files in Laravel reflect the correct region.

2. Create and Attach an IAM Role with SES Permissions

Instead of manually providing AWS credentials in .env, you can rely on an IAM role attached to the EC2 instance. The AWS SDK in Laravel will automatically retrieve temporary credentials from the instance metadata:

  1. Create the IAM Role:

    • Open the IAM console in AWS.
    • Click Roles > Create role.
    • Select AWS service and choose EC2 as the use case.
    • Click Next: Permissions.
    • Attach a policy that allows sending emails via SES. For testing, you can use AmazonSESFullAccess (not recommended for production), or create a more restrictive policy like:
      json
      { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ses:SendEmail", "ses:SendRawEmail" ], "Resource": "*" } ] }
    • Complete the role creation.
  2. Attach the Role to Your EC2 Instance:

    • Go to the EC2 console and select your running instance.
    • Choose Actions > Security > Modify IAM Role.
    • Select the IAM role you just created and attach it.

After this step, the EC2 instance will have permission to send emails through SES without requiring access keys in the application’s code.

3. Configure Laravel to Use SES

Laravel uses config/mail.php and .env for mail configurations. The SES mailer is built into Laravel’s core mail system (for Laravel versions 5.7+):

  1. .env Configuration: In your .env, specify SES as your mail driver and the AWS region:

    env
    MAIL_MAILER=ses AWS_DEFAULT_REGION=us-east-1 # or your chosen region AWS_SES_REGION=us-east-1 # match the region where your SES is set up # Leave these blank since the IAM role will provide credentials: AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY=

    Note: The AWS_SES_REGION should correspond to the region where your SES service (domain/email verification) is set up.

  2. config/mail.php: The default configuration for the SES mailer in config/mail.php might look like this:

    php
    'mailers' => [ 'ses' => [ 'transport' => 'ses', 'region' => env('AWS_SES_REGION', 'us-east-1'), ], // other mailers... ],

    The AWS SDK will automatically fetch credentials from the EC2 instance metadata since the IAM role is attached. You do not need to hardcode any keys.

4. Network and Security Considerations

  • Since the EC2 instance is in a public subnet with an Internet Gateway, it likely already has outbound internet access.
  • Ensure the instance’s Security Group allows outbound HTTPS (port 443) traffic. SES endpoints are accessed over HTTPS.
  • No need for a VPC endpoint if you are fine with public internet access. If you prefer private connectivity and do not want public internet traffic, you would consider adding a VPC endpoint. However, in a public subnet scenario, this is usually unnecessary.

5. Test the Configuration

After setting everything up, test sending an email from your Laravel application:

php
use Illuminate\Support\Facades\Mail; Mail::raw('This is a test email sent via SES', function ($message) { $message->to('recipient@example.com') ->subject('Test SES Email'); });
  • Check the logs at storage/logs/laravel.log if the email is not delivered.
  • If in the SES sandbox, ensure you verify both the sender and recipient addresses.
  • If you see errors related to Unverified email address or MessageRejected, verify that SES is configured correctly and that the email/domain is verified.

6. Common Troubleshooting Tips

  • Permissions: Make sure the IAM role has the correct SES permissions. Check IAM > Roles to confirm the attached policies.
  • Region Mismatch: Ensure the AWS_SES_REGION and the region where you verified your domain in SES match.
  • Sandbox vs. Production: If still in the SES sandbox, you must verify recipient emails. To lift sandbox restrictions, request production access from the AWS SES console.
  • Logging and Debugging:
    Check laravel.log for detailed error messages.
    You can also SSH into the instance and use the AWS CLI to test SES sending (if CLI is installed and configured to use the IAM role):
    bash
    aws ses send-email \ --from sender@verifieddomain.com \ --destination "ToAddresses=recipient@example.com" \ --message "Subject={Data=Test},Body={Text={Data=Test message}}"
    If this works, then the issue might be within the Laravel configuration. If this fails, the problem is at the IAM or SES level.

Summary

  • Assign an IAM role with SES permissions to your EC2 instance.
  • Configure Laravel’s .env and config/mail.php to use SES.
  • Ensure that SES domain/email verification and region alignment are correct.
  • Check networking to confirm outbound HTTPS is allowed.
  • Test sending emails and troubleshoot as necessary.

Thank you

Laravel application hosted on an EC2 instance in a public subnet to access S3

How to allow your Laravel application, running on an EC2 instance in a public subnet, to access S3 using an IAM role:

1. Attach an IAM Role to the EC2 Instance

Instead of hardcoding AWS credentials, you should use an IAM role. This allows the EC2 instance to receive temporary credentials automatically from the AWS metadata service, which is more secure and easier to maintain.

Steps to create and attach an IAM Role:

  1. Create the IAM Role:

    • Go to the IAM section in the AWS Management Console.
    • Click Roles > Create role.
    • Select AWS service as the trusted entity and choose EC2.
    • Click Next: Permissions and attach an appropriate policy for S3 access, for example, AmazonS3FullAccess or a custom policy.
    • Give your role a name and complete the creation process.
  2. Custom Policy Example (Read/Write to a Specific Bucket):

    json
    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::your-bucket-name/*" } ] }
  3. Attach the IAM Role to Your EC2 Instance:

    • Go to the EC2 Dashboard, select the instance that runs your Laravel application.
    • Click Actions > Security > Modify IAM Role.
    • Select the IAM role you created and attach it.

After attaching the IAM role, your EC2 instance will automatically have the necessary permissions to interact with S3 according to the policies you attached. You do not need to store or hardcode credentials on the server.

2. Configure Laravel to Use S3

Your Laravel application needs to know how to use S3 as a storage disk. This is configured in config/filesystems.php.

Update your .env file:

env
AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=your-region AWS_BUCKET=your-bucket-name

Since you’re using an IAM role, you can leave AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY empty. The AWS SDK will fetch temporary credentials from the EC2 instance’s metadata endpoint automatically.

Update config/filesystems.php:

php
's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), // leave empty for IAM role 'secret' => env('AWS_SECRET_ACCESS_KEY'), // leave empty for IAM role 'region' => env('AWS_DEFAULT_REGION', 'your-region'), 'bucket' => env('AWS_BUCKET', 'your-bucket-name'), ],

3. Network and Security Configuration

Since your EC2 instance is in a public subnet, ensure it can access the internet:

  • If your EC2 instance is associated with a public subnet that has an Internet Gateway, it likely already has outbound internet access.
  • If you were in a private subnet scenario, you would need a NAT Gateway or a similar setup.

Also, ensure the instance’s Security Group allows outbound traffic over HTTPS (port 443) to reach S3.

4. Test the Setup

You can test your setup within your Laravel application using the Storage facade:

php
use Illuminate\Support\Facades\Storage; // Example: Upload a test file to S3 Storage::disk('s3')->put('test.txt', 'This is a test file!');

If the file successfully appears in your S3 bucket, the configuration is working correctly.

Optional: Troubleshooting

  • Check that the IAM role has the correct permissions for the desired actions.
  • Review the Laravel logs (storage/logs/laravel.log) to see if any errors appear.
  • SSH into the EC2 instance and use the AWS CLI to test access:
    bash
    aws s3 ls s3://your-bucket-name

If you can list the bucket contents from the EC2 instance, it confirms that the instance has the proper credentials and network connectivity.

Summary:
By using an IAM role, you avoid hardcoding credentials. Laravel and the AWS SDK will automatically use the credentials provided by the EC2 instance’s metadata service. Ensure proper permissions, network access, and configuration in filesystems.php and .env. Then test by uploading or retrieving files from S3 via the Storage facade.

Note: You only need to create a VPC S3 endpoint if your EC2 instance does not have direct outbound internet access and you want it to access S3 privately within the VPC. Here are some scenarios:

  • If your EC2 instance is in a public subnet with a working Internet Gateway and can reach the internet (i.e., it has a public IP and Security Group rules allow outbound traffic):
    You do not need a VPC S3 endpoint. The instance can communicate with S3 over the public internet.

  • If your EC2 instance is in a private subnet without internet access (no NAT Gateway or outbound internet route):
    You will need a VPC S3 endpoint. This endpoint allows your EC2 instance to access S3 using private connectivity within AWS, without exposing traffic to the public internet.

So, the decision depends on your networking setup. If you already have internet access or a NAT Gateway for outbound traffic, you don’t need the endpoint. If you want to keep your traffic completely internal and not rely on public internet access, then setting up a VPC endpoint for S3 is the right approach.

Thank you.

Wednesday, 11 December 2024

Config Mysql in Laragon

* config in my.ini

Example allow user root access from any IP

UPDATE mysql.user SET host='%' WHERE user='root';
FLUSH PRIVILEGES;

ALTER USER 'root'@'%' IDENTIFIED BY 'root';

Update my.ini

bind-address=0.0.0.0

Thank you.

WSL networking

WSL access Server In Host (Window)

Access Ubuntu run:

usser@DESKTOP-VDO4U9R:~$ ip route show | grep -i default | awk '{ print $3}'
172.22.224.1 

Then in wsl can acesss host through above IP

Host (Window) acess WSL

- get Ip of WSL (Ubuntu) 

+ Access Ubuntu run: hostname -I (to get IP of WSL)

+ then access by IP

Reference

- https://learn.microsoft.com/en-us/windows/wsl/networking#accessing-windows-networking-apps-from-linux-host-ip

Monday, 2 December 2024

Late static binding and early binding in PHP

Late static binding and early binding are concepts in PHP that describe how methods or properties are resolved when a class hierarchy is involved. The key difference lies in when the resolution occurs and which class context is used.


Early Binding (self)

  • Definition: Early binding resolves the method or property to the class in which it is defined, regardless of the class from which it is called.
  • Behavior:
    • Uses self to reference the class where the code is written.
    • The binding happens at compile time.
    • Does not respect polymorphism in class hierarchies.

Example:

class ParentClass { public static function who() { return "ParentClass"; } public static function callWho() { return self::who(); // Early binding to ParentClass::who() } } class ChildClass extends ParentClass { public static function who() { return "ChildClass"; } } echo ParentClass::callWho(); // Output: ParentClass echo ChildClass::callWho(); // Output: ParentClass

Explanation:

  • self::who() in callWho() binds to the method who() in ParentClass because self is resolved at compile time.
  • Even when ChildClass calls callWho(), it does not use ChildClass::who().

Late Static Binding (static)

  • Definition: Late static binding resolves the method or property to the class that is actually calling the method (runtime class context).
  • Behavior:
    • Uses static to reference the calling class.
    • The binding happens at runtime.
    • Respects polymorphism in class hierarchies.

Example:

class ParentClass { public static function who() { return "ParentClass"; } public static function callWho() { return static::who(); // Late static binding } } class ChildClass extends ParentClass { public static function who() { return "ChildClass"; } } echo ParentClass::callWho(); // Output: ParentClass echo ChildClass::callWho(); // Output: ChildClass

Explanation:

  • static::who() in callWho() resolves to the who() method in the calling class.
  • When ChildClass calls callWho(), it dynamically binds to ChildClass::who().

Comparison Table

FeatureEarly Binding (self)Late Static Binding (static)
Resolution TimeCompile timeRuntime
Reference ContextThe class where the method is definedThe class that is calling the method
PolymorphismDoes not respect polymorphismRespects polymorphism
Keyword Usedselfstatic
Behavior with InheritanceAlways binds to the parent class method (if called in the parent)Dynamically binds to the calling class method

Key Points to Consider

  • Use early binding (self) when the behavior should always be tied to the parent class and should not change with inheritance.
  • Use late static binding (static) when you want polymorphic behavior, allowing the method or property resolution to adapt to the calling class at runtime.

Practical Example Comparing Both

class ParentClass { public static function who() { return "ParentClass"; } public static function earlyCall() { return self::who(); // Early binding } public static function lateCall() { return static::who(); // Late static binding } } class ChildClass extends ParentClass { public static function who() { return "ChildClass"; } } echo ParentClass::earlyCall(); // Output: ParentClass echo ChildClass::earlyCall(); // Output: ParentClass (early binding) echo ParentClass::lateCall(); // Output: ParentClass echo ChildClass::lateCall(); // Output: ChildClass (late static binding)

This highlights how self locks behavior to the defining class, while static allows dynamic resolution based on the calling class.

Thank you.

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.

Golang Advanced Interview Q&A