6

I would like to perform incremental backups (for the entire filesystem) from a machine. rsync does this quite will, however I would like to also preserve file ownership - meaning, make it possible to restore it.

Is this possible to do without running rsync as root on the target machine (storing the backups)?

Some ideas...

  • Is there a way to mount a filesystem (FUSE?) in such a way as to allow chown for a non-root user? (I guess it would probably need to be noexec to forbid elevation.)
  • Some way to store and restore the ownership in metadata files instead of the filesystem itself?
  • tar can store file ownership, though getting it to work with rsync or incremental backups would be a bit more involved. It would also be nice to be able to browse the backups like a regular filesystem.
  • Perhaps some kind of fake root environment? A virtual machine would work, but would be nice to avoid the associated maintenance and performance overhead.
Vladimir Panteleev
  • 1,705
  • 4
  • 20
  • 34

6 Answers6

16

As stated in the other answers, to directly preserve ownership information you need root access to the destination machine.

However, you had at least two workarounds to avoid root access while preserving ownership:

  1. use the --fake-super rsync option. From the man page:

When this option is enabled, rsync simulates super-user activities by saving/restoring the privileged attributes via special extended attributes that are attached to each file (as needed)

This means that ownership is not directly preserved in classical Unix style, rather ownership information is stored inside a special extended attribute (ie: a sort of "tag" attached to the file). When restoring, rsync can use this EA/tag to correctly reconstruct the original file owner.

  1. do not let rsync preserve ownership information, rather preserve them using the getfacl utility. For example, issuing getfacl -R MNTPOINT > acls.txt you effectively save ownership (and ACL) info in a text file which can be later used to restore such information using the setfacl --restore command.
shodanshok
  • 44,038
  • 6
  • 98
  • 162
2

If I were you, I would put the backups on a volume in a Docker container. This way, you can put good limits on it and avoid security risks but still run it as root so it does what it needs to do.

Florin Asăvoaie
  • 6,932
  • 22
  • 35
  • I don't know why this was downvoted. But would this work, considering that - AIUI - containers require mapping a specific set of UIDs, and forbid operations on UIDs outside the mapped set? – Vladimir Panteleev Feb 12 '16 at 10:27
1

I assume that when you say "without running rsync as root on the target" that you've really hit the problem that you cannot establish a connection TO the target as root - correct? In other words - you do not literally mean "without running rsync as root on the target" - but what you REALLY mean is "without making an (automated) connection as root to the target" - which as everyone knows is a hard and dangerous thing to do.

Assuming this is the case (it probably is), one solution is to use pipes.

The idea is to create a pipe on the target machine that is owned by the non-root login that is going to be sending in the backups, and to write the backup stream into this pipe.

Then, on that same machine, you set it up so that it runs a root process that reads from the pipe and restores the backup.

e.g. (using tar for example) - on the machine to extract the backup:-

mknod /tmp/pipe p
cd /folder-to-restore-into
sudo tar xfz /tmp/pipe 

And on the machine to send the backups over from:

cd /folder-to-backup
sudo tar cfz - . | ssh remote_nonroot_user@remoteip.com 'cat > /tmp/pipe'

You can also do it the other way too (put the pipe on the other machine) which might be handy if you want the backup server to initiate the backing-up process (since the machine-to-be-backed-up will block until the other server reads from the pipe).

  • Answering the question at the beginning of the answer - No, the interpretation in the accepted answer was what my problem was about, but thanks for contributing this answer to an alternate interpretation! – Vladimir Panteleev May 16 '21 at 07:11
1

Rather than copying all your files one-by-one like rsync does, you should consider putting the files in some kind of "container" that lets you pack up all the files, transport them around, and never lose any metadata.

Have you considered "tar"? I know that tar is the antithesis of rsync: it isn't incremental, it doesn't transport the data anywhere, etc.

However it is really good at preserving ownership, permissions, ACLs, modification times, and such. You can make a tar file, copy it to a machine that doesn't even understand the Unix way of doing file permissions (i.e. Windows, TOPS-20, VAX/VMS), then copy it back to a Unix host, untar it, and you get all the permissions, etc. that it originally had.

There is a FUSE filesystem that will mount (read-only) tar files.

Of course, you lose the incremental copies and other features that make rsync such an excellent tool. However, the Unix world used tar for 20+ years before rsync was invented and it works really well for certain situations.

TomOnTime
  • 7,567
  • 6
  • 28
  • 51
  • GNU `tar` can even make full and incremental backups. Check out e.g. the `--incremental` option in the manual, see https://www.gnu.org/software/tar/manual/html_chapter/tar_5.html#SEC94 . Note that excluding certain system directories (e.g. `/proc`), which is easy with `rsync`, is somewhat clumsy with `tar`. – András Aszódi Jan 09 '18 at 06:11
0

A solution could be to create a disk image on the remote location and mount it locally:

# we assume that /mnt/backup is a mounted SHFS, SMB, etc share
truncate -s 100GiB /mnt/backup/rsync.img # create image file
mkfs.ext3 -F /mnt/backup/rsync.img # create filesystem
echo -e "o\nn\np\n1\n\n\nw" | fdisk /mnt/backup/rsync.img # create partition
mkdir /mnt/rsync 
mount -t auto -o loop /mnt/backup/rsync.img /mnt/rsync

Now we can run rsync on our local machine as root:

args=(
  --recursive
  --links # copy symlinks as symlinks
  --perms # preserve permissions
  --times # preserve modification times
  --group # preserve group
  --owner # preserve owner
  --devices # preserve device files
  --specials # preserve special files
  --acls # preserve ACLs, optional check if really needed: getfacl --recursive --skip-base / 2>/dev/null | grep "file:" | cut -d" " -f3 | awk '{print "/"$1}'
  --xattrs # preserve extended attributes
  --sparse # handle sparse files efficiently
  --delete # delete extraneous files from dest dirs
  --compress # compress file data during the transfer
  --stats # give some file-transfer stats
  # --bwlimit=625 # limit transfer speed in KByte/s, 625 KB = 0.5 Mbit https://www.google.com/search?q=1+mbit+in+kbyte
  --verbose # increase verbosity
  --exclude="/dev"
  --exclude="/lost+found"
  --exclude="/media" # external mounts
  --exclude="/mnt" # external mounts
  --exclude="/proc"
  --exclude="/run"
  --exclude="/sys"
  --exclude="/tmp"
  --exclude="/var/lib/dhcp/proc" # mount to proc
  --exclude="/var/lib/named/proc" # mount to proc
  /
  /mnt/rsync
)
rsync "${args[@]}"
mgutt
  • 459
  • 6
  • 22
-1

Obviously to get the "root" files from the destination, you need root access. However, there are many ways to screw your system.

1) You could allow rsync to use sudo without password 2) You could use setuid to rsync so that it can access root files, while the backup orchestrator is a normal user rather than the root. 3) use rssh to limit the security risks of all the above

Nikolaidis Fotis
  • 1,994
  • 11
  • 13