Deploy a site with a git push
Push-to-deploy means you run one command on your computer, git push, and your server updates the live site by itself. The server holds a bare Git repository, and a small hook copies each new commit into the folder your web server reads from.
Before you begin
- A VPS running Ubuntu 24.04 LTS with SSH access as a user with sudo rights, such as alex.
- A project in a Git repository on your computer, with its main branch named
main. - A web server that serves
/var/www/site. Set that up separately, for example with nginx.
Step 1: Install Git and create a deploy user
Install Git on the server, then create a deploy account that owns the site and the repository. Keeping deployments under their own user means a mistake in your app cannot damage the system files.
sudo apt update
sudo apt install -y git
sudo adduser --disabled-password --gecos "" deploy
Give the deploy user your SSH public key so you can push as that user. Copy the key into place and fix its permissions, since SSH refuses keys in folders anyone else can write to:
sudo mkdir -p /home/deploy/.ssh
sudo cp ~/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys
Step 2: Create the bare repository and the site folder
A bare repository holds the Git history but no working files. It is the place you push to. The site folder is where the real files live. The --bare flag is what makes the repository "bare".
sudo mkdir -p /srv/git /var/www/site
sudo git init --bare /srv/git/site.git
sudo chown -R deploy:deploy /srv/git/site.git /var/www/site
Initialized empty Git repository in /srv/git/site.git/
Step 3: Add the post-receive hook
Git runs a file named post-receive in the repository's hooks folder after every push. The script below checks out the pushed main branch into the site folder. The --work-tree option tells Git where to put the files, and -f overwrites local edits so the server always matches the repository.
sudo nano /srv/git/site.git/hooks/post-receive
#!/bin/bash
set -e
git --work-tree=/var/www/site --git-dir=/srv/git/site.git checkout -f main
echo "Deployed main to /var/www/site"
Make the hook executable and give it to the deploy user. Git silently skips hooks that are not executable, which is a common source of confusion.
sudo chmod +x /srv/git/site.git/hooks/post-receive
sudo chown deploy:deploy /srv/git/site.git/hooks/post-receive
Step 4: Add the server as a remote on your computer
On your own computer, inside your project folder, add the server as a second remote named production. A remote is just a named address for a repository.
git remote add production deploy@203.0.113.10:/srv/git/site.git
git remote -v
production deploy@203.0.113.10:/srv/git/site.git (fetch)
production deploy@203.0.113.10:/srv/git/site.git (push)
Step 5: Push and watch it deploy
Push your main branch to the production remote. Git sends the commits, runs the hook, and prints what the hook says back to your terminal.
git push production main
remote: Deployed main to /var/www/site
To 203.0.113.10:/srv/git/site.git
* [new branch] main -> main
Check the result on the server. Your files should now be in /var/www/site:
ls -la /var/www/site
git push production main. Keep a copy of the repository on your computer as the source of truth.checkout -f discards any changes made directly in /var/www/site. Make edits on your computer and push them, never by hand on the server.Troubleshooting
- "Permission denied (publickey)". Your key is not in
/home/deploy/.ssh/authorized_keys, or the permissions are wrong. Confirm withssh deploy@203.0.113.10, then re-check Step 1. - The push works but the site does not change. The hook is probably not executable, or the branch is not
main. Runls -l /srv/git/site.git/hooks/post-receiveand check that it showsxin the permissions. - "fatal: not a git repository". The path in your remote is wrong. It must point at
/srv/git/site.git, the bare folder, and not at the site folder. - "error: Your local changes would be overwritten". Someone edited files in
/var/www/sitedirectly. Restore them to match the repository withsudo -u deploy git --work-tree=/var/www/site --git-dir=/srv/git/site.git checkout -f main, then avoid editing on the server.
Next steps
Point your web server at /var/www/site if it does not already. Then consider adding a second remote for a staging copy, so you can test changes before they reach the live site. For the web server side, see the guide on troubleshooting a site that is down.
Something not working? Chat or email our support team and we will help you get unstuck.
Contact support