66

I want to sync a folder from my machine with a folder on a remote machine. The remote folder can only be manipulated by root. I have an account on the remote machine which can use sudo. How can I run rsync such that it has root permissions on the remote machine?

I've tried the following:

rsync -avz -e ssh /home/ubuntu/my/lovely/folder ubuntu@x.x.x.x:/remote/lovely/folder --delete --rsync-path="sudo rsync"

But (after entering my password) I get the following error:

sudo: no tty present and no askpass program specified
Peter
  • 967

11 Answers11

43

Try this solution. In your sudoers file (/etc/sudoers) setup your user like this:

username ALL= NOPASSWD:/usr/bin/rsync

the NOPASSWD:/usr/bin/rsync tells sudo that when your user runs /usr/bin/rsync or just rsync that no password is needed.

Then your original --rsync-path="sudo rsync" should work.

ki9
  • 115
  • 7
dynabaul
  • 539
17

I'm amazed by the complexity of the existing answers! It's far easier to configure the remote host so that you can connect as root from specific clients without using a password. And although it may sound scary, it is quite secure.

  1. On the remote host make sure that /etc/ssh/sshd_config has this line PermitRootLogin without-password (in many distributions it's there by default). This allows root to get an ssh shell using any authentication method except the insecure password prompt.
  2. (If you don't already know how) follow any of the many tutorials on how to obtain passwordless login via ssh
  3. Use rsync as you would normally do and without any password prompts.

Just don't forget that after step 2, and for as long as you don't remove the line that was added in /root/.ssh/authorized_keys, your client can connect as root to the remote host.

ndemou
  • 1,280
  • 1
  • 13
  • 21
13

This is the solution I came up with:

rsync -R -avz -e ssh --rsync-path="echo mypassword | sudo -S  mkdir -p /remote/lovely/folder && sudo rsync" /home/ubuntu/my/lovely/folder ubuntu@x.x.x.x:/remote/lovely/folder --delete

Bit of a mission!

Peter
  • 967
11

The solution on this blog worked really well for me: http://www.pplux.com/2009/02/07/rsync-root-and-sudo/.

Basically:

stty -echo; ssh myUser@REMOTE_SERVER "sudo -v"; stty echo  
rsync -avze ssh --rsync-path='sudo rsync' myUser@REMOTE_SERVER:/REMOTE_PATH/ LOCAL_PATH 

The first line allows for interactive password entry, without showing the password on the screen. Works great for me on Ubuntu 9.04.

Andrew
  • 351
7

on remote machine

sudo apt install ssh-askpass
which ssh-askpass

then on local machine

rsync -av -e 'ssh -X' --rsync-path='SUDO_ASKPASS=/usr/libexec/openssh/ssh-askpass sudo -A rsync' /some/local/path user@remote:/some/remote/path

substitute path to ssh-askpass with actual path on remote machine

source: http://unix.bris.ac.uk/2015/08/04/rsync-between-two-hosts-using-sudo-and-a-password-prompt/

wotanii
  • 179
4

Here is what worked for me, considering that I want to keep password authentication (so I don't want to use NOPASSWD or keys) - on Ubuntu 14.04:

  • "Open up" sudo on remote machine by disabling tty_tickets through a temporary file in /etc/sudoers.d/ (which should be supported on Debian, see /etc/sudoers.d/README), and "Update the user's cached credentials", which "extends the sudo timeout for another 15 minutes"
  • Run the rsync with sudo as shown in other answers
  • "Close down" sudo on remote machine by removing the temporary file in /etc/sudoers.d/, which re-enables tty_tickets

... or, with command lines:

ssh -t $REMOTEPC 'echo "Defaults !tty_tickets" | sudo tee /etc/sudoers.d/temp; sudo -v'
rsync -aP -e 'ssh' '--rsync-path=sudo rsync' /etc/pulse/client.conf $REMOTEPC:/etc/pulse/client-copy.conf
ssh -t $REMOTEPC 'sudo rm -v /etc/sudoers.d/temp; sudo -v'

These are the responses I get when running these commands on the local machine:

$ ssh -t $REMOTEPC 'echo "Defaults !tty_tickets" | sudo tee /etc/sudoers.d/temp; sudo -v'
remoteuser@$REMOTEPC's password: 
[sudo] password for remoteuser: 
Defaults !tty_tickets
Connection to $REMOTEPC closed.

$ rsync -aP -e 'ssh' '--rsync-path=sudo rsync' /etc/pulse/client.conf $REMOTEPC:/etc/pulse/client-copy.conf
remoteuser@$REMOTEPC's password: 
sending incremental file list
client.conf
           1269 100%    0.00kB/s    0:00:00 (xfr#1, to-chk=0/1)

$ ssh -t $REMOTEPC 'sudo rm -v /etc/sudoers.d/temp; sudo -v'
remoteuser@$REMOTEPC's password: 
removed ‘/etc/sudoers.d/temp’
[sudo] password for remoteuser: 
Connection to $REMOTEPC closed.

Note that sudo -v should be ran after each time files in /etc/sudoers.d/, so the changes therein are accepted.

sdaau
  • 6,008
4

You need a method to supply the password to sudo. An askpass program is designed to ask for passwords when the normal mechanisms aren't available. Setting up sudo to not require a password to run rsync as your userid is one option.

I normally configure key based login with appropriate restrictions for cases like this. If you configure a restricted key that an only run rsync as root then this kind of thing gets easier to do. Another alternative is to use an rsycnd process to handle the remote requests. The configuration provides a variety of restrictions that can be applied.

EDIT: I included a script to setup keys for key based loings in the Creating Userids on Clients section of my post on Setting up BackupPC on Linux. See also the documenation for ssh_config which details some of the things you can do with resticting key usage as shown in the script.

BillThor
  • 11,345
  • 2
  • 28
  • 25
0

Another method is to get around the permissions restrictions by initiating rsync on the remote machine. Instead of:

rsync /home/ubuntu/my/lovely/folder ubuntu@x.x.x.x:/remote/lovely/folder

You can do:

ssh ubuntu@x.x.x.x 'rsync ubuntu@y.y.y.y:/home/ubuntu/my/lovely/folder /remote/lovely/folder'

Where y.y.y.y is your local machine's IP address. This only works if your local machine can act as an SSH server.

ki9
  • 115
  • 7
0

My workuround is to add --rsync-path="echo PASSWORD | sudo -Sv && sudo rsync"

example:

rsync -avz -e ssh /home/ubuntu/my/lovely/folder ubuntu@x.x.x.x:/remote/lovely/folder --delete --rsync-path="echo <PASSWORD> | sudo -Sv && sudo rsync"

It usually isn't a good idea to put passwords into a command line one-liner; they become visible in the process tree, for example. I sometimes replace the actual password in this type of statement with $( cat my_password.txt ) which is slightly better

rsync -avz -e ssh /home/ubuntu/my/lovely/folder ubuntu@x.x.x.x:/remote/lovely/folder --delete --rsync-path="cat my_password.txt | sudo -Sv && sudo rsync"

Bulat
  • 101
0

Run as cronjob in the background

Ok, so you have a few options here.

The ones above are pretty good when it comes to rsync as a normal user with sudo permissions on (both) other side(s).

I had this same problem, the only difference was that I wanted to run this as a cronjob at night.

Step 1

I work with ssh-keys (this makes it possible to login to a remote host without password authentication while still being very secure!!)

  1. Create a ssh-key on your source computer (server) with the following command:
ssh-keygen

You will be prompted a few options, just press enter every time (do not (enter) set a password!!).

This command creates 2 different keys. 1. An id_rsa_pub key: this key needs to be copied to the remote (destination server) host. 2. An id_rsa: this is a private key and you do not want to mess with this key. Make sure no one can see this key (read permissions). Only you should have the right to see this key.

Step 2

  1. The moment you have generated the keys, it is time to copy the id_rsa_pub key to the remote computer (server). You can do this with the following command:
ssh-copy-id user@remoteserver.example

You will be prompted to fill in your password for default ssh access. Just enter your password and the ssh-copy-id command will do the rest for you.

Time to test

  1. Now, ssh into the remote server (the destination you used with the ssh-copy-id command).

You can consider the test successful if you do not get to see a prompt to enter a password.

Now you can do rsync commands to a remote host without having to fill in a password all the time! Also you can autocomplete on the destination host from within your source host. That is pretty neat if you ask me (example ssh 192.168.1.100: "press two time the tab button to autocomplete the rest of the command. Note that the ip address 192.168.1.100 is the ip address of the destination server).

Now you can do a rsync command from a cronjob with a normal "sudo" user (no need for root access on both servers for ssh for using user root).

Just do the same as described above, but add one option:

sudo rsync --rsync-path="sudo rsync" -az --delete -e "ssh -p 1022 -l **buser** -i /home/**buser**/.ssh/id_rsa" /path/to/rsync user@destinationserver.example:

Note that buser (BackupUSER, is my user who uses the ssh-key to login through ssh without being prompted for a password). Change buser to your username who uses the ssh-key login method.

Note the last character in the command ends with a ":" This means that you are copying files to the home folder of the remote user. If you want to deviate to another location outside your home directory, you can achieve this by adding the absolute path after the ":" For example:

sudo rsync --rsync-path="sudo rsync" -az --delete -e "ssh -p 1022 -l **buser** -i /home/**buser**/.ssh/id_rsa" /path/to/rsync user@destinationserver.example:/srv/backup_folder

Explaining the option "ssh -p 1022 -l username -i /home/username/.ssh/id_rsa"

ssh -p 1022 ssh uses the default port 22. I deviate from the default port because my ssh-server listens to port 1022.

-l username the user defined who can login to the remote host with the ssh-key authentication method. In my case, this is the user BUSER.

-i (stands for Identity) uses the private key which we created with the ssh-keygen command. It points to where this key is stored. The default location is in the users home folder in a hidden directory called ssh (/home/username/.ssh/id_rsa).

I hope this will help other users to automate their backup through cron in a secure matter.

Double check

From the source machine (server), make sure you execute your command (script) as the ROOT user (if you make a cronjob, you have to make sure that you are the user root (#) when creating the cronjob)

Make sure the user on the destination server has sudo rights.

Make sure you have done the visudo as Keith describes in his answer!

0

Another nice solution, that I found while setting up rsync on my root-lacking Android phone:

Daemon-based solution

You can also just run the remote rsync as a daemon on localhost, and then tell the local rsync to forward the port to the local localhost, and connect to that!

First, on the remote system, create a rsyncd.conf:

address = 127.0.0.1
port = 18730

[MyConnectingHostname] path = /home/ubuntu/my/lovely/folder use chroot = false read only = false

(Replace MyConnectingHostname by the host name of the connecting machine.)

E.g. by scping a prepared one over:

scp rsyncd.conf ubuntu@x.x.x.x:

Now start rsync on the remote system, like so:

ssh -t ubuntu@x.x.x.x \
  sudo rsync --daemon --config=/home/ubuntu/rsyncd.conf --log-file=/dev/null

Note that -t makes a pseudo-TTY, so that sudo can ask for a password.

And connect you local rsync to the port that ssh is told to forward:

sudo rsync -avz \
  -e 'ssh -L 18730:localhost:18730' --delete \
  /home/ubuntu/my/lovely/folder \
  ubuntu@localhost:18730:/home/ubuntu/my/lovely/folder

If you don’t need it anymore, you can now kil rsync and delete the conf file again:

ssh -t ubuntu@x.x.x.x sudo killall rsync
ssh ubuntu@x.x.x.x rm rsyncd.conf

(Change the killall to something diffrent, if the remote system may run more than one rsync instance at the same time.)