zBackups-TimeMachineMay 15, 2017
Self-service Restore of rsnapshot Backup Files
- Introduction
- Make Backup Shares
- rsnapshot-samba-sync-links Script
- Sample /etc/default/rsnapshot-samba Directives
- Sample /etc/rsnapshot.conf Directives
- Sample /etc/crontab Directives
- Setting up Samba on Backup Server
- Sample Samba Stanza on Backup Server
- Mounting Backup Shares
- Sample server-share Mount Script
Introduction
This document describes a methodology of backing up Samba shares with rsnapshot and providing a special folder in the Samba shares (here named zBackups-TimeMachine
) where users can securely recover their own files from the backup.
I use a separate backup server to backup all my other servers. The backup server has passwordless access to all the other servers so I am most protective of people accessing the backup server.
I use rsnapshot to backup user files as it provides a space efficient method of storing a history of backups.
However, because of the way rsnapshot stores its backups in folders named like hourly.0, hourly.1, ..., daily.0, daily.1, ...
, and because it stores files
in shares under their full path name, it makes it difficult for regular users to figure out where their backed up files are located and which version they are getting.
The script presented below maps the Samba share backups from the rsnapshot folders into a sorted list of links with names being the date of the backup.
I then use Samba to share that folder back on to the network.
However, I do not allow any regular users to access the Samba share for their backed up files.
I instead mount the backup share on the user's server to a folder named zBackups-TimeMachine
that is located in the user's share folder.
That way every user who can access a share can also access the share's backup files.
Making Backup Shares
The shares on the backup server contain links to rsnapshot directories. The rsnapshot directories
change (are rotated) each time rsnapshot runs. The following script should be run after every time rsnapshot runs.
It will resynchronize the links in the backup shares to the proper rsnapshot directories. I place the script in /usr/local/sbin
.
rsnapshot-samba-sync-links Script
#!/bin/bash SHELL=/bin/bash # Synchronize samba share links with the rsnapshot backup files. # # This is necessary because share names are static whereas rsnapshot rotates its directory names. # The top directories under hourly.0, hourly.1, ... correspond to the shares defined in /var/shares. # The modify dates of the hourly.0, hourly.1, ... directories are used as file names in the backup shares. # Format of the directory names in backup shares is: "nn-Weekday Month Day, Year HH:MMam" # where nn ranges from 01 to the number of backups saved where 01 is the most recent backup. For example: # 01-Tuesday September 24, 2013 8.00pm # 02-Tuesday September 24, 2013 5.00pm # 03-Tuesday September 24, 2013 2.00pm # Note: This program should be run after every rsnapshot command. Do not use the cmd_postexec # config setting in /etc/rsnapshot.conf as that is run only after rsync'ing the files and not # after every rotation. # Note: It is recommended to configure rsnapshot sync_first to rsync files as a separate step # in the crontab file to reduce the time the links are out of sync with the backup files. # Configure source /etc/default/rsnapshot-samba # Begin # Set share root directory's last update time to be the same as the backup root. # Samba share names for rsnapshot backups are derived from the time the backup was done. # This should set the share root's last changed time to be the same as the share's name. for b in $SNAPSHOT_ROOT/* do for s in $SHARE_DIRS do [ -d "$b/$s" ] && touch --reference="$b" "$b/$s" done done # Construct commands that will link backups to shares. cd $SNAPSHOT_ROOT ls -lt --time-style=+'%A %B %-e, %Y %l.%M%P' | \ perl -ne ' BEGIN { our $index = 0; our $snapshot_root = "'$SNAPSHOT_ROOT'"; our $shares_root = "'$SHARES_ROOT'"; our @share_dirs = split(/\n/,<<End_Of_Share_Dirs); '"$SHARE_DIRS"' End_Of_Share_Dirs our @interval_dirs; # hourly.0, ..., daily.0, ... our @backup_dates; # e.g. "201204020000 Monday April 2, 2012 12:00am" print qq[#\n]; print qq[# '"$(date)"'\n]; print qq[#\n]; } { next if $. == 1; # skip first line (the total line produced by ls) chomp; s/([^ ]+ +){5}(.*) ([^ ]+)$/$2/; # keep only date and interval directory name push(@backup_dates,$_); push(@interval_dirs,$3); } END { for my $share_dir (@share_dirs) { (my $share = $share_dir) =~ s|/.*||; # shares are named after first directory in path next unless $share; chdir "$shares_root/$share" or next; # Get list of current files my @curr_files = <*>; my %seen; print qq[cd "$shares_root/$share"\n]; for (my $i=0; $i < @interval_dirs; $i++) { my $backup_date = $backup_dates[$i]; my $interval_dir = $interval_dirs[$i]; my $backup_path = "$snapshot_root/$interval_dir/$share_dir"; my $backup_link = sprintf("%02d",$i+1) . "-" . $backup_date; $seen{$backup_link} = 1; print qq(if [ -d "$backup_path" ]; then\n); print qq( [ -L "$backup_link" ] && rm -f "$backup_link"\n); print qq( ln -s "$backup_path" "$backup_link"\n); print qq(fi\n); } # Remove existing files that are not links to the current set of backup files. # Remove only links and not actual files that might possibly exist. for my $file (@curr_files) { if (! $seen{$file}) { print qq([ -L "$file" ] && rm -f "$file"\n); } } } }' | /bin/bash # without log file ##}' | tee -a /var/log/rsnapshot-samba-sync-links.log | /bin/bash # with log file
Sample /etc/default/rsnapshot-samba Directives
The following is a sample configuration file for the above script.
# Settings allowing rsnapshot backups to be sync'ed with samba shares allowing access to backups through the shares. SNAPSHOT_ROOT=/backup/rsnapshot # location of backup directories hourly.0, hourly.1, ... SHARES_ROOT=/var/shares # location of samba shares # List the directories under hourly.0, ... to the shares' top directories, one per line. # This is the path on the host server from / to the directory that's shared (samba's path setting). # The top directory under the interval directories (hourly.0,...) is constructed from the server # name and the share name, e.g. server name is "homes" and share name is "accounting" so # the directory name is "homes-accounting". # The following settings should match the backups listed in /etc/rsnapshot.conf SHARE_DIRS=' homes-accounting/home/accounting/share homes-cs/home/cs/share homes-it/home/it/share homes-marketing/home/marketing/share homes-production/home/production/share homes-purchasing/home/purchasing/share homes-sales/home/sales/share '
Sample /etc/rsnapshot.conf Directives
The above configuration corresponds to a rsnapshot configuration similar to the following:
snapshot_root /backup/rsnapshot/ interval hourly 24 interval monthly 13 # Don't forget to exclude your mounted backup directories from your backup # otherwise your backup will go in circles till you run out of resources. exclude /home/*/share/Backups/*** link_dest 1 sync_first 1 # Backup samba shares # Note: These shares should also be listed in /etc/default/rsnapshot-samba # Also create a directory in /var/shares for the target server-share backup root@homes:/home/accounting/share/ homes-accounting/ backup root@homes:/home/cs/share/ homes-cs/ backup root@homes:/home/it/share/ homes-it/ backup root@homes:/home/marketing/share/ homes-marketing/ backup root@homes:/home/production/share/ homes-production/ backup root@homes:/home/purchasing/share/ homes-purchasing/ backup root@homes:/home/sales/share/ homes-sales/
Sample /etc/crontab Directives
The following crontab
entry invokes rsnapshot backups and keeps backup shares sync'ed.
# Backup snapshots of file shares 0 * * * * root /usr/bin/rsnapshot sync; test $? -eq 0 -o $? -eq 2 && /usr/bin/rsnapshot hourly && /usr/local/sbin/rsnapshot-samba-sync-links 50 23 * * * root /usr/bin/rsnapshot daily && /usr/local/sbin/rsnapshot-samba-sync-links 40 23 * * 6 root /usr/bin/rsnapshot weekly && /usr/local/sbin/rsnapshot-samba-sync-links 30 23 1 * * root /usr/bin/rsnapshot monthly && /usr/local/sbin/rsnapshot-samba-sync-links
Setting up Samba on Backup Server
Samba shares need to be set up on the backup server so that they can be mounted to directories in the user's share.
I mount the shares in the /var/shares
directory. Each share is named after the server name and the share name.
So for example, if I'm backing up the share named Accounting on the server named Homes, I link the backups to the share
homes-accounting
that is located in /var/shares/homes-accounting
.
I set up one user to access each backup share on the backup server. I name the user the same as the share name. So the
backup share setup homes-accounting
is accessed by the user homes-accounting
.
- Create special user for mounting backup share back onto remote server. - The numeric group id of this user needs to match the group id number of the remote server share group. - Create long random password (I use KeyPass (128bit) random password option.) - Create a group in /etc/group if group number on backup server is not yet defined. - Use created group number as group id for new user. useradd -M -N -d /nonexistent -s /bin/false -g 1012 homes-exec; smbpasswd -a homes-exec - Create share for homes-exec vi /etc/samba/smb.conf /etc/init.d/samba reload
Sample Samba Stanza on Backup Server
Following is a sample set of instructions to set up a Samba share on the backup server that can be used to mount backups back on the user's server.
[global] netbios name = BACKUPSERVER hosts allow = 127. 192.168.1. dead time = 20 unix extensions = no [homes-accounting] comment = Backup of Accounting Files path = /var/shares/homes-accounting writeable = no read only = yes printable = no follow symlinks = yes wide links = yes valid users = homes-accounting
Mounting Backup Shares
Note: I have successfully used the autofs package to dynamically mount the backup drives when accessed instead of using the following scripts.
On the user's server the backup shares are mounted on directories within their share folders. To automatically mount
the backup shares on the users' server you can edit /etc/fstab
and place your passwords in a protected file.
I however ended up creating a script that I copy for each backup share that needs to be mounted. It allows for remounting
the shares if there is a network disconnect.
I created the directory /etc/mount-shares.d
on the users' server and made copies of the following script there.
Then to automatically remount the shares when the server reboots I put the line
run-parts /etc/mount-shares.d
into the /etc/rc.local
file. The scripts should be owned by root and only readable by root as the passwords to the
backup shares are embedded in them.
Sample server-share Mount Script
These scripts execute on the users' server to mount the backup server shares on to directories within the users' share.
#!/bin/bash # # Config # SHARE=//backupbox/homes-accounting MOUNT=/home/accounting/share/Backups # Remote user id the mount program is to use to connect to the server share. export USER=homes-accounting export PASSWD=AVeryLongArbitraryPasswordThatsHardToGuess # Mounted files appear to be owned by following user and group. local_user=accounting local_group=accounting # Mount share as read-only or read/write #mode=rw # read/write mode=ro # read-only # # Begin # [ "$1" = '-f' ] && { FORCE=-f; shift; } [ -d "$MOUNT" ] || mkdir --mode=0555 "$MOUNT" if mount | grep "on $MOUNT type" >/dev/null 2>&1 then if [ $FORCE ] then umount "$MOUNT" sleep 3 else exit # already mounted fi fi mount -t cifs -o uid=$local_user,gid=$local_group,$mode "$SHARE" "$MOUNT"