summaryrefslogtreecommitdiff
path: root/ppsnapback-install
diff options
context:
space:
mode:
Diffstat (limited to 'ppsnapback-install')
-rwxr-xr-xppsnapback-install267
1 files changed, 267 insertions, 0 deletions
diff --git a/ppsnapback-install b/ppsnapback-install
new file mode 100755
index 0000000..a42a84c
--- /dev/null
+++ b/ppsnapback-install
@@ -0,0 +1,267 @@
+#!/bin/bash
+#
+# ppsnapback-install - ppsnapback installation wizard
+#
+# Copyright (C) 2011 Nicolas Schodet.
+#
+# See end of file for documentation, copyright and license.
+#
+# Man page can be generated using:
+#
+# $ pod2man -c '' -r '' ppsnapback-install > ppsnapback-install.1
+#
+
+fatal () {
+ echo $* >&2
+ exit 1
+}
+usage () {
+ fatal "Usage: $0 [options] MODULE [BACKUP_DIR]"
+}
+ask () {
+ local question=$1
+ local default=$2
+ local validate=$3
+ local response
+ [[ -n $default ]] && question="$question [$default]"
+ while true; do
+ echo -n "$question " >&2
+ read response
+ [[ -z $response ]] && response="$default"
+ [[ -z $validate ]] && break
+ response=$($validate "$response") && break
+ done
+ echo "$response"
+}
+validate_yesno () {
+ case "$1" in
+ [yY]|[yY][eE][sS]) echo yes ;;
+ [nN]|[nN][oO]) echo no ;;
+ *)
+ echo "please answer yes or no" >&2
+ return 1
+ ;;
+ esac
+ return 0
+}
+
+# Check parameter and check configuration does not exists.
+btype=push
+bpath=
+hostname=ASK
+remote=
+rppsnapback=
+while getopts 't:p:h:r:R:' option; do
+ case "$option" in
+ t) btype="$OPTARG" ;;
+ p) bpath="$OPTARG" ;;
+ h) hostname="$OPTARG" ;;
+ r) remote="$OPTARG" ;;
+ R) rppsnapback="$OPTARG" ;;
+ ?) usage ;;
+ esac
+done
+shift $((OPTIND-1))
+
+MODULE=${1:-NONE}
+BASEDIR=${2:-$HOME/backups}
+MD=$BASEDIR/$MODULE
+
+[[ $MODULE = NONE ]] && usage
+[[ ! -d $BASEDIR ]] && fatal "backup directory '$BASEDIR' does not exist"
+[[ -e $MD ]] && fatal "module directory for '$MODULE' exists"
+
+# Cleanup code.
+cleanup () {
+ echo "cleaning up..."
+ [[ -f $MD/config ]] && rm "$MD/config"
+ [[ -f $MD/exclude ]] && rm "$MD/exclude"
+ [[ -f $MD/$MODULE-backup-key ]] && rm "$MD/$MODULE-backup-key"
+ [[ -f $MD/$MODULE-backup-key.pub ]] && rm "$MD/$MODULE-backup-key.pub"
+ [[ -d $MD ]] && rmdir "$MD"
+}
+
+# Request functions.
+validate_path () {
+ if [[ ! -d $1 ]]; then
+ echo "path does not exist" >&2
+ return 1
+ fi
+ echo "$1"
+}
+need_path () {
+ [[ -d $bpath ]] && return
+ bpath=$(ask "Path to backup?" "$PWD/" validate_path)
+}
+need_hostname () {
+ [[ $hostname = ASK ]] || return
+ local use_hostname=$(ask "Use from= in SSH authorized_keys?" yes \
+ validate_yesno)
+ if [[ $use_hostname = yes ]]; then
+ hostname=$(ask "Hostname?" "$(hostname -f)")
+ else
+ hostname=
+ fi
+}
+validate_remote () {
+ case "$1" in
+ *:*)
+ echo "remote should not include path, only host" >&2
+ return 1
+ ;;
+ '')
+ echo "please enter something" >&2
+ return 1
+ ;;
+ esac
+ echo "$1"
+}
+need_remote () {
+ if [[ -n $remote ]]; then
+ remote=$(validate_remote "$remote") || exit 1
+ else
+ remote=$(ask "Remote host?" '' validate_remote)
+ fi
+}
+validate_rppsnapback () {
+ case "$1" in
+ /?*) echo "$1" ;;
+ *)
+ echo "please enter absolute path" >&2
+ return 1
+ ;;
+ esac
+}
+need_rppsnapback () {
+ [[ -n $rppsnapback ]] && return
+ rppsnapback=$(ask "Path to remote ppsnapback script?" \
+ '/usr/local/bin/ppsnapback' validate_rppsnapback)
+}
+
+# Proceed with installation.
+case "$btype" in
+ push)
+ need_path
+ need_hostname
+ need_remote
+ need_rppsnapback
+ trap cleanup EXIT
+ mkdir "$MD" || fatal "cannot create module directory"
+ ssh-keygen -t rsa -f "$MD/$MODULE-backup-key" \
+ -C "${hostname:+$hostname }$MODULE backup key" -N '' \
+ || fatal "cannot create backup key"
+ cat > "$MD/config" <<-EOF || fatal "cannot write module configuration"
+ path="$bpath"
+ remote="$remote"
+ privkey="$MODULE-backup-key"
+ EOF
+ touch "$MD/exclude"
+ authorized_keys="${hostname:+from=\"$hostname\",}\
+command=\"$rppsnapback $MODULE\",\
+no-pty,no-port-forwarding,no-x11-forwarding,no-agent-forwarding \
+$(< "$MD/$MODULE-backup-key.pub")"
+ RMD="backups/$MODULE"
+ echo $authorized_keys | ssh "$remote" "mkdir \"$RMD\" \
+ && touch \"$RMD/config\" \
+ && cat >> .ssh/authorized_keys" || fatal "cannot configure remote"
+ ;;
+ *)
+ fatal "only push type supported"
+ ;;
+esac
+trap - EXIT
+
+exit 0
+
+__END__
+
+=head1 NAME
+
+ppsnapback-install - ppsnapback installation wizard
+
+=head1 SYNOPSIS
+
+B<ppsnapback-install> [I<options>] I<module> [I<backup_dir>]
+
+=head1 DESCRIPTION
+
+B<ppsnapback-install> will ask for parameters to create a new B<ppsnapback>
+module. This include:
+
+=over
+
+=item * creation of the local configuration,
+
+=item * creation of a SSH backup key,
+
+=item * creation of the remote configuration,
+
+=item * update of remote authorized_keys file.
+
+=back
+
+=head1 OPTIONS
+
+Options can be used to avoid a parameter prompt. If a parameter is missing,
+B<ppsnapback-install> will ask the user to provide it.
+
+=over
+
+=item B<-t> I<type>
+
+Choose configuration type. For the moment, the only syported type is I<push>.
+
+=item B<-p> I<path>
+
+Path to backup. Will default to current directory.
+
+=item B<-h> I<hostname>
+
+Local machine hostname. This is used to limit SSH authorization to the
+current machine address. Use an empty string to disable.
+
+=item B<-r> I<remote>
+
+Remote machine or location.
+
+=item B<-R> I<path_to_ppsnapback>
+
+Absolute path to ppsnapback on the remote machine.
+
+=back
+
+=head1 RESTRICTIONS
+
+For the moment, the only supported configuration type is I<push>, which
+corresponds to the paragraph "Push Remote Backup Repository With Snapshot
+Rotation" in B<ppsnapback> man page.
+
+Remote backup directory is always $HOME/backups.
+
+=head1 SEE ALSO
+
+ppsnapback(1)
+
+=head1 AUTHOR
+
+Nicolas Schodet, http://ni.fr.eu.org/ppsnapback
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2011 Nicolas Schodet.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA.
+
+=cut
+