DEV Community

Brian
Brian

Posted on

🛠️ How to Deploy a Laravel App with Zero Downtime Using Git Hooks

Deploying a Laravel application can be as simple or as sophisticated as you want it to be. If you're working on a small project or don't want the overhead of CI/CD tools, Git hooks provide a lightweight way to automate your deployment — with minimal downtime.

In this tutorial, we’ll walk through setting up a zero-downtime Git-based deployment flow for your Laravel app using a post-receive hook.

🔍 What You'll Need

  • A server (e.g., Ubuntu-based VPS or cloud instance)

  • SSH access

  • Git installed on both local and server

  • A Laravel project under version control

  • Basic Linux terminal skills

Step 1: Prepare the Server

First, SSH into your server:

ssh user@your-server-ip

Enter fullscreen mode Exit fullscreen mode

Install the required packages (if you haven’t already):

sudo apt update
sudo apt install git unzip php-cli php-mbstring php-xml php-bcmath php-curl composer -y

Enter fullscreen mode Exit fullscreen mode

Create a directory where your Laravel app will live:

mkdir -p /var/www/myapp
cd /var/www/myapp

Enter fullscreen mode Exit fullscreen mode

Step 2: Initialize a Bare Git Repository

Create a bare Git repository to receive code from your local machine:

mkdir -p /home/deploy/myapp.git
cd /home/deploy/myapp.git
git init --bare

Enter fullscreen mode Exit fullscreen mode

This bare repo is where your code will be pushed — it won’t contain a working tree (no real files), just Git metadata.

Step 3: Create the post-receive Hook

Inside your bare repo:

cd /home/deploy/myapp.git/hooks
nano post-receive

Enter fullscreen mode Exit fullscreen mode

Paste this script into post-receive:

#!/bin/bash

GIT_WORK_TREE=/var/www/myapp git checkout -f

cd /var/www/myapp

# Install PHP dependencies
composer install --no-interaction --prefer-dist --optimize-autoloader

# Set permissions
chown -R www-data:www-data /var/www/myapp
chmod -R 775 /var/www/myapp/storage

# Laravel setup
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache

Enter fullscreen mode Exit fullscreen mode

Make the hook executable:

chmod +x post-receive

Enter fullscreen mode Exit fullscreen mode

Step 4: Add the Server as a Git Remote on Your Local Machine

Back on your local machine:

git remote add production ssh://user@your-server-ip:/home/deploy/myapp.git

Enter fullscreen mode Exit fullscreen mode

To push your code:

git push production main

Enter fullscreen mode Exit fullscreen mode

This will trigger the post-receive hook and deploy the latest version of your app.

Optional: Zero Downtime with Atomic Deployment

If you want true zero downtime, add atomic deploys using a symlinked current directory:

  1. Push to a timestamped release folder like /var/www/releases/20250507120000

  2. After deployment, update a symlink: ln -sfn /var/www/releases/20250507120000 /var/www/myapp

  3. Your web server always points to /var/www/myapp, which stays live

You can extend the post-receive hook to automate this entire process.

🔐 Bonus Tips for Production

  • Use .env.production and symlink it after each deploy

  • Set up a queue worker supervisor (e.g., with supervisord or systemd)

  • Monitor logs via journalctl or Laravel's /storage/logs/laravel.log

Conclusion

Git hooks offer a powerful, low-cost deployment solution — perfect for solo developers, MVPs, or side projects. With a little scripting and Laravel tooling, you can automate everything and deploy confidently with minimal or no downtime.

Top comments (0)