114

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 Answers 6

204

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

13
  • 5
    Thanks, only I use pki so I used -e="ssh -i $PRIVATE_KEY_PATH" --rsync-path="sudo rsync"
    – A T
    May 15, 2017 at 6:01
  • 4
    Of course <username> can now read/write everything as root using rsync, locally and remote, so the part about not being able to log in as root due to security concerns is kinda moot... cause essentially you're doing that now.
    – hmn
    Aug 2, 2018 at 21:16
  • 1
    @hmn: not exactly. Disabling root access on SSH basis will prevent some brute force login attacks. In my case, I log on with a keyfile and I need a different password for that than for the sudo command. sudo does quite a good job protecting us, e.g. you cannot have an open root shell forever and it gives you logging. I personally like it. Aug 3, 2018 at 6:25
  • 3
    Still getting the "not tty present..." error after following these instructions? I was. Making sure the line I added to /etc/sudoers comes at the end of the file (or after any group rules which may affect the same user) solved the problem for me.
    – CPBL
    Jan 28, 2019 at 1:15
  • 2
    I'm using this solution but would like to improve security by restricting the args the user can pass to rsync on the destination server. Typically I would limit the args that can be used with <username> ALL=NOPASSWD:<path to rsync> <args> but I don't know what the args would be when called remotely like this. Any ideas? Sep 12, 2019 at 1:00
18

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"  [email protected]:/ .

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"  [email protected]:/ .

(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)

3
  • This works great to pull between ec2 instances (minus the echo <SUDOPASS> part). Dont forget to add a Security Group rule to allow port 22 from the sgID itself, to the instances that need it. rsync -aPvhe ssh -A --rsync-path="sudo -Sv && sudo rsync" ec2-user@<privateEC2-IP>:/home/ec2-user/testfile /home/ec2-user Note, the testfile was 700 root:root and this copied the file while maintaining permissions.
    – semtex41
    Dec 15, 2020 at 21:09
  • 5
    Did not work for me. I am getting the error [sudo] password for sysadmin: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper sudo: a password is required
    – Joyce Babu
    Apr 9, 2022 at 9:47
  • I faced @JoyceBabu 's error message. Upon scribbling there seems to be a flaw with the use of read here. read is run before rsync to define a local variable. Yet when --rsync-path injects echo's stdout to sudo -Sv it is calling a remote variable. One could use correct order of quotes (' ") to expand local variable within remote command, yet then the issue of logs and history picking up plain-text password is back on menu. I tried injecting read before echo, but that leaves me with a blank page (not input), and a need to CTRL-C. NOPASSWD works for non-X environment.
    – cbugk
    Feb 20, 2023 at 13:21
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
3
4

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/
2
  • 2
    sudo on rsync is very inelegant.. Surely you'd be better off using a specific user which has permissions on the remove side via facl on the specific directories you want to read or modify. Aug 10, 2021 at 12:39
  • 1
    Actually I find this one the most elegant solution for simple one-off jobs, as it requires no modifications on remote systems. One would need to replace first line with ssh -t myUser@REMOTE_SERVER "sudo -v" instead for most systems, though. For recurring (esp. automated) jobs, other solutions are preferred as noted (including PermitRootLogin prohibit-password in sshd_config and creating key for root access, allowing that key to only run rsync in /root/.ssh/authorized_keys; perhaps even paired with Apparmor/SElinux read-only restrictions for it if one cares extra about security etc) Jan 10 at 8:31
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
  • 1
    PASSWORD=<SUDOPASS> rsync... logs the password into your shell's history, at least for bash
    – studog
    May 5, 2022 at 15:14
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 ;-)

2
  • 1
    PASSWORD=<SUDOPASS> rsync... logs the password into your shell's history, at least for bash
    – studog
    May 5, 2022 at 15:13
  • This is true. However, as described, I use this solution within an automation tool (ansible) that does not log anything entered. There is a very small chance that someone can observe your environment variables from another process, but it sounds like a security misconfiguration anyway if that is possible. May 7, 2022 at 19:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .