diff --git a/.goreleaser.yml b/.goreleaser.yml index 2b989072..9cb364ec 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -153,15 +153,24 @@ nfpms: postinstall: "contrib/posix/post-install.sh" contents: - { type: config, src: contrib/posix/profiles.conf, dst: /etc/resticprofile/profiles.conf.dist } + - { type: config, src: contrib/posix/conf.d/backup.conf, dst: /etc/resticprofile/conf.d/backup.conf.dist } - { type: config, src: contrib/posix/conf.d/check.conf, dst: /etc/resticprofile/conf.d/check.conf.dist } - { type: config, src: contrib/posix/conf.d/hooks.conf, dst: /etc/resticprofile/conf.d/hooks.conf.dist } - { type: config, src: contrib/posix/conf.d/metrics.conf, dst: /etc/resticprofile/conf.d/metrics.conf.dist } - { type: config, src: contrib/posix/conf.d/prune.conf, dst: /etc/resticprofile/conf.d/prune.conf.dist } - - { type: config, src: contrib/posix/conf.d/repository.conf, dst: /etc/resticprofile/conf.d/repository.conf.dist } + - { type: config, src: contrib/posix/conf.d/z_overrides.conf, dst: /etc/resticprofile/conf.d/z_overrides.conf.dist } - { type: config, src: contrib/posix/profiles.d/fs-snapshot.yaml.sample, dst: /etc/resticprofile/profiles.d/fs-snapshot.yaml.sample } - - { type: config, src: contrib/posix/profiles.d/system.toml, dst: /etc/resticprofile/profiles.d/system.toml.dist } + - { type: config, src: contrib/posix/profiles.d/minimal.conf.sample, dst: /etc/resticprofile/profiles.d/minimal.conf.sample } + - { type: config, src: contrib/posix/profiles.d/minimal.yaml.sample, dst: /etc/resticprofile/profiles.d/minimal.yaml.sample } + - { type: config, src: contrib/posix/profiles.d/system.conf, dst: /etc/resticprofile/profiles.d/system.conf.dist } + - { type: config, src: contrib/posix/repository.d/default.conf, dst: /etc/resticprofile/repository.d/default.conf.dist } + - { type: config, src: contrib/posix/repository.d/other.conf.sample, dst: /etc/resticprofile/repository.d/other.conf.sample } + - { type: config, src: contrib/posix/templates/default-host.conf, dst: /etc/resticprofile/templates/default-host.conf.dist } + - { type: config, src: contrib/posix/templates/default-tags.conf, dst: /etc/resticprofile/templates/default-tags.conf.dist } - { type: config, src: contrib/posix/templates/systemd.timer.in, dst: /etc/resticprofile/templates/systemd.timer.in.dist } - { type: config, src: contrib/posix/templates/systemd.unit.in, dst: /etc/resticprofile/templates/systemd.unit.in.dist } - - src: contrib/systemd/resticprofile-send-error.sh + - src: contrib/posix/resticprofile-send-error.rc + dst: /etc/resticprofile/resticprofile-send-error.rc.dist + - src: contrib/notification-scripts/resticprofile-send-error.sh dst: /usr/local/bin/resticprofile-send-error - file_info: { mode: 0640, owner: root, group: root } + file_info: { mode: 0755, owner: root, group: root } diff --git a/contrib/notification-scripts/README.md b/contrib/notification-scripts/README.md index 8edc25e9..0bcb6232 100644 --- a/contrib/notification-scripts/README.md +++ b/contrib/notification-scripts/README.md @@ -15,6 +15,7 @@ Usage: resticprofile-send-error.sh [options] user1@domain user2@domain ... Options: -s Only send mail when operating on schedule (RESTICPROFILE_ON_SCHEDULE=1) + -o name,.. Only send mail when PROFILE_NAME is in the list of specified names -c command Set the profile command (instead of PROFILE_COMMAND) -n name Set the profile name (instead of PROFILE_NAME) -p Print mail to stdout instead of sending it diff --git a/contrib/notification-scripts/resticprofile-send-error.sh b/contrib/notification-scripts/resticprofile-send-error.sh index adc4e96e..8ad17940 100755 --- a/contrib/notification-scripts/resticprofile-send-error.sh +++ b/contrib/notification-scripts/resticprofile-send-error.sh @@ -7,6 +7,7 @@ help() { Usage $1 [options] user1@domain user2@domain ... Options: -s Only send mail when operating on schedule (RESTICPROFILE_ON_SCHEDULE=1) + -o name,.. Only send mail when PROFILE_COMMAND is in the list of specified names -c command Set the profile command (instead of PROFILE_COMMAND) -n name Set the profile name (instead of PROFILE_NAME) -p Print mail to stdout instead of sending it @@ -17,9 +18,11 @@ HELP # Parse CLI args FORCE_SENDING=0 SEND_COMMAND="" -while getopts 'c:fhn:ps' flag ; do +LIMIT_COMMAND_NAMES="" +while getopts 'c:fhn:o:ps' flag ; do case "${flag}" in c) PROFILE_COMMAND="${OPTARG}" ;; + o) LIMIT_COMMAND_NAMES="${OPTARG}" ;; f) FORCE_SENDING=1 ;; n) PROFILE_NAME="${OPTARG}" ;; p) SEND_COMMAND="cat -" ;; @@ -51,14 +54,14 @@ RC_FILE="/etc/resticprofile/$(basename "$0").rc}" [[ -f "${RC_FILE}" ]] && source "${RC_FILE}" main() { - if [[ -n "${PROFILE_NAME}" || "${FORCE_SENDING}" == "1" ]] ; then + if can_send ; then if [[ -n "${DETAILS_COMMAND}" ]] ; then DETAILS_COMMAND_RESULT="$(${DETAILS_COMMAND})" fi for email in "$@" "${MAIL_TO}" ; do if [[ "${email}" =~ ^[a-zA-Z0-9_.%+-]+@[a-zA-Z0-9_]+[a-zA-Z0-9_.-]+$ ]] ; then - send_mail "${email}" || echo "Failed sending to \"${email}\"" + send_mail "${email}" || echo "Failed sending to \"${email}\" using '${SEND_COMMAND}' exit code $?" elif [[ -n "${email}" ]] ; then echo "Skipping notification for invalid address \"${email}\"" fi @@ -67,6 +70,22 @@ main() { return 0 } +can_send() { + if [[ -n "${PROFILE_NAME}" ]] ; then + if [[ -n "${LIMIT_COMMAND_NAMES}" ]] ; then + local IFS=",; " + for cmd in ${LIMIT_COMMAND_NAMES} ; do + [[ "${PROFILE_COMMAND}" == "$cmd" ]] && return 0 + done + else + return 0 + fi + fi + + [[ "${FORCE_SENDING}" == "1" ]] + return $? +} + send_mail() { ${SEND_COMMAND} <>> "profiles.d/example.conf" +# +# [profiles.example] +# description = "Backup example" +# inherit = "base" +# +# [profiles.example.backup] +# schedule = "daily" +# source = [ +# "/path/to/backup", +# "/other/path/to/backup", +# ] +# +# <<< +# + + +## +# Backup defaults +[profiles.default.backup] + +# Hostname and tags to identify backup snapshots in the repository +{{ template "conf:default-host" . }} +{{ template "conf:default-tags" . }} + +# Exclude known cache files & folders from backups +exclude-caches = true + +# Exclude nested filesystems +# Prefer overriding this option in dedicated backup profiles instead of +# globally as it can greatly increase the volume if nested FS mounts are +# contained in backup source paths. +one-file-system = true + +# Toggle whether a failure in reading a backup source is considered an error +no-error-on-warning = false + +# Wait on acquiring locks when running the profile on a schedule +schedule-lock-wait = "45m" + +# Specify the user that runs profile tasks on a schedule +# "system" - root runs the profile tasks +# "user" - user that created the schedule runs the profile tasks +schedule-permission = "system" + +# Toggle verbose output for troubleshooting +#verbose = false + +# Toggles immediate repository check before and after backup. +# Checks can be heavy on resources. Consider scheduling "maintenance" +# (see "conf.d/check.conf") instead of enabling checks here. +check-before = false +check-after = false + + +## +# Snapshot retention defaults +[profiles.default.retention] +# Remove obsolete snapshots prior to starting a backup +before-backup = false +# Remove obsolete snapshots after a successful backup +after-backup = true + +# +# Note: Retention operates on host, path and tag filters to identify snapshots +# to retain or remove. In most cases these filters should be in sync with +# the backup configuration of a profile so that snapshots will be removed +# that truely belong to a profile's backup. +# + +# Copying "host" block to identify snapshots by hostname +{{ template "conf:default-host" . }} + +# Retention allows to build tag filter from backup with 'true'. It is strongly +# advised not to change this as tags are the primary filter besides hostname. +tag = true + +# Copying backup source paths to identify snapshots to retain or remove. +# Set to "false" or a list of paths to disable or customize the path filter. +# +# It may make sense to disable path filters when source paths change. Ensure +# that tags and hostname can properly identify snapshots when disabling paths. +path = true + +# Specify the snapshots to keep when checking for obsolete snapshots +# Snapshots that do not match any condition are removed +keep-tag = [ "forever" ] +keep-last = 3 +#keep-hourly = 1 +#keep-daily = 1 +#keep-weekly = 1 +#keep-monthly = 1 +#keep-yearly = 1 +#keep-within = "30d" + +# Use compact format for listing snapshots +#compact = false + +# Toggles immediate prune of the repository as snapshots are removed. +# +# While removing snapshots is a light operation, prune (reclaim space) can +# be heavy on resources as it rewrites parts of the repository. +# Consider scheduling "maintenance" (see "conf.d/prune.conf") instead of +# enabling prune here. +# +# Also an attempt to recover a removed snapshot with "resticprofile recover" +# only works as long as the repository was not yet pruned. +prune = false + + +## +# Defaults for operations on repository snapshots of this host +# Usage: +# - "resticprofile snapshots" - view snapshots +# - "resticprofile mount /mnt/restore" - mount snapshots +# - "resticprofile ls latest /" - list files in a snapshot +# - "resticprofile dump latest /file" - dump a file to stdout +# - "resticprofile find PATTERN..." - find files in snapshots +# - "resticprofile copy --repo2=..." - copy snapshots to repo2 +# - "resticprofile restore --target=/to/dir --include=PATTERN... latest" +[profiles.default.copy] +{{ template "conf:default-host" . }} +schedule-lock-wait = "1h30m" +[profiles.default.dump] +{{ template "conf:default-host" . }} +[profiles.default.find] +{{ template "conf:default-host" . }} +[profiles.default.forget] +{{ template "conf:default-host" . }} +[profiles.default.ls] +{{ template "conf:default-host" . }} +[profiles.default.mount] +{{ template "conf:default-host" . }} +[profiles.default.restore] +{{ template "conf:default-host" . }} +[profiles.default.snapshots] +{{ template "conf:default-host" . }} +[profiles.default.stats] +{{ template "conf:default-host" . }} +[profiles.default.tag] +{{ template "conf:default-host" . }} + + +## +# Setup operations on repository snapshots for profiles deriving from "base" +# Usage: +# - "resticprofile profileName.snapshots" - view snapshots +# - "resticprofile profileName.mount /mnt/restore" - mount snapshots +# - "resticprofile profileName.ls latest /" - list files in a snapshot +# - "resticprofile profileName.dump latest /file" - dump a file to stdout +# - "resticprofile profileName.find PATTERN..." - find files in snapshots +# - "resticprofile profileName.copy --repo2=..." - copy snapshots to repo2 +# - "resticprofile profileName.restore --target=/to/dir latest" +[profiles.base.copy] +{{ template "conf:default-tags" . }} +[profiles.base.dump] +{{ template "conf:default-tags" . }} +[profiles.base.find] +{{ template "conf:default-tags" . }} +[profiles.base.forget] +{{ template "conf:default-tags" . }} +[profiles.base.ls] +{{ template "conf:default-tags" . }} +[profiles.base.mount] +{{ template "conf:default-tags" . }} +[profiles.base.restore] +{{ template "conf:default-tags" . }} +[profiles.base.snapshots] +{{ template "conf:default-tags" . }} +[profiles.base.stats] +{{ template "conf:default-tags" . }} +[profiles.base.tag] +{{ template "conf:default-tags" . }} + + +# ----------------------------------------------------------------------------- diff --git a/contrib/posix/conf.d/check.conf b/contrib/posix/conf.d/check.conf index 806058ce..6dcd1e78 100644 --- a/contrib/posix/conf.d/check.conf +++ b/contrib/posix/conf.d/check.conf @@ -1,71 +1,52 @@ - -## -# Groups for profiles that check & verify repositories -# Usage -# - `resticprofile -n check-all` -# - `resticprofile -n check-all schedule` -# - `resticprofile -n check-all unschedule` -# - `resticprofile -n verify-all` -# - `resticprofile -n verify-all schedule` -# - `resticprofile -n verify-all unschedule` -[groups] -check-all = [ "check" ] -verify-all = [ "verify" ] - - +# ----------------------------------------------------------------------------- ## -# Profile "check" may be used to schedule repository checks +# Repository check defaults # # Usage -# - `resticprofile -n check` -# - `resticprofile -n check schedule` -# - `resticprofile -n check unschedule` # -[check] -# Operate on the pepository defined in the "base" profile -inherit = "base" -initialize = false -default-command = "check" - -# Configuring the "check" command in profile "check" -[check.check] -schedule = "daily" -schedule-lock-wait = "4h" +# Run check on the default profile: +# - "resticprofile check" +# Run check on all maintenance profiles: +# - "resticprofile maintenance-all.check" # -# Check cache -# `check` uses a separate local repo cache to detect problems. The default -# is to create this cache below "/tmp/". While the daily check (without reading -# actual data) uses less space cache-dir may require changing when on tmpfs -cache-dir = "{{.TempDir}}/.restic-temp-check-cache" -with-cache = true +# Schedule the default maintenance profile: +# - "resticprofile maintenance.schedule" +# - "resticprofile maintenance.unschedule" +# Schedule all maintenance profiles: +# - "resticprofile maintenance-all.schedule" +# - "resticprofile maintenance-all.unschedule" +# + ## -# Profile "verify" may be used to schedule deep repository checks +# Defaults for repository checks +[profiles.default.check] +# Read actual repository data for verification +read-data = false +# Read a subset of the repository for verification (when read-data = true) +read-data-subset = "33%" # -# Usage -# - `resticprofile -n verify` -# - `resticprofile -n verify schedule` -# - `resticprofile -n verify unschedule` -# -[verify] -# Operate on the pepository defined in the "base" profile -inherit = "base" -initialize = false -default-command = "check" +# Check cache setup +# "check" uses a separate local one-time repo cache to detect problems. +# The default is to create this cache below "/tmp/" and it may grow to several +# GB during check execution, adjust path if needed. +cache-dir = "{{ .TempDir }}/restic-check-cache.resticprofile" +with-cache = true +# Allow longer lock waits for check schedules to ensure checks run as other +# tasks take longer to complete +schedule-lock-wait = "8h" +# Only root may schedule check +schedule-permission = "system" + -# Configuring the "check" command in profile "verify" -[verify.check] -schedule = "monthly" -schedule-lock-wait = "48h" -# Read the entire repository for verification +## +# Configuring "check" schedule in maintenance profile +[profiles.maintenance.check] +# Schedule at 5th, 10th, 15th, 20th, 25th and 30th day in month at 04:15 +schedule = "*-*-5,10,15,20,25,30 04:15:00" +# Read repository data for verification every 15th day in month +{{ if .Now.Day | eq 15 -}} read-data = true -# Read a subset of the repository for verification -#read-data-subset = "15%" -# -# Check cache -# `check` uses a separate local repo cache to detect problems. The built-in -# default location of this cache is "/tmp/" which can cause issues on tmpfs -# as the cache may need several GB of storage. Overridding built-in default -# for the full repo verification check: -cache-dir = "~/.restic-temp-check-cache" -with-cache = true +{{ end -}} + +# ----------------------------------------------------------------------------- diff --git a/contrib/posix/conf.d/hooks.conf b/contrib/posix/conf.d/hooks.conf index 0c5725e3..0b6434f9 100644 --- a/contrib/posix/conf.d/hooks.conf +++ b/contrib/posix/conf.d/hooks.conf @@ -1,19 +1,53 @@ +# ----------------------------------------------------------------------------- +## +# Base configuration for action hooks that run before, after, after failure or +# always after a set of profile tasks (profile task = restic command or +# action hook) +# +# The following additional environment variables are defined in an action: +# +# - PROFILE_NAME - Name of the active profile +# - PROFILE_COMMAND - Name of the requested command +# - ERROR - Error message if the requested command failed +# - ERROR_EXIT_CODE - Exit code of the failing command or action hook +# - ERROR_COMMANDLINE - Commandline of the failing command or action hook +# - ERROR_STDERR - Stderr of the failing command or action hook +# ## # Action hooks for profiles that derive from "base" -[base] -# Actions to run before any profile task -#run-before = [ -# 'echo ">>> ${PROFILE_NAME} - BEGIN ${PROFILE_COMMAND}"', -#] +[profiles.base] +## +# Actions to run before restic +run-before = [ + #'echo ">>> ${PROFILE_NAME} - BEGIN ${PROFILE_COMMAND}"', +] -# Actions to run after a profile task -#run-after = [ -# 'echo "<<< ${PROFILE_NAME} - END ${PROFILE_COMMAND}"', -#] +## +# Actions to run after restic (only if "run-before" and "restic" succeeded) +run-after = [ + #'echo "<<< ${PROFILE_NAME} - END ${PROFILE_COMMAND}"', +] -# Actions to run when a profile task has failed +## +# Actions to run when a profile task has failed (triggers as "run-before", +# "restic" or "run-after" failed) +# +# ERROR variables are set and contain details on the failed task run-after-fail = [ - 'echo "!!! ${PROFILE_NAME} - FAILED ${PROFILE_COMMAND}" - ERROR: ${ERROR}"', - # 'resticprofile-send-error admin@localhost', + # Example: Print error + 'echo "!!! ${PROFILE_NAME} - FAILED ${PROFILE_COMMAND} - ERROR: ${ERROR}"', + + # Send mail (see /etc/resticprofile/resticprofile-send-error.rc) + 'resticprofile-send-error -s -o "check,copy,forget,backup,prune"', ] + +## +# Actions to run in any case after all other actions. +# +# On failure ERROR variables are set and contain details on the failed task +run-finally = [ + '["${PROFILE_COMMAND}" == "check"] && rm -rf "{{ .TempDir }}/restic-check-cache.resticprofile"', +] + +# ----------------------------------------------------------------------------- diff --git a/contrib/posix/conf.d/metrics.conf b/contrib/posix/conf.d/metrics.conf index 8d99b48d..73f2034d 100644 --- a/contrib/posix/conf.d/metrics.conf +++ b/contrib/posix/conf.d/metrics.conf @@ -1,15 +1,32 @@ +# ----------------------------------------------------------------------------- +## +# Metrics collection configuration +# +# Resticprofile can create metrics for prometheus or as a custom JSON format. +# In order to create metrics, the option "extended-status = true" must be set +# for "backup" along with metrics output configuration in the profile. +# ## -# Metric collection for profiles that derive from "base" -[base.backup] +# Toggle metrics collection in "backup" for profiles that derive from "base" +[profiles.base.backup] # Toggles full "restic" output capture to allow collecting backup metrics # for "status-file" and "prometheus-(save-to-file|push)" #extended-status = true + +## +# Metric configuration for profiles that derive from "base" +[profiles.base] +## # Write backup metrics as JSON (requires extended-status = true) -#status-file = "{{.TempDir}}/resticprofile-{{.Profile.Name}}-status.json" +#status-file = "{{ .TempDir }}/resticprofile-{{ .Profile.Name }}-status.json" +## # Export backup metrics to Prometheus (requires extended-status = true) -#prometheus-save-to-file = "/var/lib/prometheus/node-exporter/{{.Profile.Name}}.prom" +#prometheus-save-to-file = "/var/lib/prometheus/node-exporter/{{ .Profile.Name }}.prom" #prometheus-push = "http://host:9091/" + + +# ----------------------------------------------------------------------------- diff --git a/contrib/posix/conf.d/prune.conf b/contrib/posix/conf.d/prune.conf index 977fe7ab..adcd1071 100644 --- a/contrib/posix/conf.d/prune.conf +++ b/contrib/posix/conf.d/prune.conf @@ -1,44 +1,56 @@ - -## -# Group for profiles that prune repositories -# Usage -# - `resticprofile -n prune-all` -# - `resticprofile -n prune-all schedule` -# - `resticprofile -n prune-all unschedule` -[groups] -prune-all = [ "prune" ] - - +# ----------------------------------------------------------------------------- ## -# Profile "prune" may be used to schedule pruning of the default repository -# which reclaims space that is no longer occupied by removed snapshots from -# profiles that use this repository. +# Repository prune defaults # # Usage -# - `resticprofile -n prune` -# - `resticprofile -n prune schedule` -# - `resticprofile -n prune unschedule` # -[prune] -# Operate on the pepository defined in the "base" profile -inherit = "base" -initialize = false -default-command = "prune" +# Run prune on the default profile: +# - "resticprofile prune" +# Run prune on all maintenance profiles: +# - "resticprofile maintenance-all.prune" +# +# Schedule the default maintenance profile: +# - "resticprofile maintenance.schedule" +# - "resticprofile maintenance.unschedule" +# Schedule all maintenance profiles: +# - "resticprofile maintenance-all.schedule" +# - "resticprofile maintenance-all.unschedule" +# -# Configuring the "prune" command in profile "prune" -[prune.prune] -schedule = "daily" -schedule-lock-wait = "4h" -# Auto remove old cache directories in the local cache + +## +# Defaults for repository prune +[profiles.default.prune] +## +# Auto remove old cache entries from the local cache that are no longer +# needed as data was pruned from the repository. cleanup-cache = true -# Repacking (repository compaction) + +## +# Repacking (repository compaction) configuration. # Limited by: -# - `max-unused` (higher precentage, less repacking) -# - `max-repack-size` (lower size value, less repacking) +# - "max-unused" (higher precentage, less repacking) +# - "max-repack-size" (lower size value, less repacking) # -# Repacking requires up to `max-repack-size` temporary space in the repository, +# Repacking requires up to "max-repack-size" temporary space in the repository, # ensure it has the configured size available at least before running prune. -max-repack-size = "5g" -# Tolerate given limit of unused data (default 5%) +# Using a smaller size means more iterations are needed until all space is +# reclaimed. +max-repack-size = "3g" +# Tolerate given limit of unused data that is not reclaimed (default 5%) # A higher percentage performs less repacking which will speedup prune. -max-unused = "5%" +max-unused = "5%" + +## +# Wait on acquiring locks when running "prune" on a schedule +schedule-lock-wait = "1h30m" +# Only root may schedule prune +schedule-permission = "system" + + +## +# Configuring "prune" schedule in maintenance profile +[profiles.maintenance.prune] +schedule = "daily" + +# ----------------------------------------------------------------------------- diff --git a/contrib/posix/conf.d/z_overrides.conf b/contrib/posix/conf.d/z_overrides.conf new file mode 100644 index 00000000..5e06a174 --- /dev/null +++ b/contrib/posix/conf.d/z_overrides.conf @@ -0,0 +1,64 @@ +# ----------------------------------------------------------------------------- +## +# Is included as last conf file and may override any settings made earlier. +# +# Prefer this file to customize resticprofile's default configuration rather +# than modifying other .conf files. +# + +## +# Example: Override default retention +# +# Note: Retention settings are inherited like all other parameters one-by-one. +# Anything that is set here must be explicitly configured in profiles +# if the default should not apply. +# +# [profiles.default.retention] +# keep-tag = [ "forever" ] +# keep-last = 10 +# keep-hourly = 0 +# keep-daily = 14 +# keep-weekly = 2 +# keep-monthly = 0 +# keep-yearly = 0 +# keep-within = "30d" + + +## +# Example: Global repository access +# +# Enable to access the default repository without host or tag filter +# +# [profiles.global.copy] +# host = false +# tag = false +# [profiles.global.dump] +# host = false +# tag = false +# [profiles.global.find] +# host = false +# tag = false +# [profiles.global.forget] +# host = false +# tag = false +# [profiles.global.ls] +# host = false +# tag = false +# [profiles.global.mount] +# host = false +# tag = false +# [profiles.global.restore] +# host = false +# tag = false +# [profiles.global.snapshots] +# host = false +# tag = false +# [profiles.global.stats] +# host = false +# tag = false +# [profiles.global.tag] +# host = false +# tag = false + + +# ----------------------------------------------------------------------------- diff --git a/contrib/posix/post-install.sh b/contrib/posix/post-install.sh index bb262623..417e03d9 100755 --- a/contrib/posix/post-install.sh +++ b/contrib/posix/post-install.sh @@ -1,39 +1,159 @@ #!/usr/bin/env sh -set -e +# Temp dir (using fixed path to ensure "rm -rf" will not have side effects) +TEMP_PATH="/tmp/.resticprofile-setup" +if [ -d "$TEMP_PATH" ] ; then + rm -rf "${TEMP_PATH}" +fi +mkdir -p "$TEMP_PATH" +trap "rm -rf \"${TEMP_PATH}\"" EXIT INT TERM + +# Paths +CACHE_PATH="${TEMP_PATH}/cache" CONFIG_PATH="/etc/resticprofile" -SECRET_FILE="${CONFIG_PATH}/conf.d/default-repository.secret" +CONFIG_CACHE_FILE="${CONFIG_PATH}/.dist.cache" +REPOSITORY_SECRET="repositories.d/default-repository.secret" +SECRET_FILE="${CONFIG_PATH}/${REPOSITORY_SECRET}" + +# Config files that are merged with .dist files when already existing +MERGEABLES="conf.d/backup.conf conf.d/check.conf conf.d/hooks.conf conf.d/metrics.conf conf.d/prune.conf" +MERGEABLES="${MERGEABLES} profiles.conf repositories.d/default.conf" + +# Search path of dirs to install shell completions (only first match will be used) +COMPLETION_DIRS="/usr/share/bash-completion/completions" +COMPLETION_DIRS="${COMPLETION_DIRS} /usr/share/bash-completion/bash_completion" +COMPLETION_DIRS="${COMPLETION_DIRS} /usr/local/etc/bash_completion.d" +COMPLETION_DIRS="${COMPLETION_DIRS} /etc/bash_completion.d" + +# Fix permissions (only root may edit and read since password & tokens can be in any of the files) +set_permission() { + _path="${CONFIG_PATH}/$1" + + if [ -e "${_path}" ] ; then + echo "Setting perms on ${_path}" + chown root:root "${_path}" + fi + + if [ -d "${_path}" ] || echo "${_path}" | grep -q -E '.rc$' ; then + chmod 0755 "${_path}" + elif [ -f "${_path}" ] ; then + echo "$1" | grep -q .secret \ + && chmod 0400 "${_path}" \ + || chmod 0640 "${_path}" + fi +} -# Fix permissions (only root may edit and read since password -# & tokens can be in any of the files) -if [ -d "${CONFIG_PATH}" ] ; then - chown -R root:root "${CONFIG_PATH}" - chmod -R 0640 "${CONFIG_PATH}" +if cd "${CONFIG_PATH}" ; then + for file in *.dist \ + conf.d conf.d/*.dist \ + profiles.d profiles.d/*.dist \ + repositories.d repositories.d/*.dist ${REPOSITORY_SECRET} \ + templates templates/*.dist \ + ${MERGEABLES} ; do + set_permission "${file}" + done else echo "config path (${CONFIG_PATH}) not found" exit 1 fi # Check installation -if [ ! -e "$(which resticprofile)" ] || ! resticprofile version ; then +if [ ! -e "$(which resticprofile)" ] || ! resticprofile version >/dev/null ; then echo "resticprofile not found or not executable" exit 1 fi -# Generate default-repo secret (if missing) +# Generate default-repo secret if missing if [ ! -f "${SECRET_FILE}" ] ; then echo "Generating ${SECRET_FILE}" - resticprofile random-key > "${SECRET_FILE}" + resticprofile random-key > "${SECRET_FILE}" \ + && set_permission "${REPOSITORY_SECRET}" +fi + +# Change scheduler to crond when systemd is missing (Alpine) +if [ ! -d /etc/systemd/ ] ; then + sed -i 's/#scheduler = "systemd"/scheduler = "crond"/g' "${CONFIG_PATH}/profiles.conf.dist" fi -# Unwrap dist files (if target is missing) -cd "${CONFIG_PATH}" -for file in conf.d/*.dist profiles.d/*.dist templates/*.dist ; do +# Generate bash completions +for completion_path in ${COMPLETION_DIRS} ; do + completion_file="${completion_path}/resticprofile" + + if [ -d "${completion_path}" ] ; then + echo "Generating ${completion_file}" + if [ -f "${completion_file}" ] ; then + chmod u+w "${completion_file}" + fi + resticprofile completion-script --bash > "${completion_file}" \ + && chown root:root "${completion_file}" \ + && chmod 0555 "${completion_file}" + + break # install only in the first path + fi +done + +# Merge configuration updates with existing files +if [ -e "$(which diff3)" ] ; then + echo "Merging updates to config files" + + # Extract previous .dist files from .dist.cache + if [ -s "${CONFIG_CACHE_FILE}" ] ; then + cd "${CACHE_PATH}" \ + && tar -xzf "${CONFIG_CACHE_FILE}" + fi + + new_dist_cache_list="${TEMP_PATH}/dist_cache.list" + + cd "${CONFIG_PATH}" || exit 1 + + # Merge existing config with updates from .dist files + for file in $MERGEABLES ; do + target_file="${file}" + new_file="${file.dist}" + cached_file="${CACHE_PATH}/${new_file}" + output="${TEMP_PATH}/merged.conf" + + if [ -e "${new_file}" ] ; then + echo "${new_file}" >> "${new_dist_cache_list}" + fi + + if [ -e "${target_file}" ] && [ -e "${new_file}" ] && [ -e "${cached_file}" ] ; then + + diff3 --easy-only --merge "${new_file}" "${cached_file}" "${target_file}" > "${output}" + + if [ "$?" = "0" ] || [ "$?" = "1" ] ; then + if [ "$?" = "1" ] ; then + backup="${target_file}.prev" + cp -f "${target_file}" "${backup}" \ + && set_permission "${backup}" + echo "Conflicts found in \"${target_file}\", please verify. Created ${backup}" + fi + if [ -s "${output}" ] ; then + mv -f "${output}" "${target_file}" \ + && set_permission "${target_file}" + fi + else + echo "Failed merging \"${new_file}\" \"${cached_file}\" \"${target_file}\"" + fi + fi + done + + # Create new .dist.cache from current .dist files + if [ -s "${new_dist_cache_list}" ] ; then + tar -c --files-from "${new_dist_cache_list}" -zf "${CONFIG_CACHE_FILE}" + fi +fi + +# Unwrap remaining dist files where target file does not exist already +cd "${CONFIG_PATH}" || exit 1 + +for file in *.dist conf.d/*.dist profiles.d/*.dist repositories.d/*.dist templates/*.dist ; do target_file="$(dirname "${file}")/$(basename -s ".dist" "${file}")" + if [ -e "${target_file}" ] ; then - echo "Skipping ${target_file}. File already exists" rm "${file}" else - mv -f "${file}" "${target_file}" + mv -f "${file}" "${target_file}" \ + && set_permission "${target_file}" fi done diff --git a/contrib/posix/profiles.conf b/contrib/posix/profiles.conf index 802ce9e0..1d03c2b8 100644 --- a/contrib/posix/profiles.conf +++ b/contrib/posix/profiles.conf @@ -4,23 +4,29 @@ # See https://github.com/creativeprojects/resticprofile # # Note: This configuration file should not be changed directly. -# Add overrides to "conf.d" and profiles to "profiles.d". +# Configure resticprofile in "(conf|repositories).d" and add +# profiles to "profiles.d". # ----------------------------------------------------------------------------- +## Configuration file format version +version = 2 + ## -# Loading config overrides from "conf.d" and profiles from "profiles.d": +# Loading config from "(conf|repositories).d" and profiles from "profiles.d": includes = [ + 'templates/*.conf', 'conf.d/*.conf', + 'repositories.d/*.conf', + 'profiles.d/*.conf', 'profiles.d/*.toml', 'profiles.d/*.yaml', ] - ## # The global section [global] -# initialize a repository if none exists at the specified location -# (can be overriden in individual profiles) +# Initialize a repository if none exists at the specified location? +# Is configured in profiles, global setting should remain 'false'. initialize = false # restic IO priority @@ -39,7 +45,7 @@ systemd-unit-template = "templates/systemd.unit.in" systemd-timer-template = "templates/systemd.timer.in" # what to run when no command is specified -default-command = "snapshots" +default-command = "profiles" # Optional: Specify path to restic #restic-binary = "/usr/local/bin/restic" @@ -57,7 +63,8 @@ default-command = "snapshots" # # The default profile should not be used directly for running backups # nor should it contain schedules. -[default] +[profiles.default] +description = "Profile defaults for this host" ## Locks # Prevent concurrent invocation of a profile lock = "{{.TempDir}}/resticprofile-{{.Profile.Name}}.lock" @@ -65,123 +72,46 @@ lock = "{{.TempDir}}/resticprofile-{{.Profile.Name}}.lock" force-inactive-lock = true -## -# Backup defaults -[default.backup] - -# Hostname and tags to identify backup snapshots in the repository -#### {{block "conf:default-backup-tags" .}} -# Multiple tags can be used, defaulting to profile name. -# Important: Set the same tags for "backup" and "retention" -tag = [ "{{.Profile.Name}}" ] -#### {{end}} -#### {{block "conf:default-backup-host" .}} -# Specify a hostname or leave it at 'true' for the current hostname -host = true -#### {{end}} - -# Exclude known cache files & folders from backups -exclude-caches = true - -# Exclude nested filesystems -one-file-system = true - -# Toggle whether a failure in reading a backup source is considered an error -#no-error-on-warning = false - -# Wait on acquiring locks when running the profile on a schedule -schedule-lock-wait = "30m" - -# Specify the user that runs profile tasks on a schedule -# "system" - root runs the profile tasks -# "user" - user that created the schedule runs the profile tasks -schedule-permission = "system" - -# Toggle verbose output for troubleshooting -#verbose = false - - -## -# Snapshot retention defaults -[default.retention] -# Remove obsolete snapshots prior to starting a backup -before-backup = false -# Remove obsolete snapshots after a successful backup -after-backup = true - -# Copying "host" and "tags" blocks to identify snapshots to retain or remove -# Note: "host" and "tag" must be in sync between "backup" and "retention" -{{template "conf:default-backup-host" .}} -# In retention, tags can be copied from backup with `true`: -tags = true - -# Copying backup source paths to identify snapshots to retain or remove -# Set to "false" or a list of paths to disable or customize the path filter -path = true - -# Specify the snapshots to keep when checking for obsolete snapshots -# Snapshots that do not match any condition are removed -keep-tag = [ "forever" ] -keep-last = 3 -#keep-hourly = 1 -#keep-daily = 1 -#keep-weekly = 1 -#keep-monthly = 1 -#keep-yearly = 1 -#keep-within = "30d" - -# Use compact format for listing snapshots -#compact = false - -# Enable to prune the repository immediatelly as snapshots are removed -# Prune can be expensive. Consider scheduling prune (see "conf.d/prune.conf") -#prune = true - - -## -# Defaults for showing snapshots of this host -# Usage: -# - `resticprofile snapshots` to view snapshots of this host -[default.snapshots] -# Copying "host" block to identify snapshots to list -{{template "conf:default-backup-host" .}} - - -## -# Defaults for mounting snapshot of this host -# Usage: -# - `resticprofile mount /mnt/restore` to mount snapshots of this host -[default.mount] -# Copying "host" block to identify snapshots to mount -{{template "conf:default-backup-host" .}} - - - ## # The "base" profile is the base for all other profiles to inherit from # # Note: Profiles that do not inherit from "base" will run on built-in # defaults instead and have to take care of a full profile setup. -[base] +[profiles.base] +description = "Base config for derived profiles" # Inherit all settings from the "default" profile inherit = "default" +initialize = true ## -# Configures the "snapshots" command for profiles inheriting from "base" -# Usage: -# - `resticprofile -n profileName snapshots` to view snapshots of one profile -[base.snapshots] -# Copying "host" and "tags" blocks to identify snapshots to list -{{template "conf:default-backup-host" .}} -{{template "conf:default-backup-tags" .}} +# The "maintenance" profile is used to perform ondemand or scheduled +# repository maintenance tasks like prune and check. +# +# See also "conf.d/check.conf" & "conf.d/prune.conf" +[profiles.maintenance] +description = "Maintenance for default repository" +inherit = "base" +# We never initialize a new repository for maintenance +initialize = false + +## +# Group for profiles that check & verify repositories +# Usage +# - "resticprofile maintenance-all.check" +# - "resticprofile maintenance-all.prune" +# - "resticprofile maintenance-all.cache" +# - "resticprofile maintenance-all.schedule" +# - "resticprofile maintenance-all.unschedule" +[groups.maintenance-all] +description = "Group of check and cleanup profiles" +profiles = [ "maintenance" ] ## -# Configures the "mount" command for profiles inheriting from "base" -# Usage: -# - `resticprofile -n profileName mount /mnt/restore` to mount snapshots -[base.mount] -# Copying "host" and "tags" block to identify snapshots to mount -{{template "conf:default-backup-host" .}} -{{template "conf:default-backup-tags" .}} +# Group for profiles that perform actual backups +# Usage +# - "resticprofile backup-all.backup" +[groups.backup-all] +description = "Group of backup profiles" +profiles = [ ] diff --git a/contrib/posix/profiles.d/fs-snapshot.yaml.sample b/contrib/posix/profiles.d/fs-snapshot.yaml.sample index d37c9d57..1dd0040b 100644 --- a/contrib/posix/profiles.d/fs-snapshot.yaml.sample +++ b/contrib/posix/profiles.d/fs-snapshot.yaml.sample @@ -1,54 +1,65 @@ +# ----------------------------------------------------------------------------- ## -# Example profile for applications whose files must be backed-up from a readonly snapshot. +# Example profile for applications whose files must be backed-up from a +# readonly snapshot. # -applications: - inherit: base +profiles: + applications: + description: Applications backup + inherit: base - backup: - source: - - /opt/apps/_backup - - /mnt/data_backup - - /opt/vms/my-vm1.xml - - /opt/vms/my-vm1.qcow2 + backup: + source: + - /opt/apps/_backup + - /mnt/data_backup + - /opt/vms/my-vm1.xml + - /opt/vms/my-vm1.qcow2 - # Create snapshots of supported sources prior to running a backup - run-before: - # Snapshot on Btrfs (mounted on /opt/apps/_backup) - - btrfs subvolume snapshot -r /opt/apps/ /opt/apps/_backup + # Create snapshots of supported sources prior to running a backup + run-before: + # Snapshot on Btrfs (mounted on /opt/apps/_backup) + - btrfs subvolume snapshot -r /opt/apps/ /opt/apps/_backup - # Snapshot on LVM (mounted on /opt/apps/_backup) - - lvcreate -l100%FREE -s -n data_backup /dev/vg00/data && mount /dev/vg00/data_backup /mnt/data_backup + # Snapshot on LVM (mounted on /opt/apps/_backup) + - lvcreate -l100%FREE -s -n data_backup /dev/vg00/data && mount /dev/vg00/data_backup /mnt/data_backup - # Snapshot & config dump for libvirt VMs (VM disk images are readonly during backup) - - virsh dumpxml "my-vm1" > /opt/vms/my-vm1.xml - - {{template "libvirt-create-snapshot" "my-vm1"}} + # Snapshot & config dump for libvirt VMs (VM disk images are readonly during backup) + - virsh dumpxml "my-vm1" > /opt/vms/my-vm1.xml + - {{ template "libvirt-create-snapshot" "my-vm1" }} - # Release snapshots after backup - run-finally: - # Cleanup on Btrfs - - btrfs subvolume delete /opt/apps/_backup + # Release snapshots after backup + run-finally: + # Cleanup on Btrfs + - btrfs subvolume delete /opt/apps/_backup - # Cleanup on LVM - - umount /mnt/data_backup && lvremove -f /dev/vg00/data_backup + # Cleanup on LVM + - umount /mnt/data_backup && lvremove -f /dev/vg00/data_backup - # Cleanup for libvirt VMs (VM disk image receives changes from livedata file) - - {{template "libvirt-delete-snapshot" "my-vm1"}} + # Cleanup for libvirt VMs (VM disk image receives changes from livedata file) + - {{ template "libvirt-delete-snapshot" "my-vm1" }} +groups: + backup-all: + profiles: [ "applications" ] + ##### -# Config Templates -# Use -# - `resticprofile -n applications show` to see rendered result +# Config templates +# Notes: +# - "resticprofile applications.show" shows rendered template output +# - Could also be saved to "templates/my-libvirt-utils.conf" and shared # -{{define "libvirt-create-snapshot" -}} +{{ define "libvirt-create-snapshot" -}} virsh snapshot-create-as --domain "{{.}}" --name "{{.}}-backup" {{- " " -}} --diskspec "vda,file=/var/db/{{.}}-livedata.qcow2" {{- " " -}} --disk-only --atomic --no-metadata --quiesce -{{- end}} +{{- end }} # -{{define "libvirt-delete-snapshot" -}} +{{ define "libvirt-delete-snapshot" -}} virsh blockcommit --domain "{{.}}" vda --wait --active {{- " " -}} && virsh blockjob --domain "{{.}}" "/var/db/{{.}}-livedata.qcow2" --pivot {{- " " -}} && rm -f /var/db/{{.}}-livedata.qcow2 -{{- end}} +{{- end }} ##### + +# ----------------------------------------------------------------------------- diff --git a/contrib/posix/profiles.d/minimal.conf.sample b/contrib/posix/profiles.d/minimal.conf.sample new file mode 100644 index 00000000..d1814242 --- /dev/null +++ b/contrib/posix/profiles.d/minimal.conf.sample @@ -0,0 +1,27 @@ +## +# Minimal backup configuration example +# +# Usage: +# - "resticprofile minimal.show" +# - "resticprofile --dry-run minimal.backup" +# - "resticprofile minimal.backup" +# - "resticprofile minimal.snapshots" +# - "resticprofile minimal.mount /restore" +# - "resticprofile minimal.status" +# - "resticprofile minimal.schedule" +# - "resticprofile minimal.unschedule" +# +[profiles.minimal] +description = "Minimal backup example" +inherit = "base" + +[profiles.minimal.backup] +schedule = "daily" +source = [ + "/path/to/backup", + "/other/path/to/backup", +] + + +[groups.backup-all] +profiles = [ "minimal" ] diff --git a/contrib/posix/profiles.d/minimal.yaml.sample b/contrib/posix/profiles.d/minimal.yaml.sample new file mode 100644 index 00000000..02b54679 --- /dev/null +++ b/contrib/posix/profiles.d/minimal.yaml.sample @@ -0,0 +1,28 @@ +## +# Minimal backup configuration example +# +# Usage: +# - "resticprofile minimal.show" +# - "resticprofile --dry-run minimal.backup" +# - "resticprofile minimal.backup" +# - "resticprofile minimal.snapshots" +# - "resticprofile minimal.mount /restore" +# - "resticprofile minimal.status" +# - "resticprofile minimal.schedule" +# - "resticprofile minimal.unschedule" +# +profiles: + minimal: + description: Minimal backup example + inherit: base + + backup: + schedule: daily + source: + - /path/to/backup + - /other/path/to/backup + + +groups: + backup-all: + profiles: [ "minimal" ] diff --git a/contrib/posix/profiles.d/system.conf b/contrib/posix/profiles.d/system.conf new file mode 100644 index 00000000..197663ed --- /dev/null +++ b/contrib/posix/profiles.d/system.conf @@ -0,0 +1,55 @@ +# ----------------------------------------------------------------------------- +## +# The "root" profile to backup the system +# +# Backup $HOME of root and 'etc' folders once a day +# +# Usage: +# - "resticprofile root.show" +# - "resticprofile --dry-run root.backup" +# - "resticprofile root.backup" +# - "resticprofile root.snapshots" +# - "resticprofile root.mount /restore" +# - "resticprofile root.status" +# - "resticprofile root.schedule" +# - "resticprofile root.unschedule" +# +[profiles.root] +description = "System backup" +inherit = "base" + +## +# Backup sources and schedule +[profiles.root.backup] +no-error-on-warning = false +schedule = "daily" +source = [ + "/etc", + "/usr/local/etc", + "/opt/local/etc", + "~root/", +] +exclude = [ + "*.swp", +] +#exclude-larger-than = "2g" +#include = [ +# "**", +#] + +## +# Keep last 14 days and the latest from each of last 8 weeks and 6 months +# Total snapshots to keep: 24 +# (14 days, weeks not covered by days and months not covered by weeks) +[profiles.root.retention] +keep-last = true +keep-daily = 14 +keep-weekly = 8 +keep-monthly = 6 + +## +# Add to "backup-all" +[groups.backup-all] +profiles = [ "root" ] + +# ----------------------------------------------------------------------------- \ No newline at end of file diff --git a/contrib/posix/profiles.d/system.toml b/contrib/posix/profiles.d/system.toml deleted file mode 100644 index 70eb089c..00000000 --- a/contrib/posix/profiles.d/system.toml +++ /dev/null @@ -1,38 +0,0 @@ -## -# The "root" profile -# -# Backup $HOME of root and 'etc' folders once a day -# -# Usage: -# - `resticprofile -n root show` -# - `resticprofile -n root --dry-run backup` -# - `resticprofile -n root backup` -# - `resticprofile -n root snapshots` -# - `resticprofile -n root mount /restore` -# - `resticprofile -n root status` -# - `resticprofile -n root schedule` -# - `resticprofile -n root unschedule` -# -[root] -inherit = "base" - -## -# Backup sources and schedule -[root.backup] -source = [ - "/etc", - "/usr/local/etc", - "/opt/local/etc", - "~root/", -] -schedule = "daily" - -## -# Keep last 14 days and the latest from each of last 8 weeks and 6 months -# Total snapshots to keep: 24 -# (14 days, weeks not covered by days and months not covered by weeks) -[root.retention] -keep-last = false -keep-daily = 14 -keep-weekly = 8 -keep-monthly = 6 diff --git a/contrib/posix/conf.d/repository.conf b/contrib/posix/repositories.d/default.conf similarity index 57% rename from contrib/posix/conf.d/repository.conf rename to contrib/posix/repositories.d/default.conf index a43dfa4f..61edf2bd 100644 --- a/contrib/posix/conf.d/repository.conf +++ b/contrib/posix/repositories.d/default.conf @@ -1,4 +1,4 @@ - +# ----------------------------------------------------------------------------- ## # Repository configuration # See https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html @@ -6,62 +6,49 @@ ## # Default repository (used in all derived profiles unless redefined) -[default] -# Local: Repository mounted to local folder +[profiles.default] +# Repository password file +password-file = "repositories.d/default-repository.secret" + +## +# Local: Repository created in local path repository = "local:/backup" #run-before = [ 'mountpoint -q /backup' ] +## # SFTP: (requires password-less public-key auth for the user running restic) #repository = "sftp:user@host:/restic-repo" #repository = "sftp://user@[::1]:2222//restic-repo" +## # REST server: (https://github.com/restic/rest-server) #repository = "rest:https://user:pass@host:8000/my_backup_repo/" -#cacert = "conf.d/default-repository-self-signed-pub.pem" -#tls-client-cert = "conf.d/default-repository-client.pem" +#cacert = "repositories.d/default-repository-self-signed-pub.pem" +#tls-client-cert = "repositories.d/default-repository-client.pem" +## # S3 storage (see [default.env]) #repository = "s3:s3.amazonaws.com/bucket_name" #repository = "s3:http://host:9000/bucket_name" #repository = "s3:https://host/bucket_name" -#cacert = "conf.d/default-repository-self-signed-pub.pem" +#cacert = "repositories.d/default-repository-self-signed-pub.pem" +## # Azure storage (see [default.env]) #repository = "azure:container_name:/" -# Repository password file -password-file = "conf.d/default-repository.secret" ## # Environment variables to pass to "restic" -[default.env] +[profiles.default.env] +## # S3 Storage (AWS, Minio, etc.) #AWS_ACCESS_KEY_ID = "id" #AWS_SECRET_ACCESS_KEY = "key" +## # Azure Blob Storage #AZURE_ACCOUNT_NAME = "storage_account" #AZURE_ACCOUNT_KEY = "key" - -## -# Initialize the repository (if empty) for profiles deriving from "base" -[base] -# Initialize a repository if none exists at the specified location -initialize = true - - -## -# Example: Secondary repository -# Other repository for profiles inheriting from "other-repository-base": -# -# [other-repository-base] -# inherit = "base" -# repository = "local:/backup-other" -# -# Usage: -# [my-profile-other] -# inherit = "other-repository-base" -# [my-profile-other.backup] -# source = "/path" -# +# ----------------------------------------------------------------------------- diff --git a/contrib/posix/repositories.d/other.conf.sample b/contrib/posix/repositories.d/other.conf.sample new file mode 100644 index 00000000..2221d693 --- /dev/null +++ b/contrib/posix/repositories.d/other.conf.sample @@ -0,0 +1,69 @@ +## +# Example: Secondary repository +# +# Usage: +# +# [profiles.my-profile-other] +# inherit = "base-other" +# [profiles.my-profile-other.backup] +# source = "/path" +# + + +# ----------------------------------------------------------------------------- +## +# Secondary repository for profiles inheriting from "other-base" +[profiles.base-other] +# Inherit all settings from base +inherit = "base" + +# +# Repository password for the secondary repository +# +# Generate with: +# - "resticprofile random-key > repositories.d/other-repository.secret" +password-file = "repositories.d/other-repository.secret" + +# +# See "default.conf" for more examples +repository = "local:/backup-other" + +# ----------------------------------------------------------------------------- + + +# ----------------------------------------------------------------------------- +## +# Setup repository maintenance for "base-other" +[profiles.maintenance-other] +description = "Maintenance for other repository" +inherit = "base-other" +initialize = false + + +## +# Configuring "check" schedule in maintenance profile +[profiles.maintenance-other.check] + +# Schedule at 5th, 10th, 15th, 20th, 25th and 30th day in month at 04:15 +schedule = "*-*-5,10,15,20,25,30 04:15:00" + +# Read repository data for verification every 15th day in month +{{ if .Now.Day | eq 15 -}} +read-data = true +{{ end -}} +#read-data-subset = "100%" + + +## +# Configuring "prune" schedule in maintenance profile +[profiles.maintenance-other.prune] +schedule = "daily" +#schedule = "weekly" + + +## +# Add "maintenance-other" to "maintenance-all" +[groups.maintenance-all] +profiles = [ "maintenance-other" ] + +# ----------------------------------------------------------------------------- diff --git a/contrib/posix/resticprofile-send-error.rc b/contrib/posix/resticprofile-send-error.rc new file mode 100644 index 00000000..7acff1e6 --- /dev/null +++ b/contrib/posix/resticprofile-send-error.rc @@ -0,0 +1,39 @@ +# ----------------------------------------------------------------------------- +# +# Configuration for "resticprofile-send-error" +# +# Usage, see: +# resticprofile-send-error -h +# +# Examples: +# +# Test mail sending: +# resticprofile-send-error -f user@domain.org +# +# Send if PROFILE_NAME is set +# resticprofile-send-error user@domain.org +# +# Send if PROFILE_NAME & MAIL_TO are set +# resticprofile-send-error +# +# Send if PROFILE_COMMAND is "check" "backup" or "prune": +# resticprofile-send-error -o check,backup,prune user@domain.org +# +# Send only if RESTICPROFILE_ON_SCHEDULE is set to 1 +# resticprofile-send-error -s user@domain.org +# +# ----------------------------------------------------------------------------- + +## +# Sender address +#MAIL_FROM="\"resticprofile $(hostname -f)\" <$USER@$(hostname -f)>" + +## +# Subject line +#MAIL_SUBJECT="restic failed: \"${PROFILE_COMMAND}\" in \"${PROFILE_NAME}\"" + +## +# Recipients (are combined with recipients specified in CLI) +# Use space as delimiter when declaring more than one recipient +#MAIL_TO="admin1@mynet.org admin2@mynet.org ..." +#MAIL_TO="" diff --git a/contrib/posix/templates/default-host.conf b/contrib/posix/templates/default-host.conf new file mode 100644 index 00000000..decb73da --- /dev/null +++ b/contrib/posix/templates/default-host.conf @@ -0,0 +1,7 @@ +{{ define "conf:default-host" }} + +# Specify a hostname to set in snapshots created by this system. +# Use 'true' for the current hostname of the system +host = true + +{{ end }} diff --git a/contrib/posix/templates/default-tags.conf b/contrib/posix/templates/default-tags.conf new file mode 100644 index 00000000..ac9ba7ca --- /dev/null +++ b/contrib/posix/templates/default-tags.conf @@ -0,0 +1,24 @@ +{{ define "conf:default-tags" }} + +# +# Tags are used to identify snapshots belonging to a certain backup. +# +# Multiple tags can be defined, but profile name should always be included, +# the expression "{{ .Profile.Name }}" resolves to the currently active +# profile name. +# +# Notes: +# +# - Set the same tags for "backup" and "retention" unless you know what you +# are doing. Retention uses the tags defined in the backup section when +# "tag = true" is set in the retention configuration and this default +# setup should not be changed. +# +# - Most of the command sections should use this template to define tags so +# that commands like restore, mount, etc. relate to the selected profile. +# +# - See also "conf.d/backup.conf" where tags are applied to profile "base". +# +tag = [ "{{ .Profile.Name }}" ] + +{{ end }}