I need to synchronize ressources from a master server to a slave server. I use rsync because it can synchronize folder recursively using incremental file list. I have been able to make it work the simpliest way using ssh-keys. Everything is fine but it doesn't work through php shell_exec function. Here is what I have done so far, and where I am getting stuck. Help would be appreciated!
Master and slave servers are on ubuntu 14.04.4
Creation of the ssh-key folder within user's home directory.
mkdir ~/.ssh
chmod 0700 ~/.ssh
Creation of a private / public ssh key with no passphrase
ssh-keygen -f ~/.ssh/id_rsa -q -P ""
Unsure slave server can receive master public ssh key
// log in slave server
mkdir ~/.ssh
chmod 0700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 0644 ~/.ssh/authorized_keys
Copy public key to the slave server (where I want to synchronize ressources)
// log in master server
su ssh-copy-id -i ~/.ssh/id_rsa.pub [slave user]@[slave host]
Test synchronisation of an existing folder... let's say www/js/
rsync -avz -e "ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress ~/www/js/ [slave user]@[slave host]:~/www/js/
Yay, all works fine.
I log on slave server, remove www/js folder recursively.
I log on master server
I create a simple php script to test if it work within as a "shell command"
test.php
var_dump(shell_exec('rsync -avz -e "ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress ~/www/js/ [slave user]@[slave host]:~/www/js/'));
The synchronization doesn't work from php. Probably because php runs width www-data user? How can I make it work safely from pĥp?
As suggested by symcbean, my previous answer was is a security risk. Making www-data able to access remote hosts without password may be really dangerous. A better approach is to set up a linux user, lets say "wwwsync", that will handle rsync with remote hosts, and let www-data execute rsync "under wwwsync user". That way, we can control / secure rsync by setting up what wwwsync user can and cannot do.
Creation of a linux user that will handle synchronization (let's say wwwsync), and create the ssh-key folder within user's home directory.
// log as root user
adduser wwwsync
// log as wwwsync
su wwwsync
// create ssh folder for ssh key creation
mkdir ~/.ssh
chmod 0700 ~/.ssh
Creation of a private / public ssh key with no passphrase
ssh-keygen -f ~/.ssh/id_rsa -q -P ""
Unsure slave server can receive master public ssh key
// log in slave server
mkdir ~/.ssh
chmod 0700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 0644 ~/.ssh/authorized_keys
Copy public key to the slave server (where I want to synchronize ressources)
// log in master server as wwwsync
su ssh-copy-id -i ~/.ssh/id_rsa.pub [slave user]@[slave host]
Make www-data user (php) able to perform rsync under wwwsync user
// log in as root
su root
// edit sudo configuration
sudo visudo
// add this line at the bottom of the file
www-data ALL=(wwwsync) NOPASSWD: /usr/bin/rsync
This line will then work properly from php
shell_exec('rsync -H -u wwwsync -avz -e "ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress ~/www/js/ [slave user]@[slave host]:~/www/js/')
Next important step : Make sure that wwwsync has rights and permissions properly set, according to your needs, so www-data won't synchronize unwanted ressources to your remote servers.
** edit : this answer is not a secure. Please see my other answer **
I finally found out how to make it work
copy private ssh-key to www-data's home folder. Then php will be able to rsync through shell_exec function
www-data's home folder is /var/www/ (in my case Ubuntu 14)
create .ssh folder if not present
mkdir /var/www/.ssh
chown www-data /var/www/.ssh
chmod 0700 /var/www/.ssh
copy ssh key and set proper rights
cp ~/.ssh/id_rsa /var/www/.ssh
chown www-data /var/www/.ssh/id_rsa
chmod 0600 /var/www/.ssh/id_rsa
This line now works for me :
shell_exec('rsync -avz -e "ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress [absolute_path]/www/js/ [slave user]@[slave host]:~/www/js/');
If it helps someone...
But since I know a lot in security but can't say I'm a specialist, I wonder if that is secure ?