Docker & DevOps

Deploy a website to a VPS with Git over SSH

Push code to your VPS and have it deployed automatically: deploy keys, a bare repository with a post-receive hook, and a simple pull-based alternative.

IntermediateLinux VPS3 min read

Uploading files by FTP is slow and error-prone. A Git deploy puts each release on the server straight from version control, so you always know what is live and can roll back. This guide shows two reliable ways to deploy a website to a VPS with Git over SSH.

Before you start

  • A Linux VPS with Git installed (apt install git or dnf install git) and a deploy user, for example deploy.
  • Your site in a Git repository, locally and/or on GitHub, GitLab or Bitbucket.
  • SSH key login to the server working.

Option 1: pull from GitHub with a deploy key

Best when your code already lives on a Git host.

  1. On the server, as the deploy user, create a key for the server itself:
    ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -N ""
  2. Add the contents of ~/.ssh/deploy_key.pub to the repository as a read-only Deploy key (GitHub: Settings → Deploy keys → Add deploy key).
  3. Tell SSH to use it, in ~/.ssh/config:
    Host github.com
        IdentityFile ~/.ssh/deploy_key
        IdentitiesOnly yes
  4. Clone into the web root:
    git clone git@github.com:you/site.git /var/www/site
  5. Deploy each update with:
    cd /var/www/site && git pull --ff-only

A deploy key gives access to one repository only, which is safer than putting your personal key on the server.

Option 2: push to deploy with a bare repository

Here the server hosts its own repository and deploys whenever you push.

  1. Create a bare repository on the server:
    git init --bare /home/deploy/site.git
  2. Create the hook /home/deploy/site.git/hooks/post-receive:
    #!/bin/bash
    TARGET=/var/www/site
    GIT_DIR=/home/deploy/site.git
    BRANCH=main
    while read oldrev newrev ref; do
      if [ "$ref" = "refs/heads/$BRANCH" ]; then
        git --work-tree="$TARGET" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
        echo "Deployed $BRANCH to $TARGET"
      fi
    done
  3. Make it executable and make sure the deploy user owns the target:
    chmod +x /home/deploy/site.git/hooks/post-receive && mkdir -p /var/www/site && chown deploy: /var/www/site
  4. On your computer, add the server as a remote and push:
    git remote add production deploy@203.0.113.10:/home/deploy/site.git
    git push production main

Add build steps to the hook as needed, for example composer install --no-dev, npm ci && npm run build, or systemctl restart myapp (allowed through a narrow sudo rule).

Keep secrets and uploads out of Git

  • Store .env and config files with passwords only on the server and list them in .gitignore.
  • Keep user uploads (for example wp-content/uploads) outside the deployed tree or ignored, so checkout -f never touches them.
  • Block web access to .git if the repository sits in the web root: in Nginx, location ~ /\.git { deny all; }.

Roll back a bad release

With option 1, check out the previous commit:

git log --oneline -5 && git checkout <commit>

With option 2, revert locally and push again (git revert HEAD && git push production main), so history stays accurate.

Troubleshooting

  • Permission denied (publickey) on clone: the deploy key is not added to the repository, or SSH is not using it. Test with ssh -T git@github.com.
  • Hook does not run: it must be executable and named exactly post-receive with no extension.
  • git pull refuses: local changes: someone edited files on the server. Commit them in the repo instead, or discard with git checkout -- . after checking.

Git deployment FAQ

Is git pull on the server safe?

Yes for simple sites, as long as .git is not web-accessible and secrets are not committed. For zero-downtime releases use a release-folder tool or CI/CD.

Can I use Git deployment on cPanel hosting?

Yes, cPanel → Files → Git Version Control can clone repositories and deploy with a .cpanel.yml file.

Do I need CI/CD?

Not to start. Add a pipeline once you want automatic tests and builds before each deploy.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.