diff --git a/Makefile b/Makefile deleted file mode 100644 index c079fb1..0000000 --- a/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -## -# Copyright (C) 2013-2014 by Janek Bevendorff -# Website: http://www.refining-linux.org/ -# -# Makefile for installing the scripts to their locations in the system. -## - -OS=$(shell lsb_release -si) - -.PHONY: server-install client-install server-uninstall client-uninstall - -all: server client - -server: - true - -client: - true - -install: server-install client-install - -server-install: $(wildcard server/bkp/etc/*) $(wildcard server/etc/*/*) $(wildcard server/usr/*/*) - mkdir -p /etc/rs-skel - mkdir -p /etc/rs-backup - mkdir -p /bkp/{bin,dev,etc,lib,usr} - mkdir -p /bkp/usr/{bin,lib,share} - -ifeq ($(OS),Ubuntu) - mkdir -p /bkp/usr/share/perl -else - mkdir -p /bkp/usr/share/perl5 -endif - - ln -snf /bkp /bkp/bkp - - @for i in $+; do \ - cp -av $$i $${i/server/}; \ - chown root:root $$i; \ - done; - -client-install: $(wildcard client/etc/*/*) $(wildcard client/usr/bin/*) - mkdir -p /etc/rs-backup - - @for i in $+; do \ - cp -av $$i $${i/client/}; \ - chown root:root $$i; \ - done; - -uninstall: server-uninstall client-uninstall - -server-uninstall: $(wildcard server/etc/*/*) server/etc/rs-skel server/etc/rs-backup $(wildcard server/usr/*/*) - rm -Rf $(addprefix /,$(subst server/,,$+)) - @echo -e "\e[1mINFO: /bkp not removed to preserve your data. Delete it manually if you don't need it anymore.\e[0m" - -client-uninstall: client/etc/rs-backup client/usr/bin/* - rm -Rf $(addprefix /,$(subst client/,,$+)) diff --git a/README.md b/README.md index f6e74a2..bddf37a 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,9 @@ rs-backup-suite is split into two parts: a client part for pushing the backup to ### Server For installing the server component run - sudo make server-install + sudo ./install.sh server -on your server machine. This installs all the necessary files into the right location on your system. Finally copy the file `/etc/rs-backup/server-config.example` to `/etc/rs-backup/server-config`. +on your server machine. This installs all the necessary files into the right location on your system. #### Tweaking the configuration file If you need to tweak the server settings, simply edit `/etc/rs-backup/server-config` to your needs. There you can configure the following directives: @@ -45,7 +45,7 @@ The optional third parameter specifies the path to the SSH public key file which **TIP:** If you don't remember the parameters for all these commands, simply run them without any and you'll get simple usage instructions. #### Making the chroot work -rs-backup-suite can chroot backup users into the backup home base directory. For this to work you need to add a few lines to your `/etc/fstab` and run `mount -a` afterwards: +rs-backup-suite can chroot backup users into the backup home base directory. For this to work you need to add a few lines to your `/etc/fstab` and run `mount -a` afterwards (replace `/bkp` with your backup path): # Chroot /bin /bkp/bin none bind 0 0 @@ -55,7 +55,7 @@ rs-backup-suite can chroot backup users into the backup home base directory. For /usr/share/perl5 /bkp/usr/share/perl5 none bind 0 0 /dev /bkp/dev none bind 0 0 -**NOTE:** In Ubuntu the Perl modules are located at `/usr/share/perl` instead of `/usr/share/perl5`. Change that accordingly. +**NOTE:** In Ubuntu the Perl modules are located at `/usr/share/perl` instead of `/usr/share/perl5`. Change that accordingly. Also note that if you are using Synology DSM, you also need to add a bind mount for /opt/bin to /bkp/opt/bin. If your 64-bit system doesn't have a `/lib` folder but only `/lib64` you may need to add this to your `/etc/fstab`: @@ -80,7 +80,7 @@ If you add or remove any backup levels, make sure you also update the cron scrip ### Client To set up the client you simply need to run - sudo make client-install + sudo ./install.sh client on your client machine. Then copy the file `/etc/rs-backup/client-config.example` to `/etc/rs-backup/client-config`, edit it as root and replace the value of `REMOTE_HOST` with the hostname or IP address of your NAS. @@ -97,10 +97,10 @@ All the client configuration options are defined in `/etc/rs-backup/client-confi ## Installing client and server on the same machine You can of course also install server and client on the same machine. This may be useful if you want, e.g. save your data to an external USB drive instead of a real NAS. A shortcut for running both `sudo make server-install` and `sudo make client-install` is simply running - sudo make install + sudo ./install all ## Uninstalling -Similar to the `install` targets there are als `uninstall` and `server-uninstall` / `client-uninstall` targets. These remove all the scripts but preserve the data in `/bkp`. +For uninstalling run ./uninstall.sh [all|server|client]. These remove all the scripts but preserve the data in `/bkp` (or whatever your backup folder is). ## Backup strategies The intended use case for rs-backup-suite is as follows: you set up the server part on your NAS. Then you create a backup user for each user on each client machine. diff --git a/client/etc/rs-backup/client-config.example b/client/etc/rs-backup/client-config.example deleted file mode 100644 index fdc4686..0000000 --- a/client/etc/rs-backup/client-config.example +++ /dev/null @@ -1,55 +0,0 @@ -## -# Global config file for rs-backup-run -# This is an example file. Copy it over without the .example extension -# and modify it to your needs. -# Most config options can also be passed directly as command line parameters. -## - -# Remote host to push the files to -# The remote host must have a working rsync server running which allows -# passwordless (public key) login over SSH -REMOTE_HOST="host" - -# The rsync module on the remote server -PUSH_MODULE="push" - -# Username to use for logging into the remote server. -# You can use the variables %h which will be replaced with the hostname -# of this machine and %u which will be replaced with your local username. -# If a global system backup is performed, %u will be 'root' for the global -# backup and the corresponding user for the individual home directories -REMOTE_USER="%h-%u" - -# Additional SSH options -#SSH_OPTIONS="-C -i .ssh/id_rsa" - -# Additional options for rsync -#RSYNC_OPTIONS="" - -# Global log file to use when running as root -LOG_FILE="/var/log/rs-backup.log" - -# Log filename (only basename) of the log file to use when running as a -# normal user. The file will be placed inside the user's home directory. -# Leave empty if you don't want any per-user log file. -# The user log file will only be written when the user originally invoked -# the script, not if his home directory is backed up during a full system -# backup run by root -USER_LOG_FILE="rs-backup.user.log" - -# Name of the file inside the users' home directories -# containing the patterns for matching files to include or exclude. -# The format is the same as the global 'include-files' config file -# and described in the FILTER RULES section of the rsync(1) man page. -# If no such file is found inside a home directory, it won't be backup up -INCLUSION_PATTERN_FILE=".rs-backup-include" - -# Log verbosity -# (0 = quiet, 1 = errors only, 2 = errors and warnings, 3 = info, 4 = debug) -LOG_LEVEL=3 - -# Send error messages to STDERR -PRINT_ERRORS=true - -# Send warnings to STDERR (implies PRINT_ERRORS=true) -PRINT_WARNINGS=true diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..8d130a8 --- /dev/null +++ b/install.sh @@ -0,0 +1,213 @@ +#!/bin/sh +## +# Copyright (C) 2014 Janek Bevendorff +# Install script for installing server and client script files +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +## + +if [[ "$1" != "all" ]] && [[ "$1" != "client" ]] && [[ "$1" != "server" ]]; then + ./server/usr/bin/rs-version + echo "Usage: $(basename $0) [all|server|client]" + exit +fi + +if [ $UID -ne 0 ]; then + echo "ERROR: This script must be run as root." + exit 1 +fi + +DISTRIBUTION="$(./server/usr/bin/rs-detect-distribution)" +COMPONENT="$1" +MODE="install" +if [[ "$(basename $0)" == "uninstall.sh" ]]; then + MODE="uninstall" +fi + +# Command aliases +CP="cp -vr --preserve=mode,timestamps,links,xattr" +RM="rm -Rvf" +MKDIR="mkdir -pv" + +if [[ $MODE == "install" ]]; then + if [[ $COMPONENT == "all" ]] || [[ $COMPONENT == "server" ]]; then + echo "Installing Server component..." + + $CP ./server/usr/bin/* /usr/bin/ + $CP ./server/usr/sbin/* /usr/sbin/ + $CP ./server/etc/rs-skel /etc/ + + # Do not overwrite existing config + if [ ! -e /etc/rs-backup/server-config ]; then + $CP ./server/etc/rs-backup /etc/ + # Correct command paths in rsnapshot config for Synology DSM + if [[ "$DISTRIBUTION" == "Synology" ]]; then + sed -i "s#/usr/bin/\(cp\|rm\|rsync\)\$#/opt/bin/\1#" /etc/rs-backup/rsnapshot.global.conf + fi + fi + + echo + echo "Installing cron scripts..." + if [ -d /etc/cron.daily ]; then + $CP ./server/etc/cron.daily/* /etc/cron.daily/ + $CP ./server/etc/cron.weekly/* /etc/cron.weekly/ + $CP ./server/etc/cron.monthly/* /etc/cron.monthly/ + elif [ -e /etc/crontab ]; then + if ! grep -q "/usr/sbin/rs-rotate-cron" /etc/crontab; then + if [[ "$DISTRIBUTION" == "Synology" ]]; then + cat ./server/etc/crontab_synology >> /etc/crontab + else + cat ./server/etc/crontab >> /etc/crontab + fi + fi + else + echo "ERROR: Could not install cron scripts, please add rotation jobs manually." >&2 + fi + + echo "Installing backup directory..." + BKP_DIR="$(grep -o '^BACKUP_ROOT=".*"$' /etc/rs-backup/server-config | sed 's#BACKUP_ROOT=\"\(.*\)\"$#\1#')" + if [[ "$DISTRIBUTION" == "Synology" ]] && [[ "$BKP_DIR" == "/bkp" ]]; then + if readlink -q /var/services/homes > /dev/null; then + BKP_DIR="/var/services/homes" + elif [ -d /volume1/homes ]; then + # Try hard + BKP_DIR="/volume1/homes" + fi + fi + echo "Backup directory path will be '$BKP_DIR'." + echo -n "Do you want to use this directory? [Y/n] " + read answer + + if [[ "" != "$answer" ]] && [[ "Y" != "$answer" ]] && [[ "y" != "$answer" ]]; then + echo -n "Please enter a new location: " + read BKP_DIR + fi + + # Correct backup folder path in server config + sed -i "s#^BACKUP_ROOT=\".*\"\$#BACKUP_ROOT=\"$BKP_DIR\"#" /etc/rs-backup/server-config + + echo "Creating backup directory structure at '$BKP_DIR'..." + + $MKDIR "$BKP_DIR"/bin + $MKDIR "$BKP_DIR"/dev + $MKDIR "$BKP_DIR"/etc + $MKDIR "$BKP_DIR"/lib + $MKDIR "$BKP_DIR"/usr/bin + $MKDIR "$BKP_DIR"/usr/lib + $MKDIR "$BKP_DIR"/usr/share + + if [[ "$DISTRIBUTION" == "Synology" ]]; then + $MKDIR "$BKP_DIR"/opt/bin + fi + + if [[ "$DISTRIBUTION" == "Ubuntu" ]]; then + $MKDIR "$BKP_DIR"/usr/share/perl + else + $MKDIR "$BKP_DIR"/usr/share/perl5 + fi + + $CP ./server/bkp/etc/* "$BKP_DIR"/etc/ + + # Create symlink for chroot + dir="$(dirname ${BKP_DIR}${BKP_DIR})" + if [ ! -d "$dir" ]; then + $MKDIR "$dir" + fi + rel_dir="." + orig_dir="$(pwd)" + cd "$dir" + while [[ "$(realpath .)" != "$(realpath $BKP_DIR)" ]]; do + if [[ "." == "$rel_dir" ]]; then + rel_dir=".." + else + rel_dir="../$rel_dir" + fi + cd .. + done + ln -snf "$rel_dir" "${BKP_DIR}${BKP_DIR}" + cd "$orig_dir" + + echo "Done." + + elif [[ $COMPONENT == "all" ]] || [[ $COMPONENT == "client" ]]; then + echo "Installing client component..." + + $CP ./client/usr/bin/* /usr/bin/ + + # Do not overwrite existing config + if [ ! -e /etc/rs-backup/client-config ]; then + $CP ./client/etc/rs-backup /etc/ + fi + + echo "Done." + fi +elif [[ "$MODE" == "uninstall" ]]; then + echo "This will uninstall rs-backup suite from this computer." + echo "Selected components for removal: $COMPONENT" + echo "NOTE: This will NOT remove your backup data, just the program!" + echo + echo -n "Do you want to continue? [y/N] " + read answer + + if [[ "$answer" != "Y" ]] && [[ "$answer" != "y" ]]; then + echo "Okay, no hard feelings. Exiting." + exit + fi + + if [[ $COMPONENT == "all" ]] || [[ $COMPONENT == "server" ]]; then + echo "Uninstalling server component..." + + for i in ./server/usr/bin/*; do + $RM /usr/bin/"$(basename $i)" + done + + for i in ./server/usr/sbin/*; do + $RM /usr/sbin/"$(basename $i)" + done + + echo "Done." + + elif [[ $COMPONENT == "all" ]] || [[ $COMPONENT == "client" ]]; then + echo "Uninstalling client component..." + + for i in ./client/usr/bin/*; do + $RM /usr/bin/"$(basename $i)" + done + + echo "Done." + fi + + echo -n "Do you want to remove your config files, too? [y/N] " + read answer + if [[ "$answer" == "Y" ]] || [[ "$answer" == "y" ]]; then + echo "Removing config files..." + $RM /etc/rs-backup + echo "Done." + fi + + echo + echo "INFO: Your backup folder was not removed to preserve your data." + echo " If you don't need it anymore, just delete it." +else + # Program should never end here + echo "Nothing to do." >&2 + exit 1 +fi diff --git a/server/etc/crontab b/server/etc/crontab new file mode 100644 index 0000000..7ea328f --- /dev/null +++ b/server/etc/crontab @@ -0,0 +1,3 @@ +@daily /usr/sbin/rs-rotate-cron daily +@weekly /usr/sbin/rs-rotate-cron weekly +@monthly /usr/sbin/rs-rotate-cron monthly diff --git a/server/etc/crontab_synology b/server/etc/crontab_synology new file mode 100644 index 0000000..12c5807 --- /dev/null +++ b/server/etc/crontab_synology @@ -0,0 +1,3 @@ +@daily root /usr/sbin/rs-rotate-cron daily +@weekly root /usr/sbin/rs-rotate-cron weekly +@monthly root /usr/sbin/rs-rotate-cron monthly diff --git a/server/etc/rs-backup/rsnapshot.conf.template b/server/etc/rs-backup/rsnapshot.conf.template index 1888e5f..0abb7b5 100644 --- a/server/etc/rs-backup/rsnapshot.conf.template +++ b/server/etc/rs-backup/rsnapshot.conf.template @@ -1,4 +1,4 @@ -include_conf ${BACKUP_ROOT}/etc/rsnapshot.global.conf +include_conf ${BACKUP_ROOT}/etc/rs-backup/rsnapshot.global.conf snapshot_root ${HOME_DIR}/${FILES_DIR} logfile ${HOME_DIR}/rsnapshot.log diff --git a/server/etc/rs-backup/server-config.example b/server/etc/rs-backup/server-config.example deleted file mode 100644 index 95947fa..0000000 --- a/server/etc/rs-backup/server-config.example +++ /dev/null @@ -1,18 +0,0 @@ -# Base directory for all backups -BACKUP_ROOT="/bkp" - -# Backup user group -USER_GROUP="backup" - -# Directory containing the actual backup files (relative to BACKUP_ROOT/) -FILES_DIR="files" - -# Set quota for individual backup users -SET_QUOTA=false - -# Quota limits (use 0 for no limit) -# Numbers may also end with k, M, G or T for magnitudes of 1024 -QUOTA_SOFT_LIMIT="350G" -QUOTA_HARD_LIMIT="355G" -QUOTA_INODE_SOFT_LIMIT="3900k" -QUOTA_INODE_HARD_LIMIT="4000k" diff --git a/uninstall.sh b/uninstall.sh new file mode 120000 index 0000000..61e71e2 --- /dev/null +++ b/uninstall.sh @@ -0,0 +1 @@ +install.sh \ No newline at end of file