Skip to content

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.

  1. Connect your source control provider to Laravel Forge. source-file
  2. 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. server-provider

Create a New Server on Laravel Forge

  1. Create a new server on Laravel Forge.
  2. Choose the server size, region, and type (e.g., "App Server").
  3. Make sure to select the server type that comes with PHP, MySQL, Redis, Memcached, and Nginx pre-installed

create-server

Copy Server Credentials

Copy the server credentials (Sudo Password & Database Password) to a safe place, as you might need them later.

credentials

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

  1. Create a new site for your app on the server.
  2. Enter the domain name of your app in the "Root Domain" field.
  3. Click "Add Site".

site

Install Application

  1. Click on "Install Application".
  2. Select the repository that you want to deploy (e.g., your-username/jetship).
  3. Choose the branch to deploy (typically main).
  4. Click "Install Repository". install-appinstall-repo

Deployments

  1. Navigate to Deployments through left navigation menu.
  2. 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.