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