summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Charaoui <jcharaoui@cmaisonneuve.qc.ca>2015-03-06 16:47:08 -0500
committerJerome Charaoui <jcharaoui@cmaisonneuve.qc.ca>2015-03-06 16:47:08 -0500
commit1ef94f1f2e49e032c6c416830345fc3b4beacb01 (patch)
tree4c6bc037e48bcfc75412d86f638e2cdbc118d8c7
parentfa28702f46db802494872272ca50e0b1c37de09e (diff)
parentbab96a631337b87dd6f168f663f5b24537f58a5c (diff)
Merge branch 'master' of https://git-nadir.immerda.ch/puppet-backupninja
Conflicts: manifests/rdiff.pp
-rw-r--r--README33
-rw-r--r--files/nagios_plugins/duplicity/README.md24
-rw-r--r--files/nagios_plugins/duplicity/backupninja_duplicity_freshness.sh268
-rw-r--r--files/nagios_plugins/duplicity/check_backupninja_duplicity.py123
-rw-r--r--manifests/client.pp30
-rw-r--r--manifests/dup.pp24
-rw-r--r--manifests/generate_sshkey.pp33
-rw-r--r--manifests/init.pp1
-rw-r--r--manifests/nagios_plugin/duplicity.pp45
-rw-r--r--manifests/pgsql.pp29
-rw-r--r--manifests/rdiff.pp18
-rw-r--r--templates/pgsql.conf.erb11
12 files changed, 610 insertions, 29 deletions
diff --git a/README b/README
index 5b7c2c9..a839193 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
Backupninja Module
-------------------
-This module helps you configure all of your backups with puppet, using
+This module helps you configure all of your backups with puppet, using
backupninja!
! Upgrade notice !
@@ -32,12 +32,12 @@ Configure your backup server
Now you will need to configure a backup server by adding the following
to your node definition for that server:
-
+
include backupninja::server
By configuring a backupninja::server, this module will automatically
create sandboxed users on the server for each client for their
-backups.
+backups.
You may also want to set some variables on your backup server, such as:
@@ -130,6 +130,33 @@ backupninja::config { conf:
}
+Automatic creation of ssh-keys for duplicity
+--------------------------------------------
+
+backupninja::duplicity can be used to
+
+- create an ssh keypair for a client
+- place the keypair on the puppetmaster in a given location
+- place the keypair in /root/.ssh on the client
+
+i.e.:
+
+ backupninja::duplicity { "duplicity_${::fqdn}":
+ sshoptions => "-oIdentityFile=/root/.ssh/backupninja_${::hostname}_id_rsa",
+ desthost => 'HOST',
+ destdir => "/var/backup/backupninja/${::fqdn}",
+ destuser => "backupninja_${::hostname}",
+ encryptkey => 'KEYID',
+ password => 'PW',
+ backupkeystore => 'puppet:///keys',
+ backupkeystorefspath => '/etc/puppet/modules/keys/files',
+ backupkeydestname => "backupninja_${::hostname}_id_rsa",
+ createkey => true,
+ installkey => true,
+ ...
+ }
+
+
Nagios alerts about backup freshness
------------------------------------
diff --git a/files/nagios_plugins/duplicity/README.md b/files/nagios_plugins/duplicity/README.md
new file mode 100644
index 0000000..1cd349a
--- /dev/null
+++ b/files/nagios_plugins/duplicity/README.md
@@ -0,0 +1,24 @@
+duplicity-backup-status
+=======================
+
+Backupninja generates duplicity configfiles, this nagios plugin can check their freshness. Currently only the config files generated by backupninja can be parsed and we depend on that.
+
+## Prerequisites
+
+Make sure you have python-argparse installed (yes an extra dependency, getopt doubles the amount of code, so I gave up on that). The Python script will look for the duplicity_freshness.sh shell script in /usr/local/lib/nagios/plugins/ or /usr/lib/nagios/plugins/ make sure you copy it there and make executable.
+
+## Getting started
+
+Run the python script from your nagios. Don't forget to specify some extras like when warnings or criticalities should be emerged.
+
+- -w WARNINC Number of hours allowed for incremential backup warning level default 28
+- -W WARNFULL Number of hours allowed for incremential backup critical level default 40
+- -c CRITINC Number of days allowed for full backup warning level default 52
+- -C CRITFULL Number of days allowed for full backup critical level default 60
+
+
+## TODO:
+
+- make it cuter, tidy up
+- make it more robust
+- support other config backends as backupninja - this can be done by writing more scripts like backupninja_duplicity_freshness.sh and parsing an extra parameter
diff --git a/files/nagios_plugins/duplicity/backupninja_duplicity_freshness.sh b/files/nagios_plugins/duplicity/backupninja_duplicity_freshness.sh
new file mode 100644
index 0000000..7af2bf7
--- /dev/null
+++ b/files/nagios_plugins/duplicity/backupninja_duplicity_freshness.sh
@@ -0,0 +1,268 @@
+#!/bin/bash
+# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
+# vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
+
+# Load backupninja library/helpers, because why reinventing the wheel? [Because my wheels weren't round]
+# some duplication is to be expected
+# this is only supposed to work with duplicity
+
+## Functions
+# simple lowercase function
+function tolower() {
+ echo "$1" | tr '[:upper:]' '[:lower:]'
+}
+
+# we grab the current time once, since processing
+# all the configs might take more than an hour.
+nowtime=`LC_ALL=C date +%H`
+nowday=`LC_ALL=C date +%d`
+nowdayofweek=`LC_ALL=C date +%A`
+nowdayofweek=`tolower "$nowdayofweek"`
+
+conffile="/etc/backupninja.conf"
+
+# find $libdirectory
+libdirectory=`grep '^libdirectory' $conffile | /usr/bin/awk '{print $3}'`
+if [ -z "$libdirectory" ]; then
+ if [ -d "/usr/lib/backupninja" ]; then
+ libdirectory="/usr/lib/backupninja"
+ else
+ echo "Could not find entry 'libdirectory' in $conffile."
+ fatal "Could not find entry 'libdirectory' in $conffile."
+ fi
+else
+ if [ ! -d "$libdirectory" ]; then
+ echo "Lib directory $libdirectory not found."
+ fatal "Lib directory $libdirectory not found."
+ fi
+fi
+
+. $libdirectory/tools
+
+setfile $conffile
+
+# get global config options (second param is the default)
+getconf configdirectory /etc/backup.d
+getconf scriptdirectory /usr/share/backupninja
+getconf reportdirectory
+getconf reportemail
+getconf reporthost
+getconf reportspace
+getconf reportsuccess yes
+getconf reportinfo no
+getconf reportuser
+getconf reportwarning yes
+getconf loglevel 3
+getconf when "Everyday at 01:00"
+defaultwhen=$when
+getconf logfile /var/log/backupninja.log
+getconf usecolors "yes"
+getconf SLAPCAT /usr/sbin/slapcat
+getconf LDAPSEARCH /usr/bin/ldapsearch
+getconf RDIFFBACKUP /usr/bin/rdiff-backup
+getconf CSTREAM /usr/bin/cstream
+getconf MYSQLADMIN /usr/bin/mysqladmin
+getconf MYSQL /usr/bin/mysql
+getconf MYSQLHOTCOPY /usr/bin/mysqlhotcopy
+getconf MYSQLDUMP /usr/bin/mysqldump
+getconf PGSQLDUMP /usr/bin/pg_dump
+getconf PGSQLDUMPALL /usr/bin/pg_dumpall
+getconf PGSQLUSER postgres
+getconf GZIP /bin/gzip
+getconf GZIP_OPTS --rsyncable
+getconf RSYNC /usr/bin/rsync
+getconf admingroup root
+
+if [ ! -d "$configdirectory" ]; then
+ echo "Configuration directory '$configdirectory' not found."
+ fatal "Configuration directory '$configdirectory' not found."
+fi
+
+# get the duplicity configuration
+function get_dupconf(){
+ setfile $1
+ getconf options
+ getconf testconnect yes
+ getconf nicelevel 0
+ getconf tmpdir
+
+ setsection gpg
+ getconf password
+ getconf sign no
+ getconf encryptkey
+ getconf signkey
+
+ setsection source
+ getconf include
+ getconf vsnames all
+ getconf vsinclude
+ getconf exclude
+
+ setsection dest
+ getconf incremental yes
+ getconf increments 30
+ getconf keep 60
+ getconf keepincroffulls all
+ getconf desturl
+ getconf awsaccesskeyid
+ getconf awssecretaccesskey
+ getconf cfusername
+ getconf cfapikey
+ getconf cfauthurl
+ getconf ftp_password
+ getconf sshoptions
+ getconf bandwidthlimit 0
+ getconf desthost
+ getconf destdir
+ getconf destuser
+ destdir=${destdir%/}
+}
+
+### some voodoo to mangle the correct commands
+
+function mangle_cli(){
+
+ execstr_options="$options "
+ execstr_source=
+ if [ -n "$desturl" ]; then
+ [ -z "$destuser" ] || warning 'the configured destuser is ignored since desturl is set'
+ [ -z "$desthost" ] || warning 'the configured desthost is ignored since desturl is set'
+ [ -z "$destdir" ] || warning 'the configured destdir is ignored since desturl is set'
+ execstr_serverpart="$desturl"
+ else
+ execstr_serverpart="scp://$destuser@$desthost/$destdir"
+ fi
+
+
+ ### Symmetric or asymmetric (public/private key pair) encryption
+ if [ -n "$encryptkey" ]; then
+ execstr_options="${execstr_options} --encrypt-key $encryptkey"
+ fi
+
+ ### Data signing (or not)
+ if [ "$sign" == yes ]; then
+ # duplicity is not able to sign data when using symmetric encryption
+ [ -n "$encryptkey" ] || fatal "The encryptkey option must be set when signing."
+ # if needed, initialize signkey to a value that is not empty (checked above)
+ [ -n "$signkey" ] || signkey="$encryptkey"
+ execstr_options="${execstr_options} --sign-key $signkey"
+ fi
+
+ ### Temporary directory
+ precmd=
+ if [ -n "$tmpdir" ]; then
+ if [ ! -d "$tmpdir" ]; then
+ #info "Temporary directory ($tmpdir) does not exist, creating it."
+ mkdir -p "$tmpdir"
+ [ $? -eq 0 ] || fatal "Could not create temporary directory ($tmpdir)."
+ chmod 0700 "$tmpdir"
+ fi
+ #info "Using $tmpdir as TMPDIR"
+ precmd="${precmd}TMPDIR=$tmpdir "
+ fi
+
+ ### Source
+
+ set -o noglob
+
+ # excludes
+ SAVEIFS=$IFS
+ IFS=$(echo -en "\n\b")
+ for i in $exclude; do
+ str="${i//__star__/*}"
+ execstr_source="${execstr_source} --exclude '$str'"
+ done
+ IFS=$SAVEIFS
+
+ # includes
+ SAVEIFS=$IFS
+ IFS=$(echo -en "\n\b")
+ for i in $include; do
+ [ "$i" != "/" ] || fatal "Sorry, you cannot use 'include = /'"
+ str="${i//__star__/*}"
+ execstr_source="${execstr_source} --include '$str'"
+ done
+ IFS=$SAVEIFS
+
+ set +o noglob
+
+ execstr_options="${execstr_options} --ssh-options '$sshoptions'"
+ if [ "$bandwidthlimit" != 0 ]; then
+ [ -z "$desturl" ] || warning 'The bandwidthlimit option is not used when desturl is set.'
+ execstr_precmd="trickle -s -d $bandwidthlimit -u $bandwidthlimit"
+ fi
+}
+
+#function findlastdates(){
+# outputfile=$1
+# lastfull=0
+# lastinc=0
+# backuptime=0
+#
+# while read line; do
+# atime=0
+# arr=()
+# sort=''
+# test=$(echo $line|awk '{if (NF == 7); if ($1 == "Full" || $1 == "Incremental") {print $4, $3, $6, $5}}' )
+#
+# if [ -n "$test" ]; then
+# backuptime=$(date -u -d "$test" +%s)
+#
+# arr=($(echo $line|awk '{print $1, $2, $3, $4, $5, $6}'))
+# if [ ${arr[0]} == "Incremental" ] && [ "$lastinc" -lt "$backuptime" ] ; then
+# lastinc=$backuptime
+# elif [ ${arr[0]} == "Full" ] && [ "$lastfull" -lt "$backuptime" ] ; then
+# lastfull=$backuptime
+# fi
+#
+# fi
+#
+# done < $outputfile
+# # a full backup can be seen as incremental too
+# lastinc=$(echo $lastinc | awk 'max=="" || $1 > max {max=$1} END{ print max}')
+#}
+
+function check_status() {
+ grep -q 'No orphaned or incomplete backup sets found.' $1
+ if [ $? -ne 0 ] ; then
+ exit 2
+ fi
+}
+
+##
+## this function handles the freshness check of a backup action
+##
+
+function process_action() {
+ local file="$1"
+ local suffix="$2"
+ setfile $file
+ get_dupconf $1
+ mangle_cli
+
+ outputfile=`maketemp backupout`
+ export PASSPHRASE=$password
+ export FTP_PASSWORD=$ftp_password
+ output=` su -c \
+ "$execstr_precmd duplicity $execstr_options collection-status $execstr_serverpart >$outputfile 2>&1"`
+ exit_code=$?
+ echo -n $outputfile
+
+ #check_status
+ #findlastdates
+}
+
+files=`find $configdirectory -follow -mindepth 1 -maxdepth 1 -type f ! -name '.*.swp' | sort -n`
+
+for file in $files; do
+ [ -f "$file" ] || continue
+ suffix="${file##*.}"
+ base=`basename $file`
+ if [ "${base:0:1}" == "0" -o "$suffix" == "disabled" ]; then
+ continue
+ fi
+ if [ -e "$scriptdirectory/$suffix" -a "$suffix" == "dup" ]; then
+ process_action $file $suffix
+ fi
+done
+
diff --git a/files/nagios_plugins/duplicity/check_backupninja_duplicity.py b/files/nagios_plugins/duplicity/check_backupninja_duplicity.py
new file mode 100644
index 0000000..8ed9ce6
--- /dev/null
+++ b/files/nagios_plugins/duplicity/check_backupninja_duplicity.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+
+# Inspired by Arne Schwabe <arne-nagios@rfc2549.org> [with BSD license]
+# Inspired by backupninja [that's gpl some version]
+# minor changes by someon who doesn't understand all the license quirks
+
+from subprocess import Popen,PIPE
+import sys
+import time
+import os
+import argparse
+import getopt
+
+def main():
+ # getopt = much more writing
+ parser = argparse.ArgumentParser(description='Nagios Duplicity status checker')
+
+ parser.add_argument("-w", dest="warninc", default=28, type=int,
+ help="Number of hours allowed for incremential backup warning level, default 28")
+ parser.add_argument("-W", dest="warnfull", default=31, type=int,
+ help="Number of days allowed for full backup warning level, default 31")
+ parser.add_argument("-c", dest="critinc", default=52, type=int,
+ help="Number of hours allowed for incremential backup critical level, default 52")
+ parser.add_argument("-C", dest="critfull", default=33, type=int,
+ help="Number of days allowed for full backup critical level, default 33")
+ args = parser.parse_args()
+
+ okay = 0
+
+ # *sigh* check_output is from python 2.7 and onwards. Debian, upgrade yourself.
+ #output , err = check_output(['/root/freshness.sh'])
+
+ if os.path.isfile("/usr/lib/nagios/plugins/backupninja_duplicity_freshness.sh") and os.access("/usr/lib/nagios/plugins/backupninja_duplicity_freshness.sh", os.X_OK):
+ checkstatus, err = Popen(['/bin/bash', '/usr/lib/nagios/plugins/backupninja_duplicity_freshness.sh'], stdout=PIPE, stderr=PIPE, env={'HOME': '/root', 'PATH': os.environ['PATH']}).communicate()
+ elif os.path.isfile("/usr/local/lib/nagios/plugins/backupninja_duplicity_freshness.sh") and os.access("/usr/local/lib/nagios/plugins/backupninja_duplicity_freshness.sh", os.X_OK):
+ checkstatus, err = Popen(['/bin/bash', '/usr/local/lib/nagios/plugins/backupninja_duplicity_freshness.sh'], stdout=PIPE, stderr=PIPE, env={'HOME': '/root', 'PATH': os.environ['PATH']}).communicate()
+
+ # Don't use exec(), popen(), etc. to execute external commands without explicity using the full path of the external program. Hijacked search path could be problematic.
+ #checkstatus, err = Popen(['/bin/bash', './freshness.sh'], stdout=PIPE, stderr=PIPE, env={'HOME': '/root', 'PATH': os.environ['PATH']}).communicate()
+
+ #another sigh: Debian testing, upgrade yourself, this is only needed because Debian testing uses duplicity 0.6.18-3
+ # open file read/write
+ f = open (checkstatus,"r")
+ checklines = f.readlines()
+ f.close()
+
+ # remove the line that says Import of duplicity.backends.giobackend Failed: No module named gio
+ f = open(checkstatus,"w")
+ for line in checklines:
+ if not 'Import of duplicity.backends.giobackend Failed: No module named gio' in line:
+ f.write(line)
+ f.close()
+
+ output = open(checkstatus).read()
+
+ lastfull, lastinc = findlastdates(output)
+
+ sincelastfull = time.time() - lastfull
+ sincelastinc = time.time() - lastinc
+
+ msg = "OK: "
+
+ if sincelastfull > (args.warnfull * 24 * 3600) or sincelastinc > (args.warninc * 3600):
+ okay = 1
+ msg = "WARNING: "
+ if sincelastfull > (args.critfull * 24 * 3600) or sincelastinc > (args.critinc * 3600):
+ okay = 2
+ msg = "CRITICAL: "
+ if not checkoutput(output):
+ okay = max(okay,1)
+ msg = "WARNING: duplicity output: %s " % repr(output)
+ if err:
+ okay=2
+ msg = "Unexpected output: %s, " % repr(err)
+
+ print msg, "last full %s ago, last incremential %s ago|lastfull=%d, lastinc=%d" % ( formattime(sincelastfull), formattime(sincelastinc), sincelastfull, sincelastinc)
+
+ #clean up cruft
+ os.remove(checkstatus)
+ sys.exit(okay)
+
+def checkoutput(output):
+ if not 'No orphaned or incomplete backup sets found.' in output:
+ return False
+
+ return True
+
+def formattime(seconds):
+ days = seconds / (3600 * 24)
+ hours = seconds / 3600 % 24
+
+ if days:
+ return "%d days %d hours" % (days,hours)
+ else:
+ return "%d hours" % hours
+
+
+def findlastdates(output):
+ lastfull = 0
+ lastinc = 0
+
+ for line in output.split("\n"):
+ parts = line.split()
+
+ # ['Incremental', 'Sun', 'Oct', '31', '03:00:04', '2010', '1']
+ if len (parts) == 7 and parts[0] in ["Full","Incremental"]:
+ foo = time.strptime(" ".join(parts[1:6]),"%a %b %d %H:%M:%S %Y")
+
+ backuptime = time.mktime(foo)
+
+ if parts[0] == "Incremental" and lastinc < backuptime:
+ lastinc = backuptime
+ elif parts[0] == "Full" and lastfull < backuptime:
+ lastfull = backuptime
+
+
+ # Count a full backup as incremental backup
+ lastinc = max(lastfull,lastinc)
+ return (lastfull, lastinc)
+
+
+if __name__=='__main__':
+ main()
diff --git a/manifests/client.pp b/manifests/client.pp
index 287b02f..7e689bf 100644
--- a/manifests/client.pp
+++ b/manifests/client.pp
@@ -46,8 +46,10 @@ class backupninja::client::defaults {
class backupninja::client inherits backupninja::client::defaults {
define key(
- $user = false, $host = false, $installkey=false, $keyowner=false,
- $keygroup=false, $keystore=false, $keytype=false)
+ $user = false, $host = false, $createkey=false, $installkey=false,
+ $keyowner=false, $keygroup=false, $keystore=false, $keystorefspath='',
+ $keytype=false,
+ $keydest=false, $keydestname=false )
{
$real_user = $user ? {
false => $name,
@@ -78,9 +80,23 @@ class backupninja::client inherits backupninja::client::defaults {
false => "${backupninja::client::defaults::real_keytype}",
default => $keytype,
}
+ $key_dest = $keydest ? {
+ false => "${backupninja::client::defaults::real_keydestination}",
+ default => $keydest,
+ }
+ $key_dest_name = $keydestname ? {
+ false => "id_$key_type",
+ default => $keydestname,
+ }
+ $key_dest_file = "${key_dest}/${key_dest_name}"
- $key_dest = "${backupninja::client::defaults::real_keydestination}"
- $key_dest_file = "$key_dest/id_$key_type"
+ if $createkey == true {
+ if $keystorefspath == false {
+ err("need to define a destination directory for sshkey creation!")
+ }
+ $ssh_keys = ssh_keygen("${keystorefspath}/${key_dest_name}")
+ }
+
case $install_key {
true: {
@@ -92,7 +108,7 @@ class backupninja::client inherits backupninja::client::defaults {
}
if !defined(File["$key_dest_file"]) {
file { "$key_dest_file":
- source => "${key_store}/${real_user}_id_${key_type}",
+ source => "${key_store}/${key_dest_name}",
mode => 0400, owner => $key_owner, group => $key_group,
require => File["$key_dest"],
}
@@ -109,7 +125,7 @@ class backupninja::client::maildir inherits backupninja::client::defaults {
package { 'rsync':
ensure => $rsync_ensure_version,
}
- }
+ }
}
class backupninja::client::rdiff_backup inherits backupninja::client::defaults {
@@ -150,4 +166,4 @@ class backupninja::client::sys inherits backupninja::client::defaults {
}
default: {}
}
-}
+}
diff --git a/manifests/dup.pp b/manifests/dup.pp
index 23da8cd..5ffce29 100644
--- a/manifests/dup.pp
+++ b/manifests/dup.pp
@@ -79,7 +79,10 @@ define backupninja::duplicity( $order = 90,
$destuser = false,
# configs to backupninja client
$backupkeystore = false,
+ $backupkeystorefspath = '',
$backupkeytype = "rsa",
+ $backupkeydest = false,
+ $backupkeydestname = false,
# options to backupninja server sandbox
$ssh_dir_manage = true,
$ssh_dir = false,
@@ -87,6 +90,7 @@ define backupninja::duplicity( $order = 90,
$installuser = true,
$backuptag = false,
# key options
+ $createkey = false,
$installkey = true ) {
# the client with configs for this machine
@@ -95,7 +99,7 @@ define backupninja::duplicity( $order = 90,
case $desthost { false: { err("need to define a destination host for remote backups!") } }
case $destdir { false: { err("need to define a destination directory for remote backups!") } }
case $password { false: { err("a password is necessary either to unlock the GPG key, or for symmetric encryption!") } }
-
+
# guarantees there's a configured backup space for this backup
backupninja::server::sandbox { "${user}-${name}":
user => $destuser,
@@ -109,14 +113,18 @@ define backupninja::duplicity( $order = 90,
backupkeys => $backupkeystore,
keytype => $backupkeytype,
}
-
+
# the client's ssh key
backupninja::client::key { "${destuser}-${name}":
- user => $destuser,
- host => $desthost,
- installkey => $installkey,
- keytype => $backupkeytype,
- keystore => $backupkeystore,
+ user => $destuser,
+ host => $desthost,
+ createkey => $createkey,
+ installkey => $installkey,
+ keytype => $backupkeytype,
+ keystore => $backupkeystore,
+ keystorefspath => $backupkeystorefspath,
+ keydest => $backupkeydest,
+ keydestname => $backupkeydestname
}
# the backupninja rule for this duplicity backup
@@ -129,4 +137,4 @@ define backupninja::duplicity( $order = 90,
require => File["${backupninja::client::defaults::configdir}"]
}
}
-
+
diff --git a/manifests/generate_sshkey.pp b/manifests/generate_sshkey.pp
new file mode 100644
index 0000000..a3008e5
--- /dev/null
+++ b/manifests/generate_sshkey.pp
@@ -0,0 +1,33 @@
+define backupninja::generate_sshkey(
+ $ssh_key_basepath = '/etc/puppet/modules/keys/files/backupkeys',
+){
+
+ # generate backupninja ssh keypair
+ $ssh_key_name = "backup_${::hostname}_id_rsa"
+ $ssh_keys = ssh_keygen("${ssh_key_basepath}/${ssh_key_name}")
+ $public = split($ssh_keys[1],' ')
+ $public_type = $public[0]
+ $public_key = $public[1]
+
+ file { '/root/.ssh':
+ ensure => directory,
+ owner => 'root',
+ group => 'root',
+ mode => '0600';
+ }
+
+ # install ssh keypair on client
+ file { "/root/.ssh/$ssh_key_name":
+ content => $ssh_keys[0],
+ owner => root,
+ group => 0,
+ mode => '0600';
+ }
+
+ file { "/root/.ssh/$ssh_key_name.pub":
+ content => $public_key,
+ owner => root,
+ group => 0,
+ mode => '0666';
+ }
+}
diff --git a/manifests/init.pp b/manifests/init.pp
index 23b4268..fba8cc4 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -4,6 +4,7 @@ import "dup.pp"
import "labelmount.pp"
import "maildir.pp"
import "mysql.pp"
+import "pgsql.pp"
import "rdiff.pp"
import "server.pp"
import "sh.pp"
diff --git a/manifests/nagios_plugin/duplicity.pp b/manifests/nagios_plugin/duplicity.pp
new file mode 100644
index 0000000..7dbd263
--- /dev/null
+++ b/manifests/nagios_plugin/duplicity.pp
@@ -0,0 +1,45 @@
+class backupninja::nagios_plugin::duplicity {
+ case $::operatingsystem {
+ 'Debian': { package { 'python-argparse': ensure => installed, } }
+ 'Ubuntu': { package { 'python-argh': ensure => installed, } }
+ default: {
+ notify {'Backupninja-Duplicity Nagios check needs python-argparse to be installed !':} }
+ }
+
+ file { '/usr/lib/nagios/plugins/check_backupninja_duplicity.py':
+ source => 'puppet:///modules/backupninja/nagios_plugins/duplicity/check_backupninja_duplicity.py',
+ mode => '0755',
+ owner => 'nagios',
+ group => 'nagios',
+ }
+
+ # deploy helper script
+ file { '/usr/lib/nagios/plugins/backupninja_duplicity_freshness.sh':
+ source => 'puppet:///modules/backupninja/nagios_plugins/duplicity/backupninja_duplicity_freshness.sh',
+ mode => '0755',
+ owner => 'nagios',
+ group => 'nagios',
+ }
+
+ nagios::nrpe::command { 'check_backupninja_duplicity':
+ command_line => "sudo ${::nagios::nrpe::nagios_plugin_dir}/check_backupninja_duplicity.py"
+ }
+ sudo::spec {'nrpe_check_backupninja_duplicity':
+ ensure => present,
+ users => 'nagios',
+ hosts => 'ALL',
+ commands => "NOPASSWD: ${::nagios::nrpe::nagios_plugin_dir}/check_backupninja_duplicity.py";
+ }
+
+ nagios::service { "Backupninja Duplicity $::fqdn":
+ use_nrpe => true,
+ check_command => 'check_backupninja_duplicity',
+ nrpe_timeout => '60',
+ # check only twice a day
+ normal_check_interval => '720',
+ # recheck every hour
+ retry_check_interval => '60',
+ }
+
+
+}
diff --git a/manifests/pgsql.pp b/manifests/pgsql.pp
new file mode 100644
index 0000000..07fab32
--- /dev/null
+++ b/manifests/pgsql.pp
@@ -0,0 +1,29 @@
+# Safe PGSQL dumps, as part of a backupninja run.
+#
+# Valid attributes for this type are:
+#
+# order: The prefix to give to the handler config filename, to set
+# order in which the actions are executed during the backup run.
+#
+# ensure: Allows you to delete an entry if you don't want it any more
+# (but be sure to keep the configdir, name, and order the same, so
+# that we can find the correct file to remove).
+#
+# backupdir, compress, configfile: As defined in the
+# backupninja documentation, with the caveat that hotcopy, sqldump,
+# and compress take true/false rather than yes/no.
+#
+define backupninja::pgsql(
+ $order = 10, $ensure = present, $databases = 'all', $backupdir = "/var/backups/postgres", $compress = true, $vsname = false)
+{
+
+ include backupninja::client::defaults
+ file { "${backupninja::client::defaults::configdir}/${order}_${name}.pgsql":
+ ensure => $ensure,
+ content => template('backupninja/pgsql.conf.erb'),
+ owner => root,
+ group => root,
+ mode => 0600,
+ require => File["${backupninja::client::defaults::configdir}"]
+ }
+}
diff --git a/manifests/rdiff.pp b/manifests/rdiff.pp
index 5ff7cb5..1fc9abb 100644
--- a/manifests/rdiff.pp
+++ b/manifests/rdiff.pp
@@ -16,7 +16,8 @@
# directories.
#
define backupninja::rdiff(
- $order = 90, $ensure = present, $user = false, $home = false, $host = false,
+ $order = 90, $ensure = present, $user = false,
+ $home = "/home/${user}-${name}", $host = false,
$type = 'local',
$exclude = [ "/home/*/.gnupg", "/home/*/.local/share/Trash", "/home/*/.Trash",
"/home/*/.thumbnails", "/home/*/.beagle", "/home/*/.aMule",
@@ -29,6 +30,8 @@ define backupninja::rdiff(
{
include backupninja::client::rdiff_backup
+ $directory = "$home/rdiff-backup/"
+
case $type {
'remote': {
case $host { false: { err("need to define a host for remote backups!") } }
@@ -37,18 +40,9 @@ define backupninja::rdiff(
default => $backuptag
}
- $real_home = $home ? {
- false => $backupdir ? {
- '' => "/backup/${fqdn}",
- default => "${backupdir}/${fqdn}",
- },
- default => $home,
- }
- $directory = "${real_home}/rdiff-backup/"
-
backupninja::server::sandbox
{
- "${user}-${name}": user => $user, host => $fqdn, dir => $real_home,
+ "${user}-${name}": user => $user, host => $fqdn, dir => $home,
manage_ssh_dir => $ssh_dir_manage, ssh_dir => $ssh_dir, key => $key,
authorized_keys_file => $authorized_keys_file, installuser => $installuser,
backuptag => $real_backuptag, keytype => $backupkeytype, backupkeys => $backupkeystore,
@@ -64,6 +58,8 @@ define backupninja::rdiff(
}
}
}
+
+
file { "${backupninja::client::defaults::configdir}/${order}_${name}.rdiff":
ensure => $ensure,
content => template('backupninja/rdiff.conf.erb'),
diff --git a/templates/pgsql.conf.erb b/templates/pgsql.conf.erb
new file mode 100644
index 0000000..7781ef4
--- /dev/null
+++ b/templates/pgsql.conf.erb
@@ -0,0 +1,11 @@
+<% if vsname %>
+vsname = <%= vsname %>
+<% end %>
+<% if backupdir %>
+backupdir = <%= backupdir %>
+<% end %>
+<% if databases %>
+databases = <%= databases %>
+<% end %>
+compress = <%= compress ? 'yes' : 'no' %>
+