How to Update Your Website with rsync

Did you ever upload a website via FTP, scp, or even a clunky web uploader?

This can be quite cumbersome. Especially, when you forget to upload certain files and as a result, your website is broken. And doing this over and over again and trying very hard to make no mistakes can really break your spirit.

There must be a better way.

And there is! You can just sync the local directory where you keep the code of your website with rsync. This amazing tool will check each file and each subdirectory and make sure that the files that are on your server are in sync with the files on your computer. It can also delete all files that exist on the server but not on your local machine.

my-website/
├── css/
|   ├── mobile.css
│   └── style.css
├── downloads/
|   ├── download.zip
│   └── ...
├── fonts/
│   └── ...
├── js/
|   ├── jquery.js
│   └── ...
├── images/
│   └── ...
├── index.php
├── about.php
├── ...
└── sync.sh

Let’s say we have a classic PHP website. You can then just add a sync.sh script at the root of your project directory:

The contents of the script should look like this:

#!/bin/bash

SSH_USER="user"
SERVER_IP="my-website.com"
HTML_PATH="/var/www/my-website.com"
PROTECT_FILE="downloads/download.zip"

rsync --filter "protect $PROTECT_FILE" \
      --delete \
      --exclude sync.sh \
      --exclude .git \
      --exclude .gitignore \
      --perms \
      --owner \
      --group \
      --chown=$SSH_USER:www-data \
      --chmod=D775,F664 \
      -v \
      -r . \
      $SSH_USER@$SERVER_IP:$HTML_PATH

Once you adapt the variables at the beginning of the script to your environment, the script will sync your server with your local project directory whenever you run it from your project directory.

The script tells rsync to delete all files that exist in the target directory on the server but not in the local project directory. The only exception is the PROTECT_FILE in the downloads directory. This feature allows me to manually upload large files to the server without having to keep them in my local project directory. If you don’t need this feature just remove the --filter parameter at the beginning of the rsync command.

Since I use git to manage my project the .git directory and the .gitignore file are excluded from rsync. It will not sync them to the server and just ignore them. The same is true for the sync.sh script itself.

Permissions for the files on the server are set to 664 and permissions for directories are set to 775. Ownership of all synced files and directories on the server is changed to the provided SSH user and the group www-data.

Parameters

Here is a detailed explanation of all parameters:

Parameter(s)Description
–filter “protect $PROTECT_FILE”Protect the given server-side file from deletion
–deleteDelete all files that exist on the server but not on the local machine
–exclude sync.sh
–exclude .git
–exclude .gitignore
Ignore the sync script itself as well as the .git directory and the .gitignore file
–perms
–owner
–group
Use the permissions, owner, and group given on this command line instead of preserving those attributes of the local files
–chown=$SSH_USER:www-dataChange the user of the server-side files and directories to $SSH_USER and the group to www-data
–chmod=D775,F664Change the permissions of the server-side directories to 775 and the permissions of the server-side files to 664
-vVerbose output
-r .Sync the current working directory recursively

Leave a comment