Limited Period Offer : 20% Discount on online/offline courses, for more details call/whatsapp

For Laravel Setting UP CI/CD Pipeline using GitHub, CodeDeploy, S3 and EC2

4 min read
1 year ago By Santosh Kshirsagar

Create user group with following policies

  • AmazonS3FullAccess
  • AWSCodeDeployFullAccess

Add User to the group created

Create Service Role for EC2 with policies

  • AWSCodeDeployRole
  • AmazonS3FullAccess

Create S3 Bucket

Create EC2 Instances

Install CodeDeployAgent on EC2 Instances

Create ServiceRole for CodeDeploy

Create CodeDeploy Application then deployment group with serviceRole attached created for codedeploy

Add Secrets/Env Variables to github

After Adding secrets

Go to Actions > create new workflow > set up workflow yourself or create below file directly in code

.github/workflows/main.yml with following code

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the "master" branch
  push:
    branches: ["master"]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v3

      # Runs a single command using the runners shell
      - name: Release to S3
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
          APPLICATION_NAME: ${{ secrets.APPLICATION_NAME }}
          DEPLOYMENT_CONFIG_NAME: ${{ secrets.DEPLOYMENT_CONFIG_NAME }}
          DEPLOYMENT_GROUP_NAME: ${{ secrets.DEPLOYMENT_GROUP_NAME }}
          S3_BUCKET: ${{ secrets.S3_BUCKET }}
        run: bash scripts/release-to-s3.sh

Create scripts folder and add release-to-s3.sh file with following code

 #!/bin/bash

apt -qy update   # q for quite , y for no promt yes/no
apt -qy install curl zip unzip

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
./aws/install

rm -rf awscliv2.zip 
rm -rf ./aws

HASH=`git rev-parse --short HEAD`
BUNDLE="bundle-$HASH.tar.gz"
S3_ENDPOINT="s3://$S3_BUCKET/bundles/"

rm -rf bundle-*.tar.gz

tar \
    --exclude="*.git" \
    --exclude="storage/logs/*" \
    --exclude="vendor/*" \
    --exclude="bootstrap/cache/*" \
    --exclude=".env" \
    --exclude="composer.lock" \
    -zcf $BUNDLE . > /dev/null 2>&1

aws s3 cp $BUNDLE $S3_ENDPOINT > /dev/null 2>&1
echo "[-] Your CodeDeploy s3 endpoint will be: $S3_ENDPOINT"

aws deploy create-deployment \
    --application-name $APPLICATION_NAME \
    --deployment-config-name $DEPLOYMENT_CONFIG_NAME \
    --deployment-group-name $DEPLOYMENT_GROUP_NAME \
    --file-exists-behavior OVERWRITE \
    --s3-location bucket=$S3_BUCKET,bundleType=tgz,key=bundles/$BUNDLE

In release-to-s3.sh change tar command as per your applications, you can exclude files/folders doesn’t need to be deployed

Create appspec.yml file (for code deploy)

version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html
hooks:
  BeforeInstall:
    - location: ./scripts/install_dependencies.sh
      timeout: 300
      runas: ec2-user
  AfterInstall:
    - location: ./scripts/deploy_laravel.sh
      timeout: 300
      runas: ec2-user
    - location: ./scripts/change_permissions.sh
      timeout: 300
      runas: ec2-user
  ApplicationStart:
    - location: ./scripts/start_server.sh
      timeout: 120
      runas: ec2-user
  ApplicationStop:
    - location: ./scripts/stop_server.sh
      timeout: 120
      runas: ec2-user

Create all required scripts in scripts folder to deploy and run application

Use secret manager>parameter store for .env file generation

User Data while creating instance for amazon linux 2 to install codedeploy agent

 #!/bin/bash

sudo yum update -y
sudo amazon-linux-extras enable php8.1
sudo yum clean metadata && sudo yum install php-cli php-pdo php-fpm php-json php-mysqlnd php-gd php-mbstring php-xml php-pear php-devel -y

sudo yum install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd

echo "<h1>Hello World from $(hostname -f)</h1>" > /var/www/html/health.html

sudo usermod -a -G apache ec2-user
sudo chown -R ec2-user:apache /var/www
sudo chmod 2775 /var/www && find /var/www -type d -exec sudo chmod 2775 {} \;
find /var/www -type f -exec sudo chmod 0664 {} \;

sudo curl -sS https://getcomposer.org/installer | sudo php
sudo mv composer.phar /usr/local/bin/composer
sudo ln -s /usr/local/bin/composer /usr/bin/composer

sudo yum install -y gcc-c++ make 
curl -sL https://rpm.nodesource.com/setup_16.x | sudo -E bash - 
sudo yum install -y nodejs

sudo yum install ruby -y
sudo yum install wget -y 
cd /home/ec2-user

wget https://aws-codedeploy-ap-south-1.s3.ap-south-1.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto

mkdir /var/www/laravel/
mkdir /var/www/laravel/public
echo "<h1>Hello World from $(hostname -f)</h1>" > /var/www/laravel/public/health.html

sudo bash -c 'echo "<VirtualHost *:80>
  DocumentRoot /var/www/laravel/public
  <Directory /var/www/laravel/public>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  </Directory>
RewriteEngine on
</VirtualHost>" >> /etc/httpd/conf.d/laravel.conf'

#sudo sed -i 's/var\/www\/html/var\/www\/laravel\/public/g' /etc/httpd/conf/httpd.conf

# update php ini settings
upload_max_filesize=128M
post_max_size=256M
max_execution_time=40
memory_limit=256M

for key in upload_max_filesize post_max_size max_execution_time memory_limit
do
 sudo sed -i "s/^\($key\).*/\1 $(eval echo = \${$key})/" /etc/php.ini
done

sudo systemctl restart php-fpm
sudo systemctl restart httpd

sudo yum install jq -y

# Please update below variables as per your production setup
PARAMATER="APP_ENV"
REGION="ap-south-1"
WEB_DIR="/var/www/laravel"
WEB_USER="ec2-user"

# Get parameters and put it into .env file inside application root
aws ssm get-parameter --with-decryption --name $PARAMATER --region $REGION | jq -r '.Parameter.Value' > $WEB_DIR/.env
May 25, 2023 01:43 Back to Articles

Other Articles

Binary Tree

Binary Tree is a Non-Linear data structure which has atmost 2 child . A Binary tree is represented by a pointer to the topmost node (commonly known as the “root”) of the tree. If the tree is empty, then the value of the root is NULL. Each node of a Binary Tree contains the following parts:

1 year ago By Aniket Prajapati
Real DOM VS Virtual DOM

In this article, we will discuss the differences between the real DOM and the virtual DOM in the context of web development. We'll explore how these concepts impact the performance and efficiency of web applications, and how they contribute to the overall user experience. By the end of this article, you'll have a clear understanding of the distinctions between these two approaches to managing and updating user interfaces on the web.

1 year ago By Mitali Gupta
How to identify Stack Questions? How to identify Stack Questions?

In this article, you will get clarity about how to find any given question that can be solved using stack.

1 year ago By Aniket Prajapati
How to connect aws RDS instance using mysql workbench

Learn to connect RDS instance(mysql/mariadb) using mysql workbech.

1 year ago By Santosh Kshirsagar