Skip to content

Commit

Permalink
Add support for snapshots using pre/post scripts
Browse files Browse the repository at this point in the history
Snapshots should be created using `pre_backup_script` and cleaned up
with `post_backup_script`. Additionally, the `working_directory` and the
`source_paths` paths should be adjusted to match the snapshot mount
point.
  • Loading branch information
hashworks committed Apr 7, 2022
1 parent ba59b2d commit dfefe00
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 18 deletions.
45 changes: 45 additions & 0 deletions REFERENCE.md
Expand Up @@ -40,12 +40,15 @@ The following parameters are available in the `borg` class:
* [`keep_daily`](#keep_daily)
* [`keep_within`](#keep_within)
* [`compression`](#compression)
* [`working_directory`](#working_directory)
* [`source_paths`](#source_paths)
* [`excludes`](#excludes)
* [`includes`](#includes)
* [`backupserver`](#backupserver)
* [`install_restore_script`](#install_restore_script)
* [`restore_script_path`](#restore_script_path)
* [`backupdestdir`](#backupdestdir)
* [`backupdatadir`](#backupdatadir)
* [`absolutebackupdestdir`](#absolutebackupdestdir)
* [`manage_repository`](#manage_repository)
* [`exclude_pattern`](#exclude_pattern)
Expand All @@ -67,6 +70,8 @@ The following parameters are available in the `borg` class:
* [`wants`](#wants)
* [`requires`](#requires)
* [`after`](#after)
* [`pre_backup_script`](#pre_backup_script)
* [`post_backup_script`](#post_backup_script)

##### <a name="package_name"></a>`package_name`

Expand Down Expand Up @@ -154,6 +159,22 @@ Compression method and level to use. See the output of `borg help compression` f

Default value: `'lz4'`

##### <a name="working_directory"></a>`working_directory`

Data type: `String[Stdlib::Absolutepath]`

The working directory from where the backup should be created.

Default value: `'/'`

##### <a name="source_paths"></a>`source_paths`

Data type: `Array[Stdlib::Path]`

A list of relative or absolute paths to backup.

Default value: `['/']`

##### <a name="excludes"></a>`excludes`

Data type: `Array[Stdlib::Absolutepath]`
Expand Down Expand Up @@ -196,6 +217,14 @@ The path on the remote server where the backups should be written to. $username

Default value: `'borg'`

##### <a name="backupdatadir"></a>`backupdatadir`

Data type: `String[Stdlib::Absolutepath]`

The path where additional backup data should be stored.

Default value: `'/root/backup-data/'`

##### <a name="absolutebackupdestdir"></a>`absolutebackupdestdir`

Data type: `Optional[String[1]]`
Expand Down Expand Up @@ -360,3 +389,19 @@ Array of units that should be started before the borg-backup service

Default value: `['network-online.target']`

##### <a name="pre_backup_script"></a>`pre_backup_script`

Data type: `Optional[String[1]]`

BASH code to be executed before the backup job starts. If you wish to use snapshots, create them here.

Default value: ``undef``

##### <a name="post_backup_script"></a>`post_backup_script`

Data type: `Optional[String[1]]`

BASH code to be executed after the backup job has finished. If you need to perform any cleanup do so here.

Default value: ``undef``

21 changes: 12 additions & 9 deletions manifests/config.pp
Expand Up @@ -12,15 +12,18 @@
ensure => 'file',
content => epp("${module_name}/borg-backup.sh.epp",
{
'manage_prune' => $borg::manage_prune,
'keep_within' => $borg::keep_within,
'keep_daily' => $borg::keep_daily,
'keep_weekly' => $borg::keep_weekly,
'keep_monthly' => $borg::keep_monthly,
'keep_yearly' => $borg::keep_yearly,
'compression' => $borg::compression,
'backupdestdir' => $backupdestdir,
'exclude_pattern' => $borg::exclude_pattern + $borg::additional_exclude_pattern,
'manage_prune' => $borg::manage_prune,
'keep_within' => $borg::keep_within,
'keep_daily' => $borg::keep_daily,
'keep_weekly' => $borg::keep_weekly,
'keep_monthly' => $borg::keep_monthly,
'keep_yearly' => $borg::keep_yearly,
'compression' => $borg::compression,
'working_directory' => $borg::working_directory,
'backupdestdir' => $backupdestdir,
'backupdatadir' => $borg::backupdatadir,
'pre_backup_script' => $borg::pre_backup_script,
'post_backup_script' => $borg::post_backup_script,
}),
mode => '0755',
owner => 'root',
Expand Down
20 changes: 20 additions & 0 deletions manifests/init.pp
Expand Up @@ -33,6 +33,12 @@
# @param compression
# Compression method and level to use. See the output of `borg help compression` for available options.
#
# @param working_directory
# The working directory from where the backup should be created.
#
# @param source_paths
# A list of relative or absolute paths to backup.
#
# @param excludes
# list of default mountpoints that should be excluded from backups. Every mountpoint needs to be explicitly excluded or included. See also the additional_excludes parameter.
#
Expand All @@ -51,6 +57,9 @@
# @param backupdestdir
# The path on the remote server where the backups should be written to. $username will be prepended
#
# @param backupdatadir
# The path where additional backup data should be stored.
#
# @param absolutebackupdestdir
# By defaults, backups will be written on the remote host to $username/$backupdestdir. if $absolutebackupdestdir is set this will be used instead
#
Expand Down Expand Up @@ -114,6 +123,12 @@
# @param after
# Array of units that should be started before the borg-backup service
#
# @param pre_backup_script
# BASH code to be executed before the backup job starts. If you wish to use snapshots, create them here.
#
# @param post_backup_script
# BASH code to be executed after the backup job has finished. If you need to perform any cleanup do so here.
#
# @see https://metacpan.org/pod/App::BorgRestore
#
class borg (
Expand All @@ -133,9 +148,12 @@
Integer[0] $keep_daily = 60,
Integer[0] $keep_within = 30,
String[1] $compression = 'lz4',
Stdlib::Absolutepath $working_directory = '/',
Array[String[1]] $source_paths = ['/'],
Array[Stdlib::Absolutepath] $excludes = ['/tmp', '/sys', '/dev', '/proc', '/run', '/media', '/var/lib/nfs/rpc_pipefs'],
Array[Stdlib::Absolutepath] $includes = ['/', '/boot', '/boot/efi', '/boot/EFI', '/var/log'],
String[1] $backupdestdir = 'borg',
Stdlib::Absolutepath $backupdatadir = '/root/backup-data/',
Optional[String[1]] $absolutebackupdestdir = undef,
Array[String[1]] $exclude_pattern = ['sh:/home/*/.cache/*', 'sh:/root/.cache/*', 'sh:/var/cache/pacman/pkg/*'],
Array[String[1]] $additional_exclude_pattern = [],
Expand All @@ -155,6 +173,8 @@
Array[String[1]] $wants = ['network-online.target'],
Array[String[1]] $requires = [],
Array[String[1]] $after = ['network-online.target'],
Optional[String[1]] $pre_backup_script = undef,
Optional[String[1]] $post_backup_script = undef,
) {
contain borg::install
contain borg::config
Expand Down
4 changes: 2 additions & 2 deletions spec/classes/init_spec.rb
Expand Up @@ -213,7 +213,7 @@

it { is_expected.to contain_file('/etc/borg').with_content(%r{^REPOSITORY=backup:/some/other/path$}) }
it { is_expected.to contain_file('/etc/profile.d/borg.sh').with_content(%r{^export BORG_REPO=backup:/some/other/path$}) }
it { is_expected.to contain_file('/usr/local/bin/borg-backup').with_content(%r{\s*borg_repo="backup:/some/other/path"$}) }
it { is_expected.to contain_file('/usr/local/bin/borg-backup').with_content(%r{^\s*borg_repo="backup:/some/other/path"$}) }
end

context 'with additional excludes' do
Expand All @@ -224,7 +224,7 @@
}
end

it { is_expected.to contain_file('/usr/local/bin/borg-backup').with_content(%r{^"/path with/spaces"$}) }
it { is_expected.to contain_file('/usr/local/bin/borg-backup').with_content(%r{^\s*"/path with/spaces"$}) }
end

context 'without exclude_pattern' do
Expand Down
35 changes: 28 additions & 7 deletions templates/borg-backup.sh.epp
Expand Up @@ -5,8 +5,11 @@
Integer[0] $keep_daily,
Integer[0] $keep_within,
String[1] $compression,
Stdlib::Absolutepath $working_directory,
String[1] $backupdestdir,
Array[String[1]] $exclude_pattern,
Stdlib::Absolutepath $backupdatadir,
Optional[String[1]] $pre_backup_script,
Optional[String[1]] $post_backup_script,
| -%>
#!/bin/bash
#
Expand Down Expand Up @@ -46,7 +49,7 @@
# modified by Tim 'bastelfreak' Meusel
##

set -e
set -eu

# set PATH by hand so we ensure that the puppetlabs stuff is present
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/puppetlabs/bin:/bin:/sbin"
Expand Down Expand Up @@ -89,21 +92,29 @@ main() {
<% $borg::exclude_pattern.each |$key| { -%>
<%= $key %>
<% } -%>
<% $borg::additional_exclude_pattern.each |$key| { -%>
<%= $key %>
<% } -%>
EOF

source_paths=(
<% $borg::source_paths.each |$key| { -%>
"<%= $key %>"
<% } -%>
)

exclude_mountpoints
echo "$excludeList" > "$TMPDIR/exclude-list-borg"

run_if_exists pre_backup
backup_borg / "$borg_repo"
backup_borg "$borg_repo" "${source_paths[@]}"
run_if_exists post_backup
}

# This is called before creating the backup
pre_backup() {
# save some data that's useful for restores
local backupDataDir=/root/backup-data/
local backupDataDir="<%= $backupdatadir %>"
mkdir -p "$backupDataDir"
if [ $(command -v fdisk) ]; then
fdisk -l > "$backupDataDir/fdisk"
Expand Down Expand Up @@ -131,6 +142,9 @@ pre_backup() {
fi

# If you wish to use snapshots, create them here
<% if $pre_backup_script { -%>
<%= $pre_backup_script %>
<% } -%>

return
}
Expand All @@ -139,12 +153,16 @@ pre_backup() {
post_backup() {
# If you need to perform any cleanup do so here

<% if $post_backup_script { -%>
<%= $post_backup_script %>
<% } -%>

return
}

backup_borg() {
local src=$1
local dst=$2
local dst=$1; shift
local src=("$@")
local -a options=(
--verbose
--numeric-ids
Expand All @@ -156,7 +174,10 @@ backup_borg() {
options+=(--progress --list --filter AME)
fi

borg create "${options[@]}" --stats --verbose "$dst::backup-$(date "+%Y%m%d-%H%M%S")" "$src"
# Change the working directory in case the source paths are relative
cd "<%= $working_directory %>"

borg create "${options[@]}" --stats --verbose "$dst::backup-$(date "+%Y%m%d-%H%M%S")" "${src[@]}"
<% if $manage_prune { -%>
# keep all backups from the last <%= $keep_within %> days
# keep at least one backup for each day for <%= $keep_daily %> days
Expand Down

0 comments on commit dfefe00

Please sign in to comment.