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.