Uploading to a Production Server with RSYNC

I knew you could use RSYNC to synchronize a local copy of a website with the files on your production server. In fact I’ve known it for long enough to have tried to get it working a few years ago but failed miserably. Well I’ve learned a bit since then (well I like to think so anyway) so I thought I’d give it another go this this morning. And, it was surprisingly easy. In this guide I refer to my local server (a teeny tiny Ubuntu server) as the LOCAL SERVER and the remote production server as the REMOTE SERVER.

Install SSH Key on Remote Server

Firstly I needed to install a SSH key on my REMOTE SERVER so my LOCAL SERVER could log into it without me needing to enter a password every time I wanted to synchronize the files. This is easy enough, on the LOCAL SERVER enter the following:

sudo ssh-keygen

Enter the default values as prompted and this will create a public key in ~/.ssh/ called id_rsa.pub. This file needs to be set to the remote server. This is done easily with:

scp ~/.ssh/id_rsa.pub user@remote_server.com:/home/user/uploaded_key.pub

Then this file needs to be appended to the authorized_keys file on the REMOTE SERVER with:

ssh user@remote_server.com "echo `cat ~/.ssh/uploaded_key.pub` >> ~/.ssh/authorized_keys"

Construct RSYNC Included and Excluded Files / Folders List

If you’re like me your development folders are littered with test files and directories that you don’t want on your production servers. So you’re going to need to create inclusion and exclusion lists for RSYNC to use so it knows what to upload and what not to upload. This is simply done using text files with file / folder specifications on separate lines. For example my include.txt looks something like this:

app
classes
create-scripts
cron-scripts
css
inc
js
images
tooltips
validation_scripts

While my exclude looks something like this:

/app/jscal
/css/img/Thumbs.db
/create-scripts/*.txt
app/test-first-day-of-week.htm
app/test-mcrypt.htm
app/images/Thumbs.db

These files can be written in nano and saved somewhere sensible (probably where you’re going to put your rsync bash script).

Write your BASH script

Next step is to write a very short bash script that includes your RSYNC command. My script looks like this:

#!/bin/bash
rsync  -v -u -r -a --rsh=ssh --stats --progress --files-from=include.txt --exclude-from exclude.txt /srv/windows-share/local-source-files/   user@remote-server:/srv/www/remote-source-files/

Don’t forget you need to make your script executable with something like:

sudo chmod 700 rsync_upload.bsh

Also you’re going to want to test the RSYNC command using the -n (or –dry-run) option to make sure everything works the way you expect it to. You’ll also need to specify the -r (recursive) option because the –files-from directive overrides the implied recursion you get from the -a (archive) option.

Run your Script

So now when you’re done developing and testing files on your development server it’s simply a matter of running your new script to sync the files on your production server. Something like the following will run your script:

sudo /path/to/script/rsync_upload.bsh