Transferring files between servers (without root)
Wednesday, January 3rd, 2024I needed to transfer files between an old server and its replacement. rsync
over ssh
is the obvious tool to use but working out how to use it properly such that all file permissions are preserved under the restriction that it is not possible to ssh as root, and so sudo
is required on both ends. Additionally rsync
cannot be used to transfer files between two remote hosts, one end needs to be local to rsync
. There is a further complication caused by the fact that we cannot type in the sudo
password required by the sudo
on the remote host end on the command line as rsync
is already using that pipe for its own stuff so we need some X-forwarding to give us an independent channel for that and ssh-askpass
to make use of it. The most useful advice came from a 2015 blog from dg12158 at Bristol but I had to add a few things for my use case.
## Preparation
# On source host
sudo apt install rsync # If not already installed
# On destination host
sudo apt install ssh-askpass rsync # If not already installed
## Transfer
# On local host
ssh -AX admin-user@source.host.example.com # To get to source host with ssh-agent and X forwarding
sudo --preserve-env=SSH_AUTH_SOCK rsync --delete --relative --acls --xattrs --atimes --crtimes --hard-links -ave 'ssh -X' --rsync-path='SUDO_ASKPASS=/usr/bin/ssh-askpass sudo -A rsync' /home/./user1/Maildir /home/./user2/Maildir /home/./user3/Maildir /home/./user4/ admin-user@destination.host.example.com:/home/
# --preserve-env so that the ssh-agent forwarding works inside sudo (using ssh agent forwarding is a security risk if source.host is compromised during the transfer)
# --delete because I expect to run this multiple times while making sure destination.host is ready before flipping over to the new host, and so also need to carry over file deletions
# --relative because I am copying directories from several different user accounts. The "/./" in the path truncates the relative path at that dot so that it all ends up in the right place in /home/ later.
# --acls --xattrs --atimes --crtimes --hard-links to make rsync be even more archivey than -a makes it
# -v for verbosity during testing
# -e to pass -X to the inner ssh used by rsync to continue the X-forwarding on to destination.host
# --rsync-path sets the SUDO_ASKPASS so that all that X-forwarding can be put to use, specifies sudo be used, and with -A so that ssh-askpass is used to ask for the password.
# Then the source folders to send over (using /./ as mentioned earlier, to avoid an extra cd command)
# Finally the destination host details and directory
What I decided against was echoing passwords around or putting them in environment variables (risk of them being logged or ending up in bash histories, and using sudo -v
in advance (because that requires editing the sudo config into a less secure state not using tty_tickets
).
Hopefully that will come in useful to someone else, if not, then probably future me.