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

Mastering the Fundamentals: Basic HTML Tags for Web Development Mastering the Fundamentals: Basic HTML Tags for Web Development

In this article, we'll explore the Basic HTML elements that form the foundation of every web page.

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
10 common JavaScript interview questions that you might encounter !!!

In this article, we will discuss 10 JS questions that are commonly asked in interviews. These questions cover a range of JavaScript topics and are commonly asked in interviews to assess a candidate's understanding of the language. Make sure to practice and understand these concepts to perform well in JavaScript interviews.

1 year ago By Mitali Gupta
For Laravel Setting UP CI/CD Pipeline using GitHub, CodeDeploy, S3 and EC2

Setting ci/cd pipeline for laravel application on aws using github actions then uploading to s3 and using codedeploy application gets installled on EC2 instance

1 year ago By Santosh Kshirsagar