Rsync Over SSH without a Password

I looked over my website creation process, and decided that I needed to find a quicker, more secure way to move my website from my local computer to my webserver.

My process so far has been to use Jekyll to create my static HTML website, and then to rsync the changes to the server.

The problems I have identified with this method:

  • Jekyll regenerates all pages, changing the dates
  • Rsync sends without encryption
  • Rsync takes a long complicated command to make the connection
  • I have to remember many passwords to publish all of my sites

The first step is to generate a SSH Keypair.

1
ssh-keygen -t rsa -b 2048

When you run the command you will be asked to enter the path to store the key and the name of the key. The next prompt will be a passphrase. For an automated ststem, just push enter to set an empty passphrase. /home/username/.ssh is a common location for keys to be stored.

The next step is to install the public key on the server.

1
ssh-copy-id -i /key-dir/key-name username@servername

This will install the key. A test you should be able to perform at this point is to SSH into the remote machine with the new key.

1
ssh -i /key-dir/key-name

Now log into the remote server normally. You need to find the rrsync script, which is provided by the rsync developers. I recommend extracting it and placing it in /home/user/bin. Make sure its owned by your user.

rrsync is designed to allow rsyncing to a specific directory and no others.

The next step is to edit the authorized_keys file. You need to add the following to the beginning of the row with the key you are going to use for automated rsyncing. (You do not have to add this, but it does make things more secure.)

1
command="$HOME/bin/rrsync $HOME/public_html",no-agent-forwarding,no-port-forwrding,no-pty,no-user-cc,no-X11-forwarding

put a space between that and the start of the key. Now if you use any command, but rsync with that key the connection will fail.

Now it is time to create the rsync command to use. The command which works for my needs is:

1
rsync --verbose --compress --hard-links --checksum --recursive --rsh="ssh -i /key-dir/key-name" /path-to-website-files/ username@servername:

My complete deployment script is:

1
2
3
4
5
6
7
8
9
#! /bin/bash

KEYLOCATION="/key-dir/key-name"
LOCALWEBSITEFILES="/path-to-website-files"
REMOTEUSERNAME="remote-username"
REMOTESERVER="remote-server"

jekyll build
rsync --verbose --compress --hard-links --checksum --recursive --rsh="ssh -i $KEYLOCATION" $LOCALWEBSITEFILES $REMOTEUSERNAME@$REMOTESERVER:

I am using this to upload my website after writing new articles. I added the command jekyll build before the rsync command in a deploy.sh script. Now I can use one command to publish my website. Jekyll reginerates the whole site every time I run the build command, so I added the checksum flag to rsync to upload only files which have really changed. There are shorthand versions of the rsync flags, but since I wrote a script I wanted to read the command and know the flags. With this new setup publishing my Jekyll sites has become very easy.

Written on April 23, 2016