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

Introduction to Django

A high-level Python web framework called Django makes it possible for programmers to create web applications rapidly and effectively. It adheres to the Model-View-Controller (MVC) architectural design pattern, placing emphasis on the division of duties and encouraging code reuse. Django offers a comprehensive collection of conventions, frameworks, and tools that speed up development and promote best practises.

Arrays Introduction

An array is a continuous block of memory location which can store data of same datatype.

1 year ago By Aniket Prajapati
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
HashMaps

Hashing is a technique or process of mapping keys, and values into the hash table by using a hash function. It is done for faster access to elements.

1 year ago By Aniket Prajapati