Appearance
Laravel Forge Deployment
Zero Downtime Deployment
Imagine deploying new features and updates to your application without interrupting the user experience. Zero-downtime deployment makes this a reality. By ensuring that your application remains available and accessible to users throughout the deployment process, you can avoid lost traffic, maintain customer satisfaction, and reduce the risk of revenue loss. With a zero-downtime deployment script, you can confidently roll out updates, knowing that your users will continue to interact with your application without interruption.
In this guide, we'll walk you through setting up a zero-downtime deployment script for Laravel Forge, empowering you to deploy with confidence and keep your application always-on.
Initial Setup
Before starting the deployment process, let's define some essential variables:
sh
DOMAIN=example.com
PROJECT_REPO="your_github_repo_name"
AMOUNT_KEEP_RELEASES=5
RELEASE_NAME=$(date +%s--%Y_%m_%d--%H_%M_%S)
RELEASES_DIRECTORY=~/$DOMAIN/releases
DEPLOYMENT_DIRECTORY=$RELEASES_DIRECTORY/$RELEASE_NAME
These variables set the stage for the deployment process, including the domain name, project repository, and the number of releases to keep.
Cloning Repository and Configuring Environment
The script begins by creating a unique release directory and cloning the project repository into it:
sh
cd /home/forge/$DOMAIN
mkdir -p "$RELEASES_DIRECTORY" && cd "$RELEASES_DIRECTORY"
git clone "$PROJECT_REPO" "$RELEASE_NAME"
cd "$RELEASE_NAME"
git checkout "$FORGE_SITE_BRANCH"
git fetch origin "$FORGE_SITE_BRANCH"
git reset --hard FETCH_HEAD
Next, the script copies the .env file from the project directory:
sh
printf '\nℹ️ Copy ./.env file\n'
ENV_FILE=~/"$DOMAIN"/.env
if [ -f "$ENV_FILE" ]; then
cp $ENV_FILE ./.env
else
printf '\nError: .env file is missing at %s.' "$ENV_FILE" && exit 1
fi
Running Laravel Commands and Installing Dependencies
The script installs Composer dependencies, restarts FPM, and runs Laravel migrations:
sh
$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader
( flock -w 10 9 || exit 1
echo 'Restarting FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9>/tmp/fpmlock
if [ -f artisan ]; then
$FORGE_PHP artisan migrate --force
fi
Additionally, the script installs NPM dependencies and generates necessary files:
sh
printf '\nℹ️ Installing NPM dependencies based on \"./package-lock.json\"\n'
npm install
printf '\nℹ️ Generating JS App files\n'
npm run build
Building and Linking Deployment Directory
The script links the deployment directory to the current directory:
sh
printf '\nℹ️ !!! Link Deployment Directory !!!\n'
echo "$RELEASE_NAME" >> $RELEASES_DIRECTORY/.successes
if [ -d ~/$DOMAIN/current ] && [ ! -L ~/$DOMAIN/current ]; then
rm -rf ~/$DOMAIN/current
fi
ln -s -n -f -T "$DEPLOYMENT_DIRECTORY" ~/$DOMAIN/current
Cleaning Up and Maintaining Releases
Finally, the script performs clean-up tasks and maintains releases:
sh
printf '\nℹ️ Delete failed releases:\n'
if grep -qvf .successes <(ls -1)
then
grep -vf .successes <(ls -1)
grep -vf .successes <(ls -1) | xargs rm -rf
else
echo "No failed releases found."
fi
printf '\nℹ️ Delete old successful releases:\n'
KEEP_RELEASES=$((KEEP_RELEASES-1))
LINES_STORED_RELEASES_TO_DELETE=$(find . -maxdepth 1 -mindepth 1 -type d ! -name "$RELEASE_NAME" -printf '%T@\t%f\n' | head -n -"$KEEP_RELEASES" | wc -l)
if [ "$LINES_STORED_RELEASES_TO_DELETE" != 0 ]; then
find . -maxdepth 1 -mindepth 1 -type d ! -name "$RELEASE_NAME" -printf '%T@\t%f\n' | sort -t $'\t' -g | head -n -"$KEEP_RELEASES" | cut -d $'\t' -f 2-
find . -maxdepth 1 -mindepth 1 -type d ! -name "$RELEASE_NAME" -printf '%T@\t%f\n' | sort -t $'\t' -g | head -n -"$KEEP_RELEASES" | cut -d $'\t' -f 2- |
Deployment Guide: A Step-by-Step Tutorial
Prepare Your Server
Before starting the deployment process, you need to create a Laravel Forge account and connect your source control provider (e.g., GitHub, GitLab, Bitbucket) to Laravel Forge.
- Connect your source control provider to Laravel Forge.
- Select the server provider where you want to deploy your app (e.g., DigitalOcean, Akamai, AWS, Vultr, or Hetzner). Depending on your cloud provider, you will need to create an API key/secret and enter them in Laravel Forge. This will basically allow Laravel Forge to create and manage servers on your behalf.
Create a New Server on Laravel Forge
- Create a new server on Laravel Forge.
- Choose the server size, region, and type (e.g., "App Server").
- Make sure to select the server type that comes with PHP, MySQL, Redis, Memcached, and Nginx pre-installed
Copy Server Credentials
Copy the server credentials (Sudo Password & Database Password) to a safe place, as you might need them later.
Wait for Server Provisioning
Please allow a few minutes for the server to be fully provisioned and set up. You'll receive an email notification once it's ready to go!
Create a New Site for Your App
- Create a new site for your app on the server.
- Enter the domain name of your app in the "Root Domain" field.
- Click "Add Site".
Install Application
- Click on "Install Application".
- Select the repository that you want to deploy (e.g., your-username/jetship).
- Choose the branch to deploy (typically main).
- Click "Install Repository".
Deployments
- Navigate to Deployments through left navigation menu.
- In Deployments, you can locate a Deployment Script and replace it with the prepared script above.
sh
DOMAIN=example.com
PROJECT_REPO="git@github.com:username/your_github_repo_name.git"
KEEP_RELEASES=5
RELEASE_NAME=$(date +%s--%Y_%m_%d--%H_%M_%S)
RELEASES_DIRECTORY=~/$DOMAIN/releases
DEPLOYMENT_DIRECTORY=$RELEASES_DIRECTORY/$RELEASE_NAME
cd /home/forge/$DOMAIN
mkdir -p "$RELEASES_DIRECTORY" && cd "$RELEASES_DIRECTORY"
git clone "$PROJECT_REPO" "$RELEASE_NAME"
cd "$RELEASE_NAME"
git checkout "$FORGE_SITE_BRANCH"
git fetch origin "$FORGE_SITE_BRANCH"
git reset --hard FETCH_HEAD
printf '\nℹ️ Copy ./.env file\n'
ENV_FILE=~/"$DOMAIN"/.env
if [ -f "$ENV_FILE" ]; then
cp $ENV_FILE ./.env
else
printf '\nError: .env file is missing at %s.' "$ENV_FILE" && exit 1
fi
$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader
( flock -w 10 9 || exit 1
echo 'Restarting FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9>/tmp/fpmlock
if [ -f artisan ]; then
$FORGE_PHP artisan migrate --force
fi
printf '\nℹ️ Installing NPM dependencies based on \"./package-lock.json\"\n'
npm install
printf '\nℹ️ Generating JS App files\n'
npm run build
printf '\nℹ️ !!! Link Deployment Directory !!!\n'
echo "$RELEASE_NAME" >> $RELEASES_DIRECTORY/.successes
if [ -d ~/$DOMAIN/current ] && [ !
Now, click update and after successfully updated the file click on Deploy Now to deploy your app.
Once the deployment is done, you can visit your app's domain to see your app running. And that's it! You have successfully deployed your app to a production server using Laravel Forge. 🎉
Create Admin User
You'll need to manually create admin user in your app.
- First, navigate to the server and your app folder
cd /home/forge/your_domain
- Now, run the command:
php artisan app:create-admin-user
- Save generated password.