127

Having a problem that rsync does not set UID and GID as expected, my gut feeling is that rsync should be run as root on the destination machine.

I can't login as root via SSH, since that's disabled for security purposes. The user on the destination machine is able to use sudo.

Is it possible to use rsync with sudo?

6 Answers6

226

On the destination machine

  1. Find out the path to rsync: which rsync
  2. Edit the /etc/sudoers file: sudo visudo (see also: must I use visudo?)
  3. Add the line <username> ALL=NOPASSWD:<path to rsync>, where username is the login name of the user that rsync will use to log on. That user must be able to use sudo

Then, on the source machine, specify that sudo rsync shall be used:

rsync ... --rsync-path="sudo rsync" ...

Using it without the NOPASSWD on the destination machine will result in the message

sudo: no tty present and no askpass program specified

19

My solution is to use --rsync-path="sudo rsync", if it ask for password you can use workaround like this:

rsync -avz --stats --rsync-path="echo <SUDOPASS> | sudo -Sv && sudo rsync"  user@192.168.1.2:/ .

However, it is better to not type your password on the commandline, where it sill be stored in terminal history. Instead, you can use read -s to prompt for the password without showing it:

read -s -p "Remote sudo password: " SUDOPASS && rsync -avz --stats --rsync-path="echo $SUDOPASS | sudo -Sv && sudo rsync"  user@192.168.1.2:/ .

(Note: -p to prompt isn't supported in all shells (e.g. zsh), if you get an error you can leave it off, or echo before reading instead)

Bulat
  • 371
9

You can have the remote sudo ask you for your password through X-windows. Here's a way to do that:

  1. Make sure ssh-askpass is installed on the remote host (and that you are using X-windows, of course)
  2. Make sure this is in /etc/sudo.conf:
# Path to askpass helper program
Path askpass /usr/bin/ssh-askpass
  1. Add these options to rsync: -e "ssh -X" --rsync-path="sudo -A rsync"

    • ssh -X will forward your X-windows information and port to your remote session
    • sudo -A will make sudo use ssh-askpass to ask you for your password
6

The solutions which suggest modifying /etc/sudoers or echoing the password into a pipe didn't feel comfortable.

Instead, I've found success with the answer posted here. My slight modification prepends a sudo to the rsync call in the second line in order to have unrestricted write permissions on the local machine as well.

stty -echo; ssh myUser@REMOTE_SERVER "sudo -v"; stty echo  
sudo rsync -avze ssh --rsync-path='sudo rsync' myUser@REMOTE_SERVER:/REMOTE_PATH/ /LOCAL_PATH/
  • The first line validates the user's sudo credentials, and ensures that the sudo timestamp is updated on the remote host, allowing subsequent sudo commands to run without requiring a password for a short period.

  • The second line performs the rsync operation with sudo privilege on both the local host and the remote host.

2

If there is no access to sudoers file, just create a wrapper script for the ssh command.

ssh_sudo:

{ 
  echo $PASSWORD;
  cat - ;
} | ssh $* &

At first, this passes the password to the ssh client's sudo process in order to start rsync on the remote side. Next all input coming from the local rsync is piped to ssh.

Finally call rsync e.g. with:

PASSWORD=<SUDOPASS> rsync -avzue ssh_sudo --rsync-path "sudo -S rsync" SRC DST

I guess the security aspect here is not that bad, you'll only have to save the password locally as env var. Reading it from a file should work as well...

1

When trying to solve this same problem in the ansible synchronize module, I came across this question and would like to draw some attention to the solution https://askubuntu.com/a/1263657/874618 by Simon Schmid. Can't upvote or comment using my account (not enough reputation points), so I'll post this as another answer:

Simon's solution not only is the safest alternative in that it requires no changes to sudoers and passes the password using the environment (so that it will not pop up in history files and logs), it also works without changes to the target machine, which is very convenient if you want to rsync to lots of fresh machines and do not want to reconfigure them just for this command.

After playing around with it a bit, I've managed to inline the shell commands used for wrapping ssh on the host machine as well, so it is possible to just use a single rsync line:

PASSWORD=<SUDOPASS> rsync -avzue '/bin/sh -c "{ echo $PASSWORD; cat - ; } | ssh $0 $* &"' --rsync-path "sudo -S rsync" SRC DST

Happy syncing ;-)