From 595131b8e3ffe99e9187c7adb5e73e922bd931e1 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Tue, 25 Feb 2020 19:42:07 +0100 Subject: Initial commit --- debian/changelog | 5 + debian/control | 22 +++ debian/copyright | 27 ++++ debian/resteasy-desktop.install | 1 + debian/resteasy-desktop.postinst | 39 +++++ debian/resteasy-desktop.user.service | 9 ++ debian/resteasy.install | 2 + debian/resteasy.postinst | 42 +++++ debian/resteasy.service | 8 + debian/resteasy.udev | 6 + debian/rules | 11 ++ debian/source/format | 1 + readme.md | 16 ++ resteasy-desktop/libexec/resteasy-desktop-monitor | 31 ++++ resteasy.8.md | 186 ++++++++++++++++++++++ resteasy/libexec/resteasy-find-uuid | 22 +++ resteasy/libexec/resteasy-helper.sh | 45 ++++++ resteasy/libexec/resteasy-inhibit | 13 ++ resteasy/libexec/resteasy-init | 16 ++ resteasy/libexec/resteasy-mount | 27 ++++ resteasy/libexec/resteasy-prepare-drive | 35 ++++ resteasy/libexec/resteasy-run-backup | 74 +++++++++ resteasy/libexec/resteasy-umount | 12 ++ resteasy/libexec/resteasy-uninhibit | 13 ++ resteasy/sbin/resteasy | 32 ++++ 25 files changed, 695 insertions(+) create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/resteasy-desktop.install create mode 100644 debian/resteasy-desktop.postinst create mode 100644 debian/resteasy-desktop.user.service create mode 100644 debian/resteasy.install create mode 100644 debian/resteasy.postinst create mode 100644 debian/resteasy.service create mode 100644 debian/resteasy.udev create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 readme.md create mode 100755 resteasy-desktop/libexec/resteasy-desktop-monitor create mode 100644 resteasy.8.md create mode 100755 resteasy/libexec/resteasy-find-uuid create mode 100644 resteasy/libexec/resteasy-helper.sh create mode 100755 resteasy/libexec/resteasy-inhibit create mode 100755 resteasy/libexec/resteasy-init create mode 100755 resteasy/libexec/resteasy-mount create mode 100755 resteasy/libexec/resteasy-prepare-drive create mode 100755 resteasy/libexec/resteasy-run-backup create mode 100755 resteasy/libexec/resteasy-umount create mode 100755 resteasy/libexec/resteasy-uninhibit create mode 100755 resteasy/sbin/resteasy diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..80d7307 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +resteasy (0) unstable; urgency=medium + + * Initial Release. + + -- Jakob Odersky Sun, 16 Feb 2020 01:20:26 +0100 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..f5477b1 --- /dev/null +++ b/debian/control @@ -0,0 +1,22 @@ +Source: resteasy +Section: admin +Priority: optional +Maintainer: Jakob Odersky +Build-Depends: debhelper-compat (= 12), pandoc +Standards-Version: 4.4.1 + +Package: resteasy +Architecture: all +Depends: ${shlibs:Depends}, ${misc:Depends}, borgbackup +Description: simple plug and play backup system + Resteasy is a collection of wrapper scripts and services around borg, that + provide an easy-to-use backup solution. + +Package: resteasy-desktop +Architecture: all +Depends: ${shlibs:Depends}, ${misc:Depends}, resteasy, libnotify-bin, dbus, python3 +Description: simple plug and play backup system, desktop notification component + Resteasy is a collection of wrapper scripts and services around borg, that + provide an easy-to-use backup solution. + . + This package provides utilities for notifying users of running backups. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..42027a3 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,27 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: resteasy + +Files: * +Copyright: 2020 Jakob Odersky +License: GPL-3.0+ + +Files: debian/* +Copyright: 2020Jakob Odersky +License: GPL-3.0+ + +License: GPL-3.0+ + 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 3 of the License, or + (at your option) any later version. + . + This package 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, see . + . + On Debian systems, the complete text of the GNU General + Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". diff --git a/debian/resteasy-desktop.install b/debian/resteasy-desktop.install new file mode 100644 index 0000000..92b6301 --- /dev/null +++ b/debian/resteasy-desktop.install @@ -0,0 +1 @@ +resteasy-desktop/libexec/* usr/libexec/resteasy/ diff --git a/debian/resteasy-desktop.postinst b/debian/resteasy-desktop.postinst new file mode 100644 index 0000000..bbbe8cf --- /dev/null +++ b/debian/resteasy-desktop.postinst @@ -0,0 +1,39 @@ +#!/bin/sh +# postinst script for resteasy +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/resteasy-desktop.user.service b/debian/resteasy-desktop.user.service new file mode 100644 index 0000000..c05fc6f --- /dev/null +++ b/debian/resteasy-desktop.user.service @@ -0,0 +1,9 @@ +[Unit] +Description=monitor backup system + +[Service] +Type=simple +ExecStart=/usr/sbin/resteasy desktop-monitor + +[Install] +WantedBy=default.target diff --git a/debian/resteasy.install b/debian/resteasy.install new file mode 100644 index 0000000..2031a55 --- /dev/null +++ b/debian/resteasy.install @@ -0,0 +1,2 @@ +resteasy/libexec/* usr/libexec/resteasy/ +resteasy/sbin usr/ diff --git a/debian/resteasy.postinst b/debian/resteasy.postinst new file mode 100644 index 0000000..3bd788c --- /dev/null +++ b/debian/resteasy.postinst @@ -0,0 +1,42 @@ +#!/bin/sh +# postinst script for resteasy +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + touch /etc/resteasy + chown root:root /etc/resteasy + chmod 0600 /etc/resteasy + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/resteasy.service b/debian/resteasy.service new file mode 100644 index 0000000..f2a81ae --- /dev/null +++ b/debian/resteasy.service @@ -0,0 +1,8 @@ +[Unit] +Description=backup system + +[Service] +Type=oneshot +ExecStart=/usr/sbin/resteasy mount +ExecStart=/usr/sbin/resteasy run-backup +ExecStopPost=/usr/sbin/resteasy umount diff --git a/debian/resteasy.udev b/debian/resteasy.udev new file mode 100644 index 0000000..a6c2bcb --- /dev/null +++ b/debian/resteasy.udev @@ -0,0 +1,6 @@ +ACTION=="add", \ +SUBSYSTEM=="block", \ +ENV{ID_FS_USAGE}=="filesystem", \ +ENV{ID_PART_ENTRY_TYPE}=="8e8e0bae-5627-4acd-8fd9-70873806d42e", \ +TAG+="systemd", \ +ENV{SYSTEMD_WANTS}="resteasy.service" diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..1a0e016 --- /dev/null +++ b/debian/rules @@ -0,0 +1,11 @@ +#!/usr/bin/make -f + +%: + dh $@ + +override_dh_installman: + mkdir -p debian/resteasy/usr/share/man/man8/ + pandoc --standalone --from markdown-smart --to man resteasy.8.md | \ + gzip -9 --no-name --stdout > \ + debian/resteasy/usr/share/man/man8/resteasy.8.gz + dh_installman diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..f8b7718 --- /dev/null +++ b/readme.md @@ -0,0 +1,16 @@ +# Resteasy + +simple plug and play backup system + +See the [manpage](./resteasy.8.md) for a description. + +## Building + +Resteasy is implemented as a debian source package. It can be built with all the +regular tools, for instance `debuild -uc -us`. + +### Build and install locally + +``` +debuild -uc -us && sudo dpkg --purge resteasy resteasy-desktop && sudo dpkg --install ../*.deb +``` diff --git a/resteasy-desktop/libexec/resteasy-desktop-monitor b/resteasy-desktop/libexec/resteasy-desktop-monitor new file mode 100755 index 0000000..867eb5d --- /dev/null +++ b/resteasy-desktop/libexec/resteasy-desktop-monitor @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +import subprocess +import gi +gi.require_version('Notify', '0.7') +from gi.repository import Notify +from gi.repository import GLib +from pydbus.generic import signal +from pydbus import SystemBus + +loop = GLib.MainLoop() +bus = SystemBus() + + +def handle_signal(sender, object, iface, signal, args): + message = str(args[0]) + Notify.init("resteasy") + notification = Notify.Notification.new("resteasy", message, + "drive-harddisk") + notification.set_urgency( + 2 + ) # 2 highest level, shouldn't go away until a user acknowledges the message + notification.show() + subprocess.call(["pkill", "-SIGRTMIN+10", "i3blocks"]) + + +if __name__ == "__main__": + # subscribe to bus to monitor for server signal emissions + bus.subscribe(object="/io/crashbox/resteasy/Main", + iface="io.crashbox.resteasy.Info", + signal_fired=handle_signal) + loop.run() diff --git a/resteasy.8.md b/resteasy.8.md new file mode 100644 index 0000000..94ed5aa --- /dev/null +++ b/resteasy.8.md @@ -0,0 +1,186 @@ +% resteasy(8) +% Jakob Odersky +% February 2020 + +# NAME + +resteasy \- plug and play backups with borg + +# SYNOPSIS + +**resteasy** `` `[]` + +# DESCRIPTION + +Resteasy is a set of commands and services around Borg Backup. It provides a +system for automating backups to external hard drives without user interaction. + +The idea is that a user simply plugs in a prepared drive, and a backup is +automatically started. + +Note that although resteasy supports backing up the same system to many prepared +drives, only one may be connected at a time. This is because resteasy is geared +towards simple command invocation and hence always mounts drives to a hardcoded +location. No data loss will occur if multiple drives are connected at the same +time (and any currently running backups will not be interrupted), however many +resteasy commands will not work until only one compatible drive is connected. + +## Internals + +Resteasy works with GPT-formatted (GUID Partition Table) drives. When a block +device with a partition type of 8e8e0bae-5627-4acd-8fd9-70873806d42e is +detected, it is mounted and a backup is created using borg. + +Resteasy is implemented as a set of many individual commands (see [RESTEASY +COMMANDS](#RESTEASY-COMMANDS) section). Their implementation structure is +heavily inspired by Git. + +See also the output of **systemctl cat resteasy.service** for a list of commands +the automatic backup service runs, and **/usr/libexec/resteasy/** for their +implementations. + +## Security Considerations + +Automatically mounting and executing a backup when a drive is connected has +security implications. An attacker could simply insert a resteasy drive to +exfiltrate all data. Note however that this vector is mitigated because: + +1. Resteasy uses encrypted borg repositories. +2. Physical access is required for this attack. +3. Someone with physical access could do something much more nefarious, for + example steal the machine. + +# OPTIONS + +**--exec-path** +: Path to wherever your core resteasy programs are installed. This will print +the current setting and then exit. + +# RESTEASY COMMANDS + +Resteasy is divided into high level ("porcelain") commands and low level +("plumbing") commands. + +# HIGH-LEVEL COMMANDS + +**resteasy-inhibit** + +: Pause the automatic backup service temporarily, until **resteasy-uninhibit** is +called or the system is rebooted. Note that this will also stop any backups that +are in progress. + +**resteasy-init** + +: Initialize a borg repository. The drive containing the repository should have +previously been mounted with **resteasy-mount**. + +**resteasy-mount** `[ro]` + +: Find and mount a connected resteasy drive. Resteasy drives are GPT partitions +identified by type UUID `8e8e0bae-5627-4acd-8fd9-70873806d42e`. + +**resteasy-prepare-drive** `` + +: Prepare a drive to be recognized by the resteasy system. + + Once prepared, drives will trigger automatic mounts and backups. It is hence + recommended that the autobackup service be inhibited before running this + operation (otherwise a backup will be attempted on an uninitialized repo, + causing an error to be reported). **Note that this operation reformats the + drive.** + +**resteasy-umount** + +: Unmount a previously mounted resteasy drive. + +**resteasy-uninhibit** + +: Resume the automatic backup service. Note that this will NOT start new backup +runs; any connected resteasy drives must be disconnected and reconnected to +start a new backup. + +# LOW-LEVEL COMMANDS + +**resteasy-find-uuid** + +: Find the GPT partition UUID of a connected resteasy drive. Note that exactly +one resteasy drive mamusty be connected to the system. This command will fail if +it detects more than one. + +**resteasy-run-backup** + +: Trigger a backup. Note that this is typically not run by the user but by the +init system when a resteasy drive is connected. It requires that a drive be +mounted with **resteasy-mount** beforehand. + +# FILES + +/etc/resteasy + +: Contains the passphrase used by borg to encrypt backups. Trailing new lines +are stripped. + +# EXAMPLES + +## Prepare a New Drive + +``` +# temporarily stop the automatic backup service +resteasy inhibit + +# , assumed /dev/sdc in this example + +# set the passphrase for encrypting resteasy backups +echo "1234" > /etc/resteasy + +# wipe and prepare the new drive to be recognized by resteasy +resteasy prepare-drive /dev/sdc + +# initialize new borg repo +resteasy mount +resteasy init +resteasy umount + +# re-enable automatic backup service +resteasy uninhibit +``` + +## Create a Backup + +Simply plug in the drive! + +You can watch backup logs by running: + +``` +journalctl -u resteasy.service -f +``` + +Unplug drive when done. + +## Create a Backup Manually + +``` +resteasy mount +resteasy run-backup +resteasy umount +``` + +## Restore Data + +``` +resteasy inhibit +# +resteasy mount ro + +# perform restore operations +# e.g. borg mount /run/resteasy/mounts/... /mnt +# borg extract... +# ... + +resteasy umount +resteasy uninhibit +``` + +# SEE ALSO + +Borg Backup https://borgbackup.readthedocs.io/en/stable/ diff --git a/resteasy/libexec/resteasy-find-uuid b/resteasy/libexec/resteasy-find-uuid new file mode 100755 index 0000000..331d10a --- /dev/null +++ b/resteasy/libexec/resteasy-find-uuid @@ -0,0 +1,22 @@ +#!/bin/bash +USAGE="" + +# shellcheck source=resteasy-helper.sh +source "$(resteasy --exec-path)/resteasy-helper.sh" + +set -o errexit +set -o nounset + +[[ "$#" -eq 0 ]] || die_with_usage "too many arguments" + +mapfile -t uuids < <(lsblk \ + --noheadings \ + --list \ + --output PARTTYPE,PARTUUID \ + | grep "$RESTEASY_TYPE_UUID" \ + | cut -d' ' -f 2) + +[[ ${#uuids[@]} -gt 0 ]] || die "no resteasy device found" +[[ ${#uuids[@]} -lt 2 ]] || die "more than one resteasy devices found; this command only supports one device plugged in at a time" + +echo "${uuids[0]}" diff --git a/resteasy/libexec/resteasy-helper.sh b/resteasy/libexec/resteasy-helper.sh new file mode 100644 index 0000000..6547626 --- /dev/null +++ b/resteasy/libexec/resteasy-helper.sh @@ -0,0 +1,45 @@ +# shellcheck shell=bash +# shellcheck disable=SC2034 + +# This shell-scriptlet provides utility functions to other resteasy scripts. +# It is meant to be sourced, and should never be executed directly. + +# override $0 to the command's pretty name +BASH_ARGV0=$(basename "$0" | sed 's/-/ /') + +RESTEASY_TYPE_UUID=8e8e0bae-5627-4acd-8fd9-70873806d42e +RESTEASY_MOUNT_POINT=/run/resteasy/mount + +die() { + printf >&2 '%s\n' "$*" + exit 1 +} + +usage() { + echo "usage: $0 $USAGE" + exit 1 +} + +die_with_usage() { + printf >&2 '%s\n' "$*" + echo "usage: $0 $USAGE" >&2 + exit 1 +} + + +log_status() { + echo "status: $1" >&2 + # Send status to a dbus channel, useful for integration with desktop + # notifications. + # Note the "|| true" prevents this function from failing in case dbus is not + # available. + dbus-send --system --type=signal \ + /io/crashbox/resteasy/Main \ + "io.crashbox.resteasy.Info.Status" \ + "string:$1" || true +} + +if [[ ${1:-} == '-h' ]] || [[ ${1:-} == '--help' ]]; then + echo "usage: $0 $USAGE" + exit 0 +fi diff --git a/resteasy/libexec/resteasy-inhibit b/resteasy/libexec/resteasy-inhibit new file mode 100755 index 0000000..0a4b5e6 --- /dev/null +++ b/resteasy/libexec/resteasy-inhibit @@ -0,0 +1,13 @@ +#!/bin/bash +USAGE="" + +# shellcheck source=resteasy-helper.sh +source "$(resteasy --exec-path)/resteasy-helper.sh" + +set -o errexit +set -o nounset + +[[ "$#" -eq 0 ]] || die_with_usage "too many arguments" +[[ $EUID -eq 0 ]] || die "must be root" + +systemctl --no-ask-password --quiet mask --now --runtime resteasy.service diff --git a/resteasy/libexec/resteasy-init b/resteasy/libexec/resteasy-init new file mode 100755 index 0000000..3b98bc5 --- /dev/null +++ b/resteasy/libexec/resteasy-init @@ -0,0 +1,16 @@ +#!/bin/bash +USAGE="" + +# shellcheck source=resteasy-helper.sh +source "$(resteasy --exec-path)/resteasy-helper.sh" + +set -o errexit +set -o nounset + +[[ $# -eq 0 ]] || die_with_usage "too many arguments" +mountpoint -q "$RESTEASY_MOUNT_POINT" || die "no device mounted on $RESTEASY_MOUNT_POINT; run 'resteasy mount' beforehand" +export BORG_REPO="$RESTEASY_MOUNT_POINT/borgbackup/$HOSTNAME" +export BORG_PASSCOMMAND="cat /etc/resteasy" + +mkdir -p "$BORG_REPO" +borg init --encryption=repokey diff --git a/resteasy/libexec/resteasy-mount b/resteasy/libexec/resteasy-mount new file mode 100755 index 0000000..05bbb2a --- /dev/null +++ b/resteasy/libexec/resteasy-mount @@ -0,0 +1,27 @@ +#!/bin/bash +USAGE="[ro]" + +# shellcheck source=resteasy-helper.sh +source "$(resteasy --exec-path)/resteasy-helper.sh" + +set -o errexit +set -o nounset + +flags= +if [[ "$#" -ge 1 ]]; then + case "$1" in + ro) + shift + flags+=--read-only + ;; + *) + die_with_usage "unknown option: $1" + ;; + esac +fi + +uuid=$(resteasy find-uuid) +mkdir -p "$RESTEASY_MOUNT_POINT" +mount $flags "/dev/disk/by-partuuid/$uuid" "$RESTEASY_MOUNT_POINT" + +echo "$RESTEASY_MOUNT_POINT" diff --git a/resteasy/libexec/resteasy-prepare-drive b/resteasy/libexec/resteasy-prepare-drive new file mode 100755 index 0000000..6da4899 --- /dev/null +++ b/resteasy/libexec/resteasy-prepare-drive @@ -0,0 +1,35 @@ +#!/bin/bash +USAGE="" + +# shellcheck source=resteasy-helper.sh +source "$(resteasy --exec-path)/resteasy-helper.sh" + +set -o errexit +set -o nounset + +[[ $# -eq 1 ]] || die_with_usage "no device given" +device="$1" +[[ -b $device ]] || die "$device is not a block device" + +echo "WARNING: this will erase all data on $device." >&2 +read -r -p "Continue? yes/[no]" yn >&2 +[[ $yn == "yes" ]] || die "aborting" + +sgdisk \ + --zap-all \ + --clear \ + --new=1:0:0 \ + --change-name=1:resteasy \ + --typecode=1:"$RESTEASY_TYPE_UUID" \ + "$device" + +# the kernel needs some time to update partition information +sleep 5 +sgdisk --info=1 "$device" + +# note the '2p': this extract the second line of lsblk, which will correspond to +# the first partition on the device +partition_uuid=$(lsblk "$device" --noheadings --output=PARTUUID | sed --quiet 2p) +[[ -n $partition_uuid ]] || die "cannot determine partition UUID after reformatting" + +mkfs.ext4 "/dev/disk/by-partuuid/$partition_uuid" diff --git a/resteasy/libexec/resteasy-run-backup b/resteasy/libexec/resteasy-run-backup new file mode 100755 index 0000000..4d2cfb2 --- /dev/null +++ b/resteasy/libexec/resteasy-run-backup @@ -0,0 +1,74 @@ +#!/bin/bash +USAGE="" + +# shellcheck source=resteasy-helper.sh +source "$(resteasy --exec-path)/resteasy-helper.sh" + +set -o errexit +set -o nounset + +[[ "$#" -eq 0 ]] || die_with_usage "too many arguments" +[[ $EUID -eq 0 ]] || die "must be root" + +failed() { + log_status "errors encountered during backup" +} +trap failed EXIT + +borg --version + +# location of the mounted borg repository +export BORG_REPO="$RESTEASY_MOUNT_POINT/borgbackup/$HOSTNAME" + +# set some environment variables to prevent borg from asking interactive questions +export BORG_RELOCATED_REPO_ACCESS_IS_OK=no # relocated repos aren't cache-friendly +export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=no +export BORG_PASSCOMMAND="cat /etc/resteasy" + +# backup the system into an archive named after +# the machine this script is currently running on +log_status "starting backup" +borg create \ + --verbose \ + --filter AME \ + --list \ + --stats \ + --show-rc \ + --compression lz4 \ + --exclude-caches \ + --exclude '/var/cache/' \ + --exclude '/var/tmp/' \ + --exclude '/root/.cache/' \ + --exclude '/var/lib/docker/devicemapper/' \ + --exclude '/home/*/.cache/' \ + --exclude '/home/*/.local/share/Steam' \ + ::'{hostname}-{now}' \ + /etc \ + /home \ + /root \ + /srv \ + /usr/local \ + /var + +# unnecessary, but just to be extra sure that data has made it onto disk +sync + +log_status "pruning repository" + +# Use the `prune` subcommand to maintain archives of THIS machine. The +# '{hostname}-' prefix is very important to limit prune's operation to this +# machine's archives and not apply to other machines' archives too +borg prune \ + --list \ + --prefix '{hostname}-' \ + --show-rc \ + --keep-daily 7 \ + --keep-weekly 4 \ + --keep-monthly 12 \ + --keep-yearly 10 + +borg check + +log_status "backup completed successfully" +trap - EXIT + diff --git a/resteasy/libexec/resteasy-umount b/resteasy/libexec/resteasy-umount new file mode 100755 index 0000000..08c0451 --- /dev/null +++ b/resteasy/libexec/resteasy-umount @@ -0,0 +1,12 @@ +#!/bin/bash +USAGE="" + +# shellcheck source=resteasy-helper.sh +source "$(resteasy --exec-path)/resteasy-helper.sh" + +set -o errexit +set -o nounset + +[[ "$#" -eq 0 ]] || die_with_usage "too many arguments" + +umount "$RESTEASY_MOUNT_POINT" diff --git a/resteasy/libexec/resteasy-uninhibit b/resteasy/libexec/resteasy-uninhibit new file mode 100755 index 0000000..08371ec --- /dev/null +++ b/resteasy/libexec/resteasy-uninhibit @@ -0,0 +1,13 @@ +#!/bin/bash +USAGE="" + +# shellcheck source=resteasy-helper.sh +source "$(resteasy --exec-path)/resteasy-helper.sh" + +set -o errexit +set -o nounset + +[[ "$#" -eq 0 ]] || die_with_usage "too many arguments" +[[ $EUID -eq 0 ]] || die "must be root" + +systemctl --no-ask-password --quiet unmask --runtime resteasy.service diff --git a/resteasy/sbin/resteasy b/resteasy/sbin/resteasy new file mode 100755 index 0000000..5b3237d --- /dev/null +++ b/resteasy/sbin/resteasy @@ -0,0 +1,32 @@ +#!/bin/bash + +set -o errexit + +exec_path="/usr/libexec/resteasy" + +case $1 in + --exec-path) + echo "$exec_path" + exit 0 + ;; + -*) + echo "resteasy: unrecognized option $1" >&2 + exit 1 + ;; +esac + +if [[ -z "$1" ]]; then + echo "usage: resteasy " + exit 1 +elif command -v "resteasy-$1" > /dev/null; then + cmd="resteasy-$1" + shift + exec "$cmd" "$@" +elif [[ -x $exec_path/resteasy-$1 ]]; then + cmd="$exec_path/resteasy-$1" + shift + exec "$cmd" "$@" +else + echo "resteasy: '$1' is not a valid command" + exit 1 +fi -- cgit v1.2.3