← All posts

Tutorial DevOps

How to Deploy a PHP App to a LAMP Server with Git Hook

Automate PHP deployments using a Git post-receive hook. Push your code locally and update your LAMP server instantly.

Difficulty Intermediate Time 20 min
Git post-receive hook deploying a PHP app to a LAMP server with Composer and Apache reload

Deploying code via FTP is slow, error-prone, and belongs in the past. In this tutorial, we will set up a simple push-to-deploy pipeline using a Git post-receive hook. You will create a bare Git repository on your LAMP server that listens for incoming code. When you push from your local machine, the hook will automatically extract the files into your public web root. By the end, your deployment process will be as simple as a single Git push.

Prerequisites

  • A LAMP server (Linux, Apache, MySQL, PHP) with SSH access
  • Git installed on both your local machine and the server
  • A local PHP project already tracked by Git
  • A non-root user on the server with sudo privileges

Step 1 — Prepare the Web Root Directory

First, log into your server via SSH. We need a target directory where the live PHP application will reside. Let us assume we are deploying to /var/www/myapp. Create the directory:

sudo mkdir -p /var/www/myapp

Your standard SSH user needs permission to write to this directory during the deployment process. Change the ownership to your user (replace youruser with your actual SSH username) while keeping the group as the web server group (typically www-data):

sudo chown -R youruser:www-data /var/www/myapp sudo chmod -R 775 /var/www/myapp

Step 2 — Create a Bare Git Repository

A bare repository is a Git repository without a working tree. It does not contain your actual project files; it only contains the version control history, making it perfect for receiving pushed code. Create a directory to hold your repositories, usually in your home folder:

mkdir -p ~/git/myapp.git cd ~/git/myapp.git

Initialize the bare repository:

git init --bare

You will see a message confirming the empty Git repository has been initialized.

Step 3 — Write the post-receive Hook

Git triggers scripts called hooks at specific points in the version control process. The post-receive hook runs immediately after the bare repository receives a push. Create the hook file:

nano hooks/post-receive

Paste the following script into the editor. Be sure to update the directories if yours are different:

#!/bin/bash # Define variables TARGET="/var/www/myapp" GIT_DIR="/home/youruser/git/myapp.git" BRANCH="main" Check out the main branch to the web root while read oldrev newrev ref do if [[ $ref = refs/heads/$BRANCH ]]; then echo "Ref $ref received. Deploying ${BRANCH} branch to production..." git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH else echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server." fi done

This script checks if the push was to the main branch. If it was, it forces a checkout of those files directly into your web root directory (/var/www/myapp).

Step 4 — Make the Hook Executable

Save and close the file. For Git to run the script, it must have executable permissions. Run this command:

chmod +x hooks/post-receive

Your server is now ready to receive code and deploy it.

Step 5 — Configure the Remote on Your Local Machine

Open a terminal on your local computer and navigate to your existing PHP project folder. You need to tell your local Git repository about the new server repository. Add a remote named production:

git remote add production youruser@your_server_ip:/home/youruser/git/myapp.git

Verify the remote was added correctly:

git remote -v

Step 6 — Push to Deploy

Now for the magic. Push your main branch to the new production remote:

git push production main

In your terminal output, you will see standard Git push logs, followed by the custom deployment message from your hook: Deploying main branch to production.... Git has successfully copied your files to the /var/www/myapp directory.

Wrap-up

You have successfully replaced manual FTP uploads with a fast, automated Git deployment pipeline. Every time you run git push production main, your LAMP server will instantly reflect the latest code. From here, you can easily expand your post-receive script to run additional tasks after the checkout, such as executing Composer installs, clearing cache directories, or restarting services.