Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f17848bed2 | ||
|
|
d5497b04b4 | ||
|
|
855997d7d7 | ||
|
|
77b5a2c653 | ||
|
|
489046c603 | ||
|
|
6a43b95222 | ||
|
|
329fa40c30 | ||
|
|
7c64d861ae | ||
|
|
7ebeb00761 | ||
|
|
041d3374cc | ||
|
|
5ed72bb87f | ||
|
|
9797543231 | ||
|
|
7e5496d00a | ||
|
|
22d6af802f | ||
|
|
38b3243b4c | ||
|
|
d5a141fc9a | ||
|
|
f4d1d6f1b2 | ||
|
|
14f9741b82 | ||
|
|
43b718ea86 | ||
|
|
ef059ebd68 | ||
|
|
de1b851d3d | ||
|
|
b00ae89812 | ||
|
|
2c14351cd4 | ||
|
|
cfbc6c6c51 | ||
|
|
e8a2647cae | ||
|
|
4952cc3ee1 | ||
|
|
3ecc3c3510 | ||
|
|
65172e650b | ||
|
|
705248ee00 | ||
|
|
be2c3163a8 | ||
|
|
84e083c62e | ||
|
|
c5c4da3618 | ||
|
|
ef731f33b2 | ||
|
|
92205981b6 | ||
|
|
37f4775eaa | ||
|
|
4f7da2c975 | ||
|
|
7bc15e2254 | ||
|
|
7c0b89a9c3 | ||
|
|
09692f7a5f | ||
|
|
25207799e6 | ||
|
|
e3a5a2d250 | ||
|
|
8fd61d768b | ||
|
|
ce936fceb3 | ||
|
|
eac2177042 | ||
|
|
ef1c464efd | ||
|
|
418217f746 | ||
|
|
86ece14d73 | ||
|
|
9f1158f0cb | ||
|
|
11d600f7c0 | ||
|
|
d8cfd6f6a6 | ||
|
|
58cfbba0cb | ||
|
|
66c47afd77 | ||
|
|
92d9e7cd1f | ||
|
|
1dbc2d4799 | ||
|
|
23e134c5e7 | ||
|
|
72088212af | ||
|
|
148e43c8c3 | ||
|
|
8dd1beb3d2 | ||
|
|
99e51e297a | ||
|
|
c1ce0d069b | ||
|
|
da2ad5f6f3 | ||
|
|
9b4018ce62 | ||
|
|
3a8ca5a815 | ||
|
|
37e38b4cb5 | ||
|
|
8f734ccc69 | ||
|
|
56c4fca8f6 | ||
|
|
9449d78596 | ||
|
|
c50e66b48f | ||
|
|
c1edb2efe1 | ||
|
|
8275f708ea | ||
|
|
eac8b97932 | ||
|
|
bb40afa67a | ||
|
|
cacfe58269 | ||
|
|
96e9bc23ab | ||
|
|
911f9f44d2 | ||
|
|
abac4b11ba | ||
|
|
cfaab7eb72 | ||
|
|
978ca2becb | ||
|
|
6cb6b41066 | ||
|
|
16302e5d35 | ||
|
|
aeec8991b6 | ||
|
|
0f5a8f0ca5 | ||
|
|
4a2ca821d7 | ||
|
|
3b08a42495 | ||
|
|
9ec3b1cb79 | ||
|
|
35c1c45352 | ||
|
|
f45b6298a4 | ||
|
|
9fa5074699 | ||
|
|
71d0e8c5c1 | ||
|
|
0d92cca32d | ||
|
|
30d18b8b0e | ||
|
|
9ff51d691a | ||
|
|
edaafdf10a | ||
|
|
07541cfaf2 | ||
|
|
399e7cd4ce | ||
|
|
0f3d39dfe1 | ||
|
|
7dde85f25e | ||
|
|
9ebc9ea641 | ||
|
|
f7c13f7290 | ||
|
|
c07f0ca027 | ||
|
|
a084830441 | ||
|
|
7d67142b6e | ||
|
|
3f000ce137 |
6
.github/workflows/linter.yml
vendored
6
.github/workflows/linter.yml
vendored
@@ -3,13 +3,13 @@ name: Lint Code Base
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: master
|
||||
branches: main
|
||||
paths:
|
||||
- '**.sh'
|
||||
- '.github/workflows/linter.yml'
|
||||
- 'bin/**'
|
||||
pull_request:
|
||||
branches: master
|
||||
branches: main
|
||||
paths:
|
||||
- '**.sh'
|
||||
- '.github/workflows/linter.yml'
|
||||
@@ -29,5 +29,5 @@ jobs:
|
||||
env:
|
||||
VALIDATE_ALL_CODEBASE: true
|
||||
VALIDATE_BASH: true
|
||||
DEFAULT_BRANCH: master
|
||||
DEFAULT_BRANCH: main
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
61
CHANGELOG.md
61
CHANGELOG.md
@@ -6,6 +6,61 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [7.3.4] - 2022-04-29
|
||||
### Fixed
|
||||
- Backup stats notifications: fix issue where `restic snapshots --latest 2` will show more than two snapshots due to different backup paths used.
|
||||
|
||||
## [7.3.3] - 2022-04-14
|
||||
### Fixed
|
||||
- Trying to fix broken Homebrew bottles due to GitHub API issues.
|
||||
|
||||
## [7.3.2] - 2022-04-11
|
||||
### Fixed
|
||||
- Trying to fix broken Homebrew bottles
|
||||
|
||||
## [7.3.1] - 2022-04-11
|
||||
### Fixed
|
||||
- `resticw` is now a true wrapper in that it support `--` args to restic.
|
||||
- OnFailure no longer masked by the stderr redirect to systemd-cat. [#86](https://github.com/erikw/restic-automatic-backup-scheduler/pull/86)
|
||||
|
||||
## [7.3.0] - 2022-02-15
|
||||
### Added
|
||||
- optional user-controlled notification. See `RESTIC_NOTIFY_BACKUP_STATS` and in `backup.sh`.
|
||||
|
||||
## [7.2.0] - 2022-02-15
|
||||
### Added
|
||||
- restic-check LaunchAgent.
|
||||
|
||||
### Changed
|
||||
- [README.md](README.md) is restructured with easier TL;DR for each OS and a more general detailed section for the interested.
|
||||
|
||||
## [7.1.0] - 2022-02-13
|
||||
### Changed
|
||||
- Minimize base install. The following features are now opt-in: nm-unmetered detection, cron_mail, systemd-email.
|
||||
|
||||
## [7.0.0] - 2022-02-13
|
||||
### Changed
|
||||
- Renamed project from `restic-systemd-automatic-backup` to `restic-automatic-backup-scheduler` to fit all now supported setups.
|
||||
|
||||
## [6.0.0] - 2022-02-12
|
||||
### Added
|
||||
- Windows support with native ScheduledTask! New target `$ make install-schedtask` for Windows users.
|
||||
|
||||
## [5.3.1] - 2022-02-12
|
||||
### Fixed
|
||||
- Launchagentdir make macro
|
||||
|
||||
## [5.3.0] - 2022-02-12
|
||||
### Added
|
||||
- Allow custom launchagent dir, used by Homebrew.
|
||||
|
||||
## [5.2.1] - 2022-02-11
|
||||
### Added
|
||||
- Homebrew Formula at [erikw/homebrew-tap](https://github.com/erikw/homebrew-tap). You can now install with `$ brew install erikw/tap/restic-automatic-backup-scheduler`!
|
||||
|
||||
### Fixed
|
||||
- Use default profile in LaunchAgent.
|
||||
|
||||
## [5.2.0] - 2022-02-11
|
||||
### Added
|
||||
- Make option to override destination dir for configuration files. Needed for Homebrew.
|
||||
@@ -25,7 +80,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- `$ make install-cron` for installing the cron-job.
|
||||
|
||||
### Changed
|
||||
- **BREAKING CHANGE** moved systemd installation with makefile from `/etc/systemd/system` to `/usr/lib/systemd/system` as this is what packages should do. This is to be able to simplify the arch [PKGBUILD](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=restic-systemd-automatic-backup) so that it does not need to do anything else than `make install`.
|
||||
- **BREAKING CHANGE** moved systemd installation with makefile from `/etc/systemd/system` to `/usr/lib/systemd/system` as this is what packages should do. This is to be able to simplify the arch [PKGBUILD](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=restic-automatic-backup-scheduler) so that it does not need to do anything else than `make install`.
|
||||
- If you upgrade form an existing install, you should disable and then re-enable the timer, so that the symlink is pointing to the new location of the timer.
|
||||
```console
|
||||
# systemctl disable restic-backup@<profile>.timer
|
||||
@@ -69,7 +124,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [2.0.0] - 2022-02-01
|
||||
### Changed
|
||||
- **BREAKING CHANGE** [#45](https://github.com/erikw/restic-systemd-automatic-backup/pull/45): multiple backup profiles are now supported. Please backup your configuration before upgrading. The setup of configuration files are now laied out differently. See the [README.md](README.md) TL;DR setup section.
|
||||
- **BREAKING CHANGE** [#45](https://github.com/erikw/restic-automatic-backup-scheduler/pull/45): multiple backup profiles are now supported. Please backup your configuration before upgrading. The setup of configuration files are now laied out differently. See the [README.md](README.md) TL;DR setup section.
|
||||
- `restic_backup.sh` has had variables extracted to profiles instead, to allow for configuration of different backups on the same system.
|
||||
- `b2_env.sh` is split to two files `_global.env` and `default.env` (the default profile). `_global.env` will have B2 accountID and accountKey and `default.env` has backup paths, and retention.
|
||||
- `b2_pw.sh` renamed to pw.txt
|
||||
@@ -80,7 +135,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [1.0.1] - 2021-12-03
|
||||
### Fixed
|
||||
- $(make install) now works for the *.template files ([#40](https://github.com/erikw/restic-systemd-automatic-backup/issues/40))
|
||||
- $(make install) now works for the *.template files ([#40](https://github.com/erikw/restic-automatic-backup-scheduler/issues/40))
|
||||
|
||||
## [1.0.0] - 2021-12-02
|
||||
It's time to call this a proper major version!
|
||||
|
||||
16
LICENSE
16
LICENSE
@@ -1,15 +1,11 @@
|
||||
restic-systemd-automatic-backup - My restic backup solution using Backblaze B2 storage, systemd timers (or cron) and email notifications on failure.
|
||||
|
||||
|
||||
Copyright (c) 2022, Erik Westrup + see commit log for auhtors
|
||||
All rights reserved.
|
||||
Copyright 2018 Erik Westrup
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
http://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
@@ -6,22 +6,22 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.github.erikw.restic-automatic-backup</string>
|
||||
<string>com.github.erikw.restic-backup</string>
|
||||
<key>ProgramArguments</key>
|
||||
<!-- exec in subshell to 1) source *.env.sh 2) expand $HOME to logpath (ref. https://apple.stackexchange.com/a/365880/197493) -->
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-c</string>
|
||||
<string>source /usr/local/etc/restic/erikw.env.sh && /usr/local/bin/restic_backup.sh >>$HOME/$LOG_OUT 2>>$HOME/$LOG_ERR</string>
|
||||
<string>source $INSTALL_PREFIX/etc/restic/default.env.sh && $INSTALL_PREFIX/bin/restic_backup.sh >>$HOME/$LOG_OUT 2>>$HOME/$LOG_ERR</string>
|
||||
</array>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
||||
<string>$INSTALL_PREFIX/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
||||
<key>LOG_OUT</key>
|
||||
<string>/Library/Logs/restic/restic_stdout.log</string>
|
||||
<string>/Library/Logs/restic/backup_stdout.log</string>
|
||||
<key>LOG_ERR</key>
|
||||
<string>/Library/Logs/restic/restic_stderr.log</string>
|
||||
<string>/Library/Logs/restic/backup_stderr.log</string>
|
||||
</dict>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
37
Library/LaunchAgents/com.github.erikw.restic-check.plist
Normal file
37
Library/LaunchAgents/com.github.erikw.restic-check.plist
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.github.erikw.restic-check</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-c</string>
|
||||
<string>source $INSTALL_PREFIX/etc/restic/default.env.sh && $INSTALL_PREFIX/bin/restic_check.sh >>$HOME/$LOG_OUT 2>>$HOME/$LOG_ERR</string>
|
||||
</array>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>$INSTALL_PREFIX/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
||||
<key>LOG_OUT</key>
|
||||
<string>/Library/Logs/restic/check_stdout.log</string>
|
||||
<key>LOG_ERR</key>
|
||||
<string>/Library/Logs/restic/check_stderr.log</string>
|
||||
</dict>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<!-- Will schedule check every 1st of the month at 20:00 -->
|
||||
<key>StartCalendarInterval</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>Day</key>
|
||||
<integer>1</integer>
|
||||
<key>Hour</key>
|
||||
<integer>20</integer>
|
||||
<key>Minute</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
99
Makefile
99
Makefile
@@ -1,4 +1,3 @@
|
||||
# TODO add install for launchagent completely, and unisntall target using bootstrap?
|
||||
#### Notes ####################################################################
|
||||
# This build process is done in three stages (out-of-source build):
|
||||
# 1. copy source files to the local build directory.
|
||||
@@ -18,8 +17,10 @@
|
||||
.PHONY: help clean uninstall \
|
||||
install-systemd install-cron \
|
||||
install-targets-script install-targets-conf install-targets-systemd \
|
||||
install-targets-cron \
|
||||
activate-launchagent deactivate-launchagent
|
||||
install-targets-cron install-targets-launchagent \
|
||||
install-targets-schedtask uninstall-targets-schedtask \
|
||||
activate-launchagent-backup deactivate-launchagent-backup \
|
||||
activate-launchagent-chec deactivate-launchagent-check
|
||||
|
||||
#### Macros ###################################################################
|
||||
NOW := $(shell date +%Y-%m-%d_%H:%M:%S)
|
||||
@@ -33,6 +34,15 @@ else
|
||||
BAK_SUFFIX = -B .$(NOW).bak
|
||||
endif
|
||||
|
||||
|
||||
# Source: https://stackoverflow.com/a/14777895/265508
|
||||
ifeq ($(OS),Windows_NT)
|
||||
CUR_OS := Windows
|
||||
else
|
||||
CUR_OS := $(shell uname)
|
||||
endif
|
||||
|
||||
|
||||
# Create parent directories of a file, if not existing.
|
||||
# Reference: https://stackoverflow.com/a/25574592/265508
|
||||
MKDIR_PARENTS=sh -c '\
|
||||
@@ -42,8 +52,10 @@ MKDIR_PARENTS=sh -c '\
|
||||
|
||||
# LaunchAgent names.
|
||||
UID := $(shell id -u)
|
||||
LAUNCHAGENT = com.github.erikw.restic-automatic-backup
|
||||
LAUNCHAGENT_TARGET = gui/$(UID)/$(LAUNCHAGENT)
|
||||
LAUNCHAGENT_BACKUP = com.github.erikw.restic-backup
|
||||
LAUNCHAGENT_CHECK = com.github.erikw.restic-check
|
||||
LAUNCHAGENT_TARGET_BACKUP = gui/$(UID)/$(LAUNCHAGENT_BACKUP)
|
||||
LAUNCHAGENT_TARGET_CHECK = gui/$(UID)/$(LAUNCHAGENT_CHECK)
|
||||
|
||||
# What to substitute $INSTALL_PREFIX in sources to.
|
||||
# This can be useful to set to empty on commandline when building e.g. an AUR
|
||||
@@ -53,28 +65,45 @@ INSTALL_PREFIX := $(PREFIX)
|
||||
# Where to install persistent configuration files. Used by Homebrew.
|
||||
SYSCONFDIR := $(PREFIX)
|
||||
|
||||
# Where to install LaunchAgent. Used by Homebrew.
|
||||
LAUNCHAGENTDIR := $(HOME)
|
||||
|
||||
# ScheduledTask powershell scripts.
|
||||
SCHEDTASK_INSTALL = install.ps1
|
||||
SCHEDTASK_UNINSTALL = uninstall.ps1
|
||||
|
||||
# Source directories.
|
||||
DIR_SCRIPT = bin
|
||||
DIR_CONF = etc/restic
|
||||
DIR_SYSTEMD = usr/lib/systemd/system
|
||||
DIR_CRON = etc/cron.d
|
||||
DIR_LAUNCHAGENT = Library/LaunchAgents
|
||||
DIR_SCHEDTASK = ScheduledTask
|
||||
|
||||
# Source files.
|
||||
SRCS_SCRIPT = $(filter-out %cron_mail, $(wildcard $(DIR_SCRIPT)/*))
|
||||
SRCS_SCRIPT = $(filter-out \
|
||||
%cron_mail \
|
||||
%systemd-email \
|
||||
%nm-unmetered-connection.sh \
|
||||
, $(wildcard $(DIR_SCRIPT)/*))
|
||||
SRCS_CONF = $(wildcard $(DIR_CONF)/*)
|
||||
SRCS_SYSTEMD = $(wildcard $(DIR_SYSTEMD)/*)
|
||||
SRCS_SYSTEMD = $(filter-out \
|
||||
%status-email-user@.service \
|
||||
%nm-unmetered-connection.service \
|
||||
, $(wildcard $(DIR_SYSTEMD)/*))
|
||||
SRCS_CRON = $(wildcard $(DIR_CRON)/*)
|
||||
SRCS_LAUNCHAGENT= $(wildcard $(DIR_LAUNCHAGENT)/*)
|
||||
SRCS_SCHEDTASK = $(wildcard $(DIR_SCHEDTASK)/*)
|
||||
|
||||
# Local build directory. Sources will be copied here,
|
||||
# modified and then installed from this directory.
|
||||
BUILD_DIR := build
|
||||
BUILD_DIR = build
|
||||
BUILD_DIR_SCRIPT = $(BUILD_DIR)/$(DIR_SCRIPT)
|
||||
BUILD_DIR_CONF = $(BUILD_DIR)/$(DIR_CONF)
|
||||
BUILD_DIR_SYSTEMD = $(BUILD_DIR)/$(DIR_SYSTEMD)
|
||||
BUILD_DIR_CRON = $(BUILD_DIR)/$(DIR_CRON)
|
||||
BUILD_DIR_LAUNCHAGENT = $(BUILD_DIR)/$(DIR_LAUNCHAGENT)
|
||||
BUILD_DIR_SCHEDTASK = $(BUILD_DIR)/$(DIR_SCHEDTASK)
|
||||
|
||||
# Sources copied to build directory.
|
||||
BUILD_SRCS_SCRIPT = $(addprefix $(BUILD_DIR)/, $(SRCS_SCRIPT))
|
||||
@@ -82,13 +111,14 @@ BUILD_SRCS_CONF = $(addprefix $(BUILD_DIR)/, $(SRCS_CONF))
|
||||
BUILD_SRCS_SYSTEMD = $(addprefix $(BUILD_DIR)/, $(SRCS_SYSTEMD))
|
||||
BUILD_SRCS_CRON = $(addprefix $(BUILD_DIR)/, $(SRCS_CRON))
|
||||
BUILD_SRCS_LAUNCHAGENT = $(addprefix $(BUILD_DIR)/, $(SRCS_LAUNCHAGENT))
|
||||
BUILD_SRCS_SCHEDTASK = $(addprefix $(BUILD_DIR)/, $(SRCS_SCHEDTASK))
|
||||
|
||||
# Destination directories
|
||||
DEST_DIR_SCRIPT = $(PREFIX)/$(DIR_SCRIPT)
|
||||
DEST_DIR_CONF = $(SYSCONFDIR)/$(DIR_CONF)
|
||||
DEST_DIR_SYSTEMD = $(PREFIX)/$(DIR_SYSTEMD)
|
||||
DEST_DIR_CRON = $(PREFIX)/$(DIR_CRON)
|
||||
DEST_DIR_LAUNCHAGENT= $(HOME)/$(DIR_LAUNCHAGENT)
|
||||
DEST_DIR_LAUNCHAGENT= $(LAUNCHAGENTDIR)/$(DIR_LAUNCHAGENT)
|
||||
DEST_DIR_MAC_LOG = $(HOME)/Library/Logs/restic
|
||||
|
||||
# Destination file targets.
|
||||
@@ -96,7 +126,10 @@ DEST_TARGS_SCRIPT = $(addprefix $(PREFIX)/, $(SRCS_SCRIPT))
|
||||
DEST_TARGS_CONF = $(addprefix $(SYSCONFDIR)/, $(SRCS_CONF))
|
||||
DEST_TARGS_SYSTEMD = $(addprefix $(PREFIX)/, $(SRCS_SYSTEMD))
|
||||
DEST_TARGS_CRON = $(addprefix $(PREFIX)/, $(SRCS_CRON))
|
||||
DEST_TARGS_LAUNCHAGENT = $(addprefix $(HOME)/, $(SRCS_LAUNCHAGENT))
|
||||
DEST_TARGS_LAUNCHAGENT = $(addprefix $(LAUNCHAGENTDIR)/, $(SRCS_LAUNCHAGENT))
|
||||
|
||||
DEST_LAUNCHAGENT_BACKUP = $(DEST_DIR_LAUNCHAGENT)/$(LAUNCHAGENT_BACKUP).plist
|
||||
DEST_LAUNCHAGENT_CHECK = $(DEST_DIR_LAUNCHAGENT)/$(LAUNCHAGENT_CHECK).plist
|
||||
|
||||
INSTALLED_FILES = $(DEST_TARGS_SCRIPT) $(DEST_TARGS_CONF) \
|
||||
$(DEST_TARGS_SYSTEMD) $(DEST_TARGS_CRON) \
|
||||
@@ -113,7 +146,7 @@ clean:
|
||||
$(RM) -r $(BUILD_DIR)
|
||||
|
||||
# target: uninstall - Uninstall ALL installed (including config) files.
|
||||
uninstall:
|
||||
uninstall: uninstall-schedtask
|
||||
@for file in $(INSTALLED_FILES); do \
|
||||
echo $(RM) $$file; \
|
||||
$(RM) $$file; \
|
||||
@@ -130,10 +163,21 @@ install-systemd: install-targets-script install-targets-conf \
|
||||
# target: install-cron - Install cron setup.
|
||||
install-cron: install-targets-script install-targets-conf install-targets-cron
|
||||
|
||||
# target: install-launchagent - Install LaunchAgent setup.
|
||||
# target: install-launchagent - Install backup LaunchAgent setup.
|
||||
install-launchagent: install-targets-script install-targets-conf \
|
||||
install-targets-launchagent
|
||||
|
||||
# target: install-launchagent-check - Install check LaunchAgent setup.
|
||||
# Intended to be run after install-launchagent, thus not requiring scripts/conf
|
||||
#install-launchagent: install-targets-launchagent
|
||||
|
||||
# target: install-schedtask - Install Windows ScheduledTasks
|
||||
install-schedtask: install-targets-script install-targets-conf \
|
||||
install-targets-schedtask
|
||||
|
||||
# target: uninstall-schedtask - Uninstall Windows ScheduledTasks
|
||||
uninstall-schedtask: uninstall-targets-schedtask
|
||||
|
||||
# Install targets. Prereq build sources as well,
|
||||
# so that build dir is re-created if deleted.
|
||||
install-targets-script: $(DEST_TARGS_SCRIPT) $(BUILD_SRCS_SCRIPT)
|
||||
@@ -142,6 +186,11 @@ install-targets-systemd: $(DEST_TARGS_SYSTEMD) $(BUILD_SRCS_SYSTEMD)
|
||||
install-targets-cron: $(DEST_TARGS_CRON) $(BUILD_SRCS_CRON)
|
||||
install-targets-launchagent: $(DEST_TARGS_LAUNCHAGENT) \
|
||||
$(BUILD_SRCS_LAUNCHAGENT) $(DEST_DIR_MAC_LOG)
|
||||
install-targets-schedtask: $(BUILD_DIR_SCHEDTASK)/$(SCHEDTASK_INSTALL)
|
||||
test $(CUR_OS) != Windows || ./$<
|
||||
|
||||
uninstall-targets-schedtask: $(BUILD_DIR_SCHEDTASK)/$(SCHEDTASK_UNINSTALL)
|
||||
test $(CUR_OS) != Windows || ./$<
|
||||
|
||||
# Copies sources to build directory & replace "$INSTALL_PREFIX".
|
||||
$(BUILD_DIR)/% : %
|
||||
@@ -178,12 +227,22 @@ $(DEST_DIR_LAUNCHAGENT)/%: $(BUILD_DIR_LAUNCHAGENT)/%
|
||||
$(DEST_DIR_MAC_LOG):
|
||||
mkdir -p $@
|
||||
|
||||
# target: activate-launchagent - Activate the LaunchAgent.
|
||||
activate-launchagent:
|
||||
launchctl bootstrap gui/$(UID) $(DEST_TARGS_LAUNCHAGENT)
|
||||
launchctl enable $(LAUNCHAGENT_TARGET)
|
||||
launchctl kickstart -p $(LAUNCHAGENT_TARGET)
|
||||
# target: activate-launchagent-backup - Activate the backup LaunchAgent.
|
||||
activate-launchagent-backup:
|
||||
launchctl bootstrap gui/$(UID) $(DEST_LAUNCHAGENT_BACKUP)
|
||||
launchctl enable $(LAUNCHAGENT_TARGET_BACKUP)
|
||||
launchctl kickstart -p $(LAUNCHAGENT_TARGET_BACKUP)
|
||||
|
||||
# target: deactivate-launchagent - Deactivate and remove the LaunchAgent.
|
||||
deactivate-launchagent:
|
||||
launchctl bootout $(LAUNCHAGENT_TARGET)
|
||||
# target: activate-launchagent-check - Activate the check LaunchAgent.
|
||||
activate-launchagent-check:
|
||||
launchctl bootstrap gui/$(UID) $(DEST_LAUNCHAGENT_CHECK)
|
||||
launchctl enable $(LAUNCHAGENT_TARGET_CHECK)
|
||||
launchctl kickstart -p $(LAUNCHAGENT_TARGET_CHECK)
|
||||
|
||||
# target: deactivate-launchagent-backup - Remove the backup LaunchAgent.
|
||||
deactivate-launchagent-backup:
|
||||
launchctl bootout $(LAUNCHAGENT_TARGET_BACKUP)
|
||||
|
||||
# target: deactivate-launchagent-check - Remove the check LaunchAgent.
|
||||
deactivate-launchagent-check:
|
||||
launchctl bootout $(LAUNCHAGENT_TARGET_CHECK)
|
||||
|
||||
537
README.md
537
README.md
@@ -1,110 +1,306 @@
|
||||
# Automatic restic backups using systemd services and timers
|
||||
[](#)
|
||||
[](#)
|
||||
# Automatic restic Backups using Native OS Task Schedulers
|
||||
*formerly named restic-systemd-automatic-backup*
|
||||
|
||||
[](#)
|
||||
[](#)
|
||||
<br>
|
||||
[](https://github.com/erikw/restic-systemd-automatic-backup/actions/workflows/linter.yml)
|
||||
[](https://github.com/erikw/restic-systemd-automatic-backup/tags)
|
||||
[](https://aur.archlinux.org/packages/restic-systemd-automatic-backup/)
|
||||
[](https://aur.archlinux.org/packages/restic-systemd-automatic-backup/)
|
||||
[](https://github.com/erikw/restic-systemd-automatic-backup/issues)
|
||||
[](https://github.com/erikw/restic-systemd-automatic-backup/issues?q=is%3Aissue+is%3Aclosed)
|
||||
[](https://github.com/erikw/restic-systemd-automatic-backup/pulls?q=is%3Apr+is%3Aclosed)
|
||||
[](https://github.com/erikw/restic-automatic-backup-scheduler/actions/workflows/linter.yml)
|
||||
[](https://github.com/erikw/restic-automatic-backup-scheduler/tags)
|
||||
[](https://aur.archlinux.org/packages/restic-automatic-backup-scheduler/)
|
||||
[](https://aur.archlinux.org/packages/restic-automatic-backup-scheduler/)
|
||||
[](https://github.com/erikw/homebrew-tap)
|
||||
[](https://github.com/erikw/restic-automatic-backup-scheduler/issues)
|
||||
[](https://github.com/erikw/restic-automatic-backup-scheduler/issues?q=is%3Aissue+is%3Aclosed)
|
||||
[](https://github.com/erikw/restic-automatic-backup-scheduler/pulls?q=is%3Apr+is%3Aclosed)
|
||||
[](LICENSE)
|
||||
[](https://github.com/Netflix/osstracker)
|
||||
[](https://github.com/Netflix/osstracker)
|
||||
<br>
|
||||
|
||||
[](https://github.com/erikw/restic-systemd-automatic-backup/graphs/contributors) including these top contributors:
|
||||
<a href = "https://github.com/erikw/restic-systemd-automatic-backup/graphs/contributors">
|
||||
<img src = "https://contrib.rocks/image?repo=erikw/restic-systemd-automatic-backup&max=24"/>
|
||||
[](https://github.com/erikw/restic-automatic-backup-scheduler/graphs/contributors) including these top contributors:
|
||||
<a href = "https://github.com/erikw/restic-automatic-backup-scheduler/graphs/contributors">
|
||||
<img src = "https://contrib.rocks/image?repo=erikw/restic-automatic-backup-scheduler&max=24"/>
|
||||
</a>
|
||||
|
||||
# Intro
|
||||
[restic](https://restic.net/) is a command-line tool for making backups, the right way. Check the official website for a feature explanation. As a storage backend, I recommend [Backblaze B2](https://www.backblaze.com/b2/cloud-storage.html) as restic works well with it, and it is (at the time of writing) very affordable for the hobbyist hacker! (anecdotal: I pay for my full-systems backups each month typically < 1 USD).
|
||||
|
||||
Unfortunately restic does not come pre-configured with a way to run automated backups, say every day. However it's possible to set this up yourself using systemd/cron and some wrappers. This example also features email notifications when a backup fails to complete.
|
||||
Unfortunately restic does not come pre-configured with a way to run automated backups, say every day. However it's possible to set this up yourself using built-in tools in your OS and some wrappers. For Linux with systemd, it's convenient to use systemd timers. For macOS systems, we can use built-in LaunchAgents. For Windows we can use ScheduledTasks. Any OS having something cron-like will also work!
|
||||
|
||||
Here follows a step-by step tutorial on how to set it up, with my sample script and configurations that you can modify to suit your needs.
|
||||
|
||||
Note, you can use any of the supported [storage backends](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html). The setup should be similar but you will have to use other configuration variables to match your backend of choice.
|
||||
Note, you can use any restic's supported [storage backends](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html). The setup should be similar but you will have to use other configuration variables to match your backend of choice.
|
||||
|
||||
## Project Scope
|
||||
The scope for this is not to be a full-fledged super solution that solves all the problems and all possible setups. The aim is to be a hackable code base for you to start sewing up the perfect backup solution that fits your requirements!
|
||||
|
||||
Nevertheless the project should work out of the box, be minimal but still open the doors for configuration and extensions by users.
|
||||
|
||||
## Navigate this README
|
||||
Tip: use the Section icon in the top left of this document to navigate the sections.
|
||||
|
||||

|
||||
## Notes
|
||||
* Tip: Navigate this document easily from the Section icon in the top left corner.
|
||||

|
||||
* ☝ **Note**: in the command listing in this document, `$` means a user shell and `#` means a root shell (or use `sudo`).
|
||||
|
||||
|
||||
# Requirements
|
||||
* `restic >=v0.9.6`
|
||||
* `bash >=v4.0.0`
|
||||
* (recommended) GNU `make` if you want an automated install
|
||||
* Arch: part of the `base-devel` meta package, Debian/Ubuntu: part of the `build-essential` meta package, macOS: use the preinstalled or a more recent with Homebrew)
|
||||
* Arch: part of the `base-devel` meta package, Debian/Ubuntu: part of the `build-essential` meta package, macOS: use the pre-installed or a more recent with Homebrew
|
||||
|
||||
|
||||
# Setup
|
||||
Depending on your system, the setup will look different. Choose one of
|
||||
Depending on your system, the setup will look different. Choose one of:
|
||||
* <img height="16" width="16" src="https://unpkg.com/simple-icons@v6/icons/linux.svg" /> [Linux + Systemd](#setup-linux-systemd)
|
||||
* <img height="16" width="16" src="https://unpkg.com/simple-icons@v6/icons/apple.svg" /> [macOS + LaunchAgent](#setup-macos-launchagent)
|
||||
* <img height="16" width="16" src="https://unpkg.com/simple-icons@v6/icons/windows.svg" /> [Windows + ScheduledTask](#setup-windows-scheduledtask)
|
||||
* <img height="16" width="16" src="https://unpkg.com/simple-icons@v6/icons/clockify.svg" /> [Cron](#setup-cron) - for any system having a cron daemon. Tested on FreeBSD and macOS.
|
||||
|
||||
|
||||
## Setup Linux Systemd
|
||||
### TL;DR Setup
|
||||
1. Create B2 credentials as instructed [below](#1-create-backblaze-b2-account)
|
||||
1. Install config and scripts:
|
||||
<img height="64" width="64" src="https://unpkg.com/simple-icons@v6/icons/linux.svg" />
|
||||
|
||||
☝ **Note** The Linux setup here will assume an installation to `/`.
|
||||
|
||||
Many Linux distributions nowadays use [Systemd](https://en.wikipedia.org/wiki/Systemd), which features good support for running services and scheduled jobs. If your distribution is no on Systemd, check out the [cron setup](#setup-cron) instead.
|
||||
|
||||
**TL;DR setup**
|
||||
1. [Create](#1-create-backblaze-b2-account-bucket-and-keys) B2 bucket + credentials
|
||||
1. Install scripts, configs systemd units/timers:
|
||||
* With `make`:
|
||||
```console
|
||||
$ sudo make install-systemd
|
||||
```
|
||||
☝ **Note**: `sudo` is required here, as some files are installed into system directories (`/etc/`
|
||||
and `/usr/bin`). Have a look to the `Makefile` to know more.
|
||||
1. Fill out configuration values (edit with sudo):
|
||||
* `/etc/restic/pw.txt` - Contains the password (single line) to be used by restic to encrypt the repository files. Should be different than your B2 password!
|
||||
* `/etc/restic/_global.env.sh` - Global environment variables.
|
||||
* `/etc/restic/default.env.sh` - Profile specific environment variables (multiple profiles can be defined by copying to `/etc/restic/something.env.sh`).
|
||||
* `/etc/restic/backup_exclude.txt` - List of file patterns to ignore. This will trim down your backup size and the speed of the backup a lot when done properly!
|
||||
1. Initialize remote repo as described [below](#3-initialize-remote-repo)
|
||||
1. Configure [how often](https://www.freedesktop.org/software/systemd/man/systemd.time.html#Calendar%20Events) back up should be made.
|
||||
* Edit if needed `OnCalendar` in `/usr/lib/systemd/system/restic-backup@.timer`.
|
||||
1. Enable automated backup for starting with the system (`enable` creates symlinks):
|
||||
* <img height="16" width="16" src="https://unpkg.com/simple-icons@v6/icons/archlinux.svg" /> Arch Linux users: use the [AUR](https://aur.archlinux.org/packages/restic-automatic-backup-scheduler) package, e.g.
|
||||
```console
|
||||
$ sudo systemctl enable --now restic-backup@default.timer
|
||||
$ yay -S restic-automatic-backup-scheduler
|
||||
```
|
||||
1. And run an immediate backup if you want (if not, it will run on daily basis):
|
||||
1. Fill out [configuration values](#2-configure-b2-credentials-locally) in `/etc/restic`.
|
||||
1. [Initialize](#3-initialize-remote-repo) the remote repo.
|
||||
Source the profile to make all needed configuration available to `restic(1)`. All commands after this assumes the profile is sourced in the current shell.
|
||||
```console
|
||||
$ sudo systemctl start restic-backup@default
|
||||
# source /etc/restic/default.env.sh
|
||||
# restic init
|
||||
```
|
||||
1. Watch its progress with Systemd journal:
|
||||
1. Configure [how often](https://www.freedesktop.org/software/systemd/man/systemd.time.html#Calendar%20Events) backups should be done.
|
||||
* If needed, edit `OnCalendar` in `/usr/lib/systemd/system/restic-backup@.timer`.
|
||||
1. Enable automated backup for starting with the system & make the first backup:
|
||||
```console
|
||||
$ journalctl -f --lines=50 -u restic-backup@default
|
||||
# systemctl enable --now restic-backup@default.timer
|
||||
```
|
||||
1. Watch the first backup progress with Systemd journal:
|
||||
```console
|
||||
# journalctl -f --lines=50 -u restic-backup@default
|
||||
```
|
||||
1. Verify the backup
|
||||
```console
|
||||
# restic snapshots
|
||||
```
|
||||
1. (recommended) Enable the check job that verifies that the backups for the profile are all intact.
|
||||
```console
|
||||
# systemctl enable --now restic-check@default.timer
|
||||
````
|
||||
1. (optional) Define multiple profiles: just make a copy of the `default.env.sh` and use the defined profile name in place of `default` to run backups or enable timers. Notice that the value after `@` works as a parameter.
|
||||
```console
|
||||
# systemctl enable restic-backup@other_profile.timer
|
||||
```
|
||||
1. Consider more [optional features](#optional-features).
|
||||
|
||||
|
||||
## Setup macOS LaunchAgent
|
||||
<img height="64" width="64" src="https://unpkg.com/simple-icons@v6/icons/apple.svg" />
|
||||
|
||||
☝ **Note** The macOS setup here will assume an installation to `/usr/local`, as [custom](https://docs.brew.sh/FAQ#why-does-homebrew-say-sudo-is-bad) with Homebrew installations.
|
||||
|
||||
[Launchd](https://www.launchd.info/) is the modern built-in service scheduler in macOS. It has support for running services as root (Daemon) or as a normal user (Agent). Here we set up an LauchAgent to be run as your normal user for starting regular backups.
|
||||
|
||||
**TL;DR setup**
|
||||
1. [Create](#1-create-backblaze-b2-account-bucket-and-keys) B2 bucket + credentials
|
||||
1. Install scripts, configs and LaunchAgent:
|
||||
* (recommended) with Homebrew from the [erikw/homebrew-tap](https://github.com/erikw/homebrew-tap):
|
||||
```console
|
||||
$ brew install erikw/tap/restic-automatic-backup-scheduler
|
||||
```
|
||||
* Using `make`:
|
||||
```console
|
||||
$ make PREFIX=/usr/local install-launchagent
|
||||
```
|
||||
1. Fill out [configuration values](#2-configure-b2-credentials-locally) in `/usr/local/etc/restic`.
|
||||
1. [Initialize](#3-initialize-remote-repo) the remote repo.
|
||||
Source the profile to make all needed configuration available to `restic(1)`. All commands after this assumes the profile is sourced in the current shell.
|
||||
```console
|
||||
$ source /usr/local/etc/restic/default.env.sh
|
||||
$ restic init
|
||||
```
|
||||
1. Configure [how often](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/ScheduledJobs.html#//apple_ref/doc/uid/10000172i-CH1-SW1) backups should be done. If needed, edit `OnCalendar` in
|
||||
* Homebrew install: `~/Library/LaunchAgents/homebrew.mxcl.restic-automatic-backup-scheduler.plist`.
|
||||
* `make` install: `~/Library/LaunchAgents/com.github.erikw.restic-backup.plist`.
|
||||
1. Enable automated backup for starting with the system & make the first backup:
|
||||
* Homebrew install:
|
||||
```console
|
||||
$ brew services start restic-automatic-backup-scheduler
|
||||
```
|
||||
* `make` install:
|
||||
```console
|
||||
$ launchctl bootstrap gui/$UID ~/Library/LaunchAgents/com.github.erikw.restic-backup.plist
|
||||
$ launchctl enable gui/$UID/com.github.erikw.restic-backup
|
||||
$ launchctl kickstart -p gui/$UID/com.github.erikw.restic-backup
|
||||
```
|
||||
As a convenience, a shortcut for the above commands are `$ make activate-launchagent-backup`.
|
||||
1. Watch the first backup progress from the log files:
|
||||
```console
|
||||
$ tail -f ~/Library/Logs/restic/backup*
|
||||
```
|
||||
1. Verify the backup
|
||||
```console
|
||||
$ sudo -i
|
||||
$ source /etc/restic/default.env.sh
|
||||
$ restic snapshots
|
||||
```
|
||||
1. (optional) Define multiple profiles: just make a copy of the `default.env.sh` and use the defined profile name in place of `default` to run backups or enable timers. Notice that the value after `@` works as a parameter.
|
||||
1. (optional) Enable the check job that verifies that the backups for the profile are all intact.
|
||||
```console
|
||||
$ sudo systemctl enable --now restic-check@default.timer
|
||||
````
|
||||
1. (optional) Setup email on failure as described [here](#8-email-notification-on-failure)
|
||||
|
||||
|
||||
### Step-by-step and manual setup
|
||||
This is a more detailed explanation than the TL;DR section that will give you more understanding in the setup, and maybe inspire you to develop your own setup based on this one even!
|
||||
|
||||
Tip: The steps in this section will instruct you to copy files from this repo to system directories. If you don't want to do this manually, you can use the Makefile:
|
||||
1. (recommended) Enable the check job that verifies that the backups for the profile are all intact.
|
||||
* Homebrew install:
|
||||
```console
|
||||
$ brew services start restic-automatic-backup-scheduler-check
|
||||
```
|
||||
* `make` install:
|
||||
```console
|
||||
$ launchctl bootstrap gui/$UID ~/Library/LaunchAgents/com.github.erikw.restic-check.plist
|
||||
$ launchctl enable gui/$UID/com.github.erikw.restic-check
|
||||
$ launchctl kickstart -p gui/$UID/com.github.erikw.restic-check
|
||||
```
|
||||
As a convenience, a shortcut for the above commands are `$ make activate-launchagent-check`.
|
||||
1. Consider more [optional features](#optional-features).
|
||||
|
||||
### Homebrew Setup Notes
|
||||
Then control the service with homebrew:
|
||||
```console
|
||||
$ git clone https://github.com/erikw/restic-systemd-automatic-backup.git && cd $(basename "$_" .git)
|
||||
$ sudo make install-systemd
|
||||
$ brew services start restic-automatic-backup-scheduler
|
||||
$ brew services restart restic-automatic-backup-scheduler
|
||||
$ brew services stop restic-automatic-backup-scheduler
|
||||
```
|
||||
|
||||
If `services start` fails, it might be due to previous version installed. In that case remove the existing version and try again:
|
||||
```console
|
||||
$ launchctl bootout gui/$UID/com.github.erikw.restic-backup
|
||||
$ brew services start restic-automatic-backup-scheduler
|
||||
```
|
||||
|
||||
### Make Setup Notes
|
||||
Use the `disable` command to temporarily pause the agent, or `bootout` to uninstall it.
|
||||
```
|
||||
$ launchctl disable gui/$UID/com.github.erikw.restic-backup
|
||||
$ launchctl bootout gui/$UID/com.github.erikw.restic-backup
|
||||
```
|
||||
|
||||
If you updated the `.plist` file, you need to issue the `bootout` followed by `bootrstrap` and `enable` sub-commands of `launchctl`. This will guarantee that the file is properly reloaded.
|
||||
|
||||
|
||||
|
||||
## Setup Windows ScheduledTask
|
||||
<img height="64" width="64" src="https://unpkg.com/simple-icons@v6/icons/windows.svg" />
|
||||
|
||||
Windows comes with a built-in task scheduler called [ScheduledTask](https://docs.microsoft.com/en-us/powershell/module/scheduledtasks/new-scheduledtask?view=windowsserver2022-ps). The frontend app is "Task Scheduler" (`taskschd.msc`) and we can use PowerShell commands to install a new scheduled task.
|
||||
|
||||
I describe here one of may ways you can get restic and this backup script working on Windows. Here I chose to work with `scoop` and `git-bash`.
|
||||
|
||||
|
||||
**TL;DR setup**
|
||||
1. Install [scoop](https://scoop.sh/)
|
||||
1. Install dependencies from a PowerShell with *administrator privileges*:
|
||||
```console
|
||||
powershell> scoop install restic make git
|
||||
```
|
||||
1. In a *non-privileged* PowerShell, start git-bash and clone this repo
|
||||
```console
|
||||
powershell> git-bash
|
||||
git-bash$ mkdir ~/src && cd ~/src/
|
||||
git-bash$ git clone https://github.com/erikw/restic-automatic-backup-scheduler.git && cd $(basename "$_" .git)
|
||||
```
|
||||
1. Install scripts, configs and ScheduledTasks
|
||||
```console
|
||||
git-bash$ make install-schedtask
|
||||
```
|
||||
1. Fill out [configuration values](#2-configure-b2-credentials-locally) in `/etc/restic`.
|
||||
```console
|
||||
git-bash$ vim /etc/restic/*
|
||||
```
|
||||
Note that you should use cygwin/git-bash paths. E.g. in `default.env.sh` you could have
|
||||
```bash
|
||||
export RESTIC_BACKUP_PATHS='/c/Users/<username>/My Documents'
|
||||
```
|
||||
1. [Initialize](#3-initialize-remote-repo) the remote repo.
|
||||
Source the profile to make all needed configuration available to `restic(1)`. All commands after this assumes the profile is sourced in the current shell.
|
||||
```console
|
||||
git-bash$ source /etc/restic/default.env.sh
|
||||
git-bash$ restic init
|
||||
```
|
||||
1. Make the first backup
|
||||
```console
|
||||
git-bash$ restic_backup.sh
|
||||
```
|
||||
1. Verify the backup
|
||||
```console
|
||||
git-bash$ restic snapshots
|
||||
```
|
||||
1. Inspect the installed ScheduledTasks and make a test run
|
||||
1. Open the app "Task Scheduler" (`taskschd.msc`)
|
||||
1. Go to the local "Task Scheduler Library"
|
||||
1. Right click on one of the newly installed tasks e.g. `restic_backup` and click "run".
|
||||
- If the tasks are not there, maybe you opended it up before `make install-schedtask`: just close and start it again to refresh.
|
||||
1. Now a git-bash window should open running `restic_backup.sh`, and the next time the configured schedule hits!
|
||||
1. Consider more [optional features](#optional-features).
|
||||
|
||||
|
||||
With `taskschd.msc` you can easily start, stop, delete and configure the scheduled tasks to your liking:
|
||||
<a href="img/tasksched.png" title="Windows Task Scheduler"><img src="img/tasksched.png" width="512" alt="Windows Task Schedulder"></a>
|
||||
|
||||
|
||||
## Setup Cron
|
||||
<img height="64" width="64" src="https://unpkg.com/simple-icons@v6/icons/clockify.svg" />
|
||||
|
||||
☝ **Note** There are many different cron [implementations](https://wiki.archlinux.org/title/Cron) out there and they all work slightly different.
|
||||
|
||||
Any system that has a cron-like system can easily setup restic backups as well. However if you system supports any of the previous setups, those are recommended over cron as they provide more features and reliability for your backups.
|
||||
|
||||
|
||||
|
||||
**TL;DR setup**
|
||||
1. [Create](#1-create-backblaze-b2-account-bucket-and-keys) B2 bucket + credentials
|
||||
1. Install scripts, configs systemd units/timers:
|
||||
```console
|
||||
$ sudo make install-cron
|
||||
```
|
||||
* This assumes that your cron supports dropping files into `/etc/cron.d/`. If that is not the case, simply copy the relevant contents of the installed `/etc/cron.d/restic` in to your `/etc/crontab`.
|
||||
```console
|
||||
# grep "^@.*restic_" /etc/cron.d/restic >> /etc/crontab
|
||||
```
|
||||
1. Fill out [configuration values](#2-configure-b2-credentials-locally) in `/etc/restic`.
|
||||
1. [Initialize](#3-initialize-remote-repo) the remote repo.
|
||||
Source the profile to make all needed configuration available to `restic(1)`. All commands after this assumes the profile is sourced in the current shell.
|
||||
```console
|
||||
# source /etc/restic/default.env.sh
|
||||
# restic init
|
||||
```
|
||||
1. Make the first backup
|
||||
```console
|
||||
# restic_backup.sh
|
||||
```
|
||||
1. Verify the backup
|
||||
```console
|
||||
# restic snapshots
|
||||
```
|
||||
1. Configure [how often](https://crontab.guru/) backups should be done by directly editing `/etc/cron.d/restic` (or `/etc/crontab`).
|
||||
1. Consider more [optional features](#optional-features).
|
||||
|
||||
|
||||
## Detailed Manual Setup
|
||||
<img height="64" width="64" src="img/pen-paper.png" />
|
||||
|
||||
This is a more detailed explanation than the TL;DR sections above that will give you more understanding in the setup. This section is more general, but uses Linux + Systemd as the example setup.
|
||||
|
||||
#### 0. Clone Repo
|
||||
```console
|
||||
$ git clone https://github.com/erikw/restic-automatic-backup-scheduler.git && cd $(basename "$_" .git)
|
||||
````
|
||||
|
||||
If you want to install everything manually, we will install files to `/etc`, `/bin`, and not use the `$make install-systemd` command, then you need to clean up a placeholder `$INSTALL_PREFIX` in the souce files first by running:
|
||||
Make a quick search-and-replace in the source files:
|
||||
```console
|
||||
$ find etc bin -type f -exec sed -i.bak -e 's|$INSTALL_PREFIX||g' {} \; -exec rm {}.bak \;
|
||||
```
|
||||
@@ -113,41 +309,45 @@ and you should now see that all files have been changed like e.g.
|
||||
-export RESTIC_PASSWORD_FILE="$INSTALL_PREFIX/etc/restic/pw.txt"
|
||||
+export RESTIC_PASSWORD_FILE="/etc/restic/pw.txt"
|
||||
```
|
||||
This prefix is there so that `make` users can set a different `$PREFIX` when installing like `PREFIX=/usr/local make install-systemd`. So if we don't use the makefile, we need to remove this prefix with the command above just.
|
||||
|
||||
Why? The OS specific TL;DR setups above all use the [Makefile](Makefile) or a package manager to install these files. The placeholder string `$INSTALL_PREFIX` is in the source files for portability reasons, so that the Makefile can support all different operating systems. `make` users can set a different `$PREFIX` when installing like `PREFIX=/usr/local make install-systemd`.
|
||||
|
||||
In this detailed manual setup we will copy all files manually to `/etc`and `/bin`. Thus we need to remove the placeholder string `$INSTALL_PREFIX` in the source files as a first step.
|
||||
|
||||
|
||||
Arch Linux users can install the aur package [restic-systemd-automatic-backup](https://aur.archlinux.org/packages/restic-systemd-automatic-backup/) e.g.:
|
||||
```console
|
||||
$ yaourt -S restic-systemd-automatic-backup
|
||||
````
|
||||
#### 1. Create Backblaze B2 Account, Bucket and Keys
|
||||
In short:
|
||||
1. Create a [Backblaze](https://www.backblaze.com/) account (use 2FA!).
|
||||
1. Create a new [B2 bucket](https://secure.backblaze.com/b2_buckets.htm).
|
||||
* Private, without B2 encryption and without the object lock feature
|
||||
1. Create a pair of [keyId and applicationKey](https://secure.backblaze.com/app_keys.htm?bznetid=17953438771644852981527)
|
||||
* Limit scope of the new id and key pair to only the above created bucket.
|
||||
|
||||
#### 1. Create Backblaze B2 Account, Bucket and keys
|
||||
First, see this official Backblaze [tutorial](https://help.backblaze.com/hc/en-us/articles/4403944998811-Quickstart-Guide-for-Restic-and-Backblaze-B2-Cloud-Storage) on restic, and follow the instructions ("Create Backblaze account with B2 enabled") there on how to create a new B2 bucket. In general, you'd want a private bucket, without B2 encryption (restic does the encryption client side for us) and without the object lock feature.
|
||||
|
||||
For restic to be able to connect to your bucket, you want to in the B2 settings create a pair of keyID and applicationKey. It's a good idea to create a separate pair of ID and Key with for each bucket that you will use, with limited read&write access to only that bucket.
|
||||
|
||||
|
||||
#### 2. Configure your B2 credentials locally
|
||||
> **Attention!** Going the manual way requires that most of the following commands are run as root.
|
||||
|
||||
#### 2. Configure B2 Credentials Locally
|
||||
Put these files in `/etc/restic/`:
|
||||
* `_global.env.sh`: Fill this file out with your global settings including B2 keyID & applicationKey. A global exclude list is set here (explained in section below).
|
||||
* `_global.env.sh`: Fill this file out with your global settings including B2 keyID & applicationKey.
|
||||
* `default.env.sh`: This is the default profile. Fill this out with bucket name, backup paths and retention policy. This file sources `_global.env.sh` and is thus self-contained and can be sourced in the shell when you want to issue some manual restic commands. For example:
|
||||
```console
|
||||
$ source /etc/restic/default.env.sh
|
||||
$ restic snapshots # You don't have to supply all parameters like --repo, as they are now in your environment!
|
||||
````
|
||||
* `pw.txt`: This file should contain the restic password used to encrypt the repository. This is a new password what soon will be used when initializing the new repository. It should be unique to this restic backup repository and is needed for restoring from it. Don't re-use your B2 login password, this should be different. For example you can generate a 128 character password (must all be on one line) with:
|
||||
* `pw.txt`: This file should contain the restic password (single line) used to encrypt the repository. This is a new password what soon will be used when initializing the new repository. It should be unique to this restic backup repository and is needed for restoring from it. Don't re-use your B2 login password, this should be different. For example you can generate a 128 character password (must all be on one line) with:
|
||||
```console
|
||||
$ openssl rand -base64 128 | tr -d '\n' > /etc/restic/pw.txt
|
||||
```
|
||||
* `backup_exclude.txt`: List of file patterns to ignore. This will trim down your backup size and the speed of the backup a lot when done properly!
|
||||
|
||||
#### 3. Initialize remote repo
|
||||
Now we must initialize the repository on the remote end:
|
||||
```console
|
||||
$ sudo -i
|
||||
$ source /etc/restic/default.env.sh
|
||||
$ restic init
|
||||
# source /etc/restic/default.env.sh
|
||||
# restic init
|
||||
```
|
||||
|
||||
#### 4. Script for doing the backup
|
||||
@@ -162,27 +362,24 @@ Restic support exclude files. They list file pattern paths to exclude from you b
|
||||
Now see if the backup itself works, by running as root
|
||||
|
||||
```console
|
||||
$ sudo -i
|
||||
$ source /etc/restic/default.env.sh
|
||||
$ /bin/restic_backup.sh
|
||||
# source /etc/restic/default.env.sh
|
||||
# /bin/restic_backup.sh
|
||||
````
|
||||
|
||||
#### 6. Verify the backup
|
||||
As the `default.env.sh` is already sourced in your root shell, you can now just list the snapshos
|
||||
As the `default.env.sh` is already sourced in your root shell, you can now just list the snapshost
|
||||
```console
|
||||
$ sudo -i
|
||||
$ source /etc/restic/default.env.sh
|
||||
$ restic snapshots
|
||||
# restic snapshots
|
||||
```
|
||||
|
||||
Alternatively you can mount the restic snapshots to a directory set `/mnt/restic`
|
||||
```console
|
||||
$ restic mount /mnt/restic
|
||||
$ ls /mnt/restic
|
||||
# restic mount /mnt/restic
|
||||
# ls /mnt/restic
|
||||
```
|
||||
|
||||
#### 7. Backup automatically; systemd service + timer
|
||||
Now we can do the modern version of a cron-job, a systemd service + timer, to run the backup every day!
|
||||
#### 7. Backup automatically
|
||||
All OS setups differs in what task scheduler they use. As a demonstration, let's look at how we can do this with systemd under Linux here.
|
||||
|
||||
Put these files in `/etc/systemd/system` (note that the Makefile installs as package to `/usr/lib/systemd/system`)
|
||||
* `restic-backup@.service`: A service that calls the backup script with the specified profile. The profile is specified
|
||||
@@ -192,39 +389,84 @@ Put these files in `/etc/systemd/system` (note that the Makefile installs as pac
|
||||
|
||||
Now simply enable the timer with:
|
||||
```console
|
||||
$ sudo systemctl enable --now restic-backup@default.timer
|
||||
# systemctl enable --now restic-backup@default.timer
|
||||
````
|
||||
|
||||
☝ **Note**: You can run it with different values instead of `default` if you use multiple profiles.
|
||||
|
||||
You can see when your next backup is scheduled to run with
|
||||
```console
|
||||
$ systemctl list-timers | grep restic
|
||||
# systemctl list-timers | grep restic
|
||||
```
|
||||
|
||||
and see the status of a currently running backup with
|
||||
|
||||
and see the status of a currently running backup with:
|
||||
```console
|
||||
$ systemctl status restic-backup
|
||||
# systemctl status restic-backup
|
||||
```
|
||||
|
||||
or start a backup manually
|
||||
|
||||
or start a backup manually:
|
||||
```console
|
||||
$ systemctl start restic-backup@default
|
||||
```
|
||||
|
||||
You can follow the backup stdout output live as backup is running with:
|
||||
|
||||
```console
|
||||
$ journalctl -f -u restic-backup@default.service
|
||||
````
|
||||
|
||||
(skip `-f` to see all backups that has run)
|
||||
|
||||
|
||||
#### Recommended: Automated Backup Checks
|
||||
Once in a while it can be good to do a health check of the remote repository, to make sure it's not getting corrupt. This can be done with `$ restic check`.
|
||||
|
||||
#### 8. Email notification on failure
|
||||
There is companion scripts, service and timer (`*check*`) to restic-backup.sh that checks the restic backup for errors; look in the repo in `usr/lib/systemd/system/` and `bin/` and copy what you need over to their corresponding locations.
|
||||
|
||||
```console
|
||||
# systemctl enable --now restic-check@default.timer
|
||||
````
|
||||
|
||||
|
||||
## Optional Features
|
||||
<img height="64" width="64" src="img/plus.png" />
|
||||
|
||||
### Optional: Multiple profiles
|
||||
To have different backup jobs having e.g. different buckets, backup path of schedule, just make a copy of the `default.env.sh` and use the defined profile name in place of `default` in the previous steps.
|
||||
|
||||
To create a different backup and use you can do:
|
||||
```console
|
||||
# cp /etc/restic/default.env.sh /etc/restic/other.env.sh
|
||||
# vim /etc/restic/default.other.sh # Set backup path, bucket etc.
|
||||
# source /etc/restic/default.other.sh
|
||||
# restic_backup.sh
|
||||
```
|
||||
|
||||
### Optional: Desktop Notifications
|
||||
<img src="img/macos_notification.png" align="right" />
|
||||
|
||||
It's a good idea to be on top of your backups to make sure that they don't increase a lot in size and incur high costs. However it's notoriously tricky to make GUI notifications correctly from a non-user process (e.g. root).
|
||||
|
||||
Therefore this project provides a lightweight solution for desktop notifications that works like this: Basically `restic_backup.sh` will append a summary line of the last backup to a user-owned file (the user running your OS's desktop environment) in a fire-and-forget fashion. Then the user has a process that reads this and forward each line as a new message to the desktop environment in use.
|
||||
|
||||
To set desktop notifications up:
|
||||
1. Create a special FIFO file as your desktop user:
|
||||
```console
|
||||
$ mkfifo /home/user/.cache/notification-queue
|
||||
```
|
||||
1. In your profile, e.g. `/etc/restic/default.sh`, set:
|
||||
```bash
|
||||
RESTIC_NOTIFY_BACKUP_STATS=true
|
||||
RESTIC_BACKUP_NOTIFICATION_FILE=/home/user/.cache/notification-queue
|
||||
```
|
||||
1. Create a listener on the notification queue file that forwards to desktop notifications
|
||||
* Linux auto start + cross-platform notifier / notify-send
|
||||
* [notification-queue-notifier](https://github.com/gerardbosch/dotfiles/blob/ddc1491056822eab45dedd131f1946308ef62135/home/bin/notification-queue-notifier)
|
||||
* [notification-queue.desktop](https://github.com/gerardbosch/dotfiles-linux/blob/ea0f75bfd7a356945544ecaa42a2fc35c9fab3a1/home/.config/autostart/notification-queue.desktop)
|
||||
* macOS auto start + [terminal-notifier](https://github.com/julienXX/terminal-notifier)
|
||||
* [notification-queue-notifier.sh](https://github.com/erikw/dotfiles/blob/8a942defe268292200b614951cdf433ddccf7170/bin/notification-queue-notifier.sh)
|
||||
* [com.user.notificationqueue.plist](https://github.com/erikw/dotfiles/blob/8a942defe268292200b614951cdf433ddccf7170/.config/LaunchAgents/com.user.notificationqueue.plist)
|
||||
|
||||
|
||||
|
||||
### Optional: Email Notification on Failure
|
||||
#### Systemd
|
||||
We want to be aware when the automatic backup fails, so we can fix it. Since my laptop does not run a mail server, I went for a solution to set up my laptop to be able to send emails with [postfix via my Gmail](https://easyengine.io/tutorials/linux/ubuntu-postfix-gmail-smtp/). Follow the instructions over there.
|
||||
|
||||
Put this file in `/bin`:
|
||||
@@ -233,85 +475,71 @@ Put this file in `/bin`:
|
||||
Put this files in `/etc/systemd/system/`:
|
||||
* `status-email-user@.service`: A service that can notify you via email when a systemd service fails. Edit the target email address in this file.
|
||||
|
||||
As you maybe noticed already before, `restic-backup.service` is configured to start `status-email-user.service` on failure.
|
||||
Now edit `restic-backup@.service` and `status-email-user@.service` to call this service failure.
|
||||
```
|
||||
OnFailure=status-email-user@%n.service
|
||||
```
|
||||
#### Cron
|
||||
Use `bin/cron_mail`: A wrapper for running cron jobs, that sends output of the job as an email using the mail(1) command. This assumes that the `mail` program is correctly setup on the system to send emails.
|
||||
|
||||
To use this, wrap the restic script command with it in your cron file like:
|
||||
```diff
|
||||
-@midnight root . /etc/restic/default.sh && restic_backup.sh
|
||||
+@midnight root . /etc/restic/default.sh && cron_mail restic_backup.sh
|
||||
```
|
||||
|
||||
|
||||
#### 9. Optional: automated backup checks
|
||||
Once in a while it can be good to do a health check of the remote repository, to make sure it's not getting corrupt. This can be done with `$ restic check`.
|
||||
### Optional: No Backup on Metered Connections (Linux/systemd only)
|
||||
For a laptop, it can make sense to not do heavy backups when your on a metered connection like a shared connection from you mobile phone. To solve this we can set up a systemd service that is in success state only when a connection is unmetered. Then we can tell our backup service to depend on this service simply! When the unmetered service detects an unmetered connection it will go to failed state. Then our backup service will not run as it requires this other service to be in success state.
|
||||
|
||||
There is companion scripts, service and timer (`*check*`) to restic-backup.sh that checks the restic backup for errors; look in the repo in `usr/lib/systemd/system/` and `bin/` and copy what you need over to their corresponding locations.
|
||||
1. Edit `restic-backup@.service` and `restic-check@.service` to require the new service to be in success state:
|
||||
```
|
||||
Requires=nm-unmetered-connection.service
|
||||
```
|
||||
1. Copy and paste the command below, it will install the following files and refresh systemd daemon:
|
||||
1. Put this file in `/etc/systemd/system/`:
|
||||
* `nm-unmetered-connection.service`: A service that is in success state only if the connection is unmetered.
|
||||
1. Install this file in `/bin`:
|
||||
* `nm-unmetered-connection.sh`: Detects metered connections and returns an error code if one is detected. This scripts requires the Gnome [NetworkManager](https://wiki.gnome.org/Projects/NetworkManager) to be installed (modify this script if your system has a different network manager).
|
||||
1. Reload systemd with
|
||||
```console
|
||||
# systemctl daemon-reload
|
||||
```
|
||||
|
||||
```console
|
||||
$ sudo systemctl enable --now restic-check@default.timer
|
||||
````
|
||||
☝ **Tip**: All steps but the first can be done in one go if you use the Makefile. Set `$PREFIX` as needed or leave empty for install to `/`.
|
||||
```bash
|
||||
sudo bash -c 'export PREFIX=
|
||||
make build/usr/lib/systemd/system/nm-unmetered-connection.service
|
||||
install -m 0644 build/usr/lib/systemd/system/nm-unmetered-connection.service $PREFIX/etc/systemd/system
|
||||
install -m 0555 bin/nm-unmetered-connection.sh /bin
|
||||
systemctl daemon-reload
|
||||
'
|
||||
```
|
||||
|
||||
#### 10. Optional: 🏃 Restic wrapper
|
||||
### Optional: Restic Wrapper Script
|
||||
For convenience there's a `restic` wrapper script that makes loading profiles and **running restic**
|
||||
straightforward (it needs to run with sudo to read environment). Just run:
|
||||
|
||||
- `sudo resticw WHATEVER` (e.g. `sudo resticw snapshots`) to use the default profile.
|
||||
- You can run the wrapper by passing a specific profile: `resticw -p anotherprofile snapshots`.
|
||||
|
||||
##### Useful commands
|
||||
* `sudo resticw WHATEVER` (e.g. `sudo resticw snapshots`) to use the default profile.
|
||||
* You can run the wrapper by passing a specific profile: `resticw -p anotherprofile snapshots`.
|
||||
|
||||
Useful commands:
|
||||
| Command | Description |
|
||||
|---------------------------------------------------|-------------------------------------------------------------------|
|
||||
| `resticw snapshots` | List backup snapshots |
|
||||
| `resticw diff <snapshot-id> latest` | Show the changes from the latest backup |
|
||||
| `resticw stats` / `resticw stats snapshot-id ...` | Show the statistics for the whole repo or the specified snapshots |
|
||||
| `resticw diff <snapshotId-1> <snapshotId-2>` | Show the changes between backup snapshots |
|
||||
| `resticw stats` / `resticw stats snapshotId ...` | Show the statistics for the whole repo or the specified snapshots |
|
||||
| `resticw mount /mnt/restic` | Mount your remote repository |
|
||||
|
||||
## Setup macOS LaunchAgent
|
||||
LaunchAgent is the modern service scheduler in in macOS that uses [Launchd](https://www.launchd.info/).
|
||||
[Launchd](https://www.launchd.info/) is the modern built-in service scheduler in macOS. It has support for running services as root (Daemon) or as a normal user (Agent). Here we set up an LauchAgent to be run as your normal user for starting regular backups.
|
||||
|
||||
1. In general, follow the same setup as in (#setup-linux-systemd) except for:
|
||||
* use `make install-launchagent` instead of `make install-systemd`
|
||||
* install everything to `/usr/local` and run restic as your own user, not root
|
||||
* Thus, install with
|
||||
```console
|
||||
$ PREFIX=/usr/local make install-launchagent
|
||||
```
|
||||
1. After installation with `make` , edit the installed LaunchAgent if you want to change the default schedule or profile used:
|
||||
```console
|
||||
$ vim ~/Library/LaunchAgents/com.github.erikw.restic-automatic-backup.plist
|
||||
```
|
||||
1. Now install, enable and start the first run!
|
||||
```console
|
||||
$ launchctl bootstrap gui/$UID ~/Library/LaunchAgents/com.github.erikw.restic-automatic-backup.plist
|
||||
$ launchctl enable gui/$UID/com.github.erikw.restic-automatic-backup
|
||||
$ launchctl kickstart -p gui/$UID/com.github.erikw.restic-automatic-backup
|
||||
```
|
||||
As a convenience, a shortcut for the above commands are `$ make activate-launchagent`.
|
||||
|
||||
Use the `disable` command to temporarily pause the agent, or `bootout` to uninstall it.
|
||||
```
|
||||
$ launchctl disable gui/$UID/com.github.erikw.restic-automatic-backup
|
||||
$ launchctl bootout gui/$UID/com.github.erikw.restic-automatic-backup
|
||||
```
|
||||
|
||||
If you updated the `.plist` file, you need to issue the `bootout` followed by `bootrstrap` and `enable` sub-commands of `launchctl`. This will guarantee that the file is properly reloaded.
|
||||
|
||||
## Setup Cron
|
||||
If you want to run an all-classic cron job instead, do like this:
|
||||
|
||||
1. Follow the main setup from [Step-by-step and manual setup](#step-by-step-and-manual-setup) but skip the systemd parts.
|
||||
1. `etc/cron.d/restic`: Depending on your system's cron, put this in `/etc/cron.d/` or similar, or copy the contents to $(sudo crontab -e). The format of this file is tested under FreeBSD, and might need adaptions depending on your cron.
|
||||
* You can use `$ make install-cron` to copy it over to `/etc/cron.d`.
|
||||
1. (Optional) `bin/cron_mail`: A wrapper for running cron jobs, that sends output of the job as an email using the mail(1) command.
|
||||
|
||||
|
||||
# Uninstall
|
||||
There is a make target to remove all files (scripts and configs) that were installed by `sudo make install-*`. Just run:
|
||||
There is a make target to remove all files (scripts and **configs)** that were installed by `sudo make install-*`. Just run:
|
||||
|
||||
```console
|
||||
$ sudo make uninstall
|
||||
```
|
||||
|
||||
# Variations
|
||||
A list of variations of this setup:
|
||||
* Using `--files-from` [#44](https://github.com/erikw/restic-systemd-automatic-backup/issues/44)
|
||||
|
||||
# Development
|
||||
* To not mess up your real installation when changing the `Makefile` simply install to a `$PREFIX` like
|
||||
```console
|
||||
@@ -325,10 +553,13 @@ A list of variations of this setup:
|
||||
|
||||
# Releasing
|
||||
To make a new release:
|
||||
1.
|
||||
1. Create a new tag:
|
||||
```console
|
||||
$ vi CHANGELOG.md && git commit -am "Update CHANGELOG.md"
|
||||
$ git tag vX.Y.Z
|
||||
$ git push && git push --tags
|
||||
```
|
||||
1. Test and update the AUR [PKGBUILD](https://aur.archlinux.org/packages/restic-systemd-automatic-backup/) if needed.
|
||||
1. Update version in the AUR [PKGBUILD](https://aur.archlinux.org/packages/restic-automatic-backup-scheduler/)
|
||||
1. Update version in the Homebrew Formulas (see the repo README):
|
||||
* [restic-automatic-backup-scheduler](https://github.com/erikw/homebrew-tap/blob/main/Formula/restic-automatic-backup-scheduler.rb)
|
||||
* [restic-automatic-backup-scheduler-check](https://github.com/erikw/homebrew-tap/blob/main/Formula/restic-automatic-backup-scheduler-check.rb)
|
||||
|
||||
19
ScheduledTask/install.ps1
Normal file
19
ScheduledTask/install.ps1
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# Install restic scheduled tasks.
|
||||
# Test run the installed actions by
|
||||
# 1. open the app "Task Scheduler" (taskschd.msc)
|
||||
# 2. go to the local "Task Scheduler Library"
|
||||
# 3. right click on the new tasks and click "run".
|
||||
# Reference: https://blogs.technet.microsoft.com/heyscriptingguy/2015/01/13/use-powershell-to-create-scheduled-tasks/
|
||||
# Reference: https://www.davidjnice.com/cygwin_scheduled_tasks.html
|
||||
|
||||
|
||||
# Install restic_backup.sh
|
||||
$action = New-ScheduledTaskAction -Execute "$(scoop prefix git)\git-bash.exe" -Argument '-l -c "source $INSTALL_PREFIX/etc/restic/default.env.sh && $INSTALL_PREFIX/bin/restic_backup.sh"'
|
||||
$trigger = New-ScheduledTaskTrigger -Daily -At 7pm
|
||||
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "restic_backup" -Description "Daily backup to B2 with restic."
|
||||
|
||||
# Install restic_check.sh
|
||||
$action = New-ScheduledTaskAction -Execute "$(scoop prefix git)\git-bash.exe" -Argument '-l -c "source $INSTALL_PREFIX/etc/restic/default.env.sh && /INSTALL_PREFIX/bin/restic_check.sh"'
|
||||
$trigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 4 -DaysOfWeek Sunday -At 8pm -RandomDelay 128
|
||||
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "restic_check" -Description "Check B2 backups with restic."
|
||||
5
ScheduledTask/uninstall.ps1
Normal file
5
ScheduledTask/uninstall.ps1
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# Uninstall restic scheduled tasks.
|
||||
|
||||
Unregister-ScheduledTask -TaskName "restic_backup" -Confirm:$false
|
||||
Unregister-ScheduledTask -TaskName "restic_check" -Confirm:$false
|
||||
0
bin/cron_mail
Executable file → Normal file
0
bin/cron_mail
Executable file → Normal file
@@ -1,19 +1,19 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# Requires Gnome NetworkManager
|
||||
|
||||
systemctl is-active dbus.service >/dev/null 2>&1 || exit 0
|
||||
systemctl is-active NetworkManager.service >/dev/null 2>&1 || exit 0
|
||||
|
||||
metered_status=$(dbus-send --system --print-reply=literal \
|
||||
--system --dest=org.freedesktop.NetworkManager \
|
||||
/org/freedesktop/NetworkManager \
|
||||
org.freedesktop.DBus.Properties.Get \
|
||||
string:org.freedesktop.NetworkManager string:Metered \
|
||||
| grep -o ".$")
|
||||
--system --dest=org.freedesktop.NetworkManager \
|
||||
/org/freedesktop/NetworkManager \
|
||||
org.freedesktop.DBus.Properties.Get \
|
||||
string:org.freedesktop.NetworkManager string:Metered \
|
||||
| grep -o ".$")
|
||||
|
||||
if [[ $metered_status =~ (1|3) ]]; then
|
||||
echo Current connection is metered
|
||||
exit 1
|
||||
else
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ assert_envvars() {
|
||||
local varnames=("$@")
|
||||
for varname in "${varnames[@]}"; do
|
||||
if [ -z ${!varname+x} ]; then
|
||||
printf "%s must be set for this script to work.\n\nDid you forget to source a /etc/restic/*.env.sh profile in the current shell before executing this script?\n" "$varname" >&2
|
||||
printf "%s must be set for this script to work.\n\nDid you forget to source a $INSTALL_PREFIX/etc/restic/*.env.sh profile in the current shell before executing this script?\n" "$varname" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -57,6 +57,10 @@ for backup_path in "${backup_paths[@]}"; do
|
||||
fi
|
||||
done
|
||||
|
||||
# --one-file-system is not supportd on Windows (=msys).
|
||||
FS_ARG=
|
||||
test "$OSTYPE" = msys || FS_ARG=--one-file-system
|
||||
|
||||
# NOTE start all commands in background and wait for them to finish.
|
||||
# Reason: bash ignores any signals while child process is executing and thus the trap exit hook is not triggered.
|
||||
# However if put in subprocesses, wait(1) waits until the process finishes OR signal is received.
|
||||
@@ -72,7 +76,7 @@ wait $!
|
||||
# --tag lets us reference these backups later when doing restic-forget.
|
||||
restic backup \
|
||||
--verbose="$RESTIC_VERBOSITY_LEVEL" \
|
||||
--one-file-system \
|
||||
$FS_ARG \
|
||||
--tag "$RESTIC_BACKUP_TAG" \
|
||||
--option b2.connections="$B2_CONNECTIONS" \
|
||||
"${exclusion_args[@]}" \
|
||||
@@ -101,3 +105,24 @@ wait $!
|
||||
#wait $!
|
||||
|
||||
echo "Backup & cleaning is done."
|
||||
|
||||
# (optionally) Notify about backup summary stats.
|
||||
if [ "$RESTIC_NOTIFY_BACKUP_STATS" = true ]; then
|
||||
if [ -w "$RESTIC_BACKUP_NOTIFICATION_FILE" ]; then
|
||||
echo 'Notifications are enabled: Silently computing backup summary stats...'
|
||||
|
||||
snapshot_size=$(restic stats latest --tag "$RESTIC_BACKUP_TAG" | grep -i 'total size:' | cut -d ':' -f2 | xargs) # xargs acts as trim
|
||||
latest_snapshot_diff=$(restic snapshots --tag "$RESTIC_BACKUP_TAG" --latest 2 --compact \
|
||||
| grep -Ei "^[abcdef0-9]{8} " \
|
||||
| awk '{print $1}' \
|
||||
| tail -2 \
|
||||
| tr '\n' ' ' \
|
||||
| xargs restic diff)
|
||||
added=$(echo "$latest_snapshot_diff" | grep -i 'added:' | awk '{print $2 " " $3}')
|
||||
removed=$(echo "$latest_snapshot_diff" | grep -i 'removed:' | awk '{print $2 " " $3}')
|
||||
|
||||
echo "Added: ${added}. Removed: ${removed}. Snap size: ${snapshot_size}" >> "$RESTIC_BACKUP_NOTIFICATION_FILE"
|
||||
else
|
||||
echo "[WARN] Couldn't write the backup summary stats. File not found or not writable: ${RESTIC_BACKUP_NOTIFICATION_FILE}"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -20,7 +20,7 @@ assert_envvars() {
|
||||
local varnames=("$@")
|
||||
for varname in "${varnames[@]}"; do
|
||||
if [ -z ${!varname+x} ]; then
|
||||
printf "%s must be set for this script to work.\n\nDid you forget to source a /etc/restic/*.env.sh profile in the current shell before executing this script?\n" "$varname" >&2
|
||||
printf "%s must be set for this script to work.\n\nDid you forget to source a $INSTALL_PREFIX/etc/restic/*.env.sh profile in the current shell before executing this script?\n" "$varname" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
5
bin/resticw
Executable file → Normal file
5
bin/resticw
Executable file → Normal file
@@ -116,8 +116,9 @@ else eval "${prefix}"'_restic_arguments_line_=()'; fi; local docopt_i=1
|
||||
declare -p "${prefix}__profile" "${prefix}_restic_arguments_line_"; done; }
|
||||
# docopt parser above, complete command for generating this parser is `docopt.sh resticw`
|
||||
|
||||
# Parse arguments
|
||||
eval "$(docopt "$@")" # See https://github.com/andsens/docopt.sh for the magic :)
|
||||
# Parse arguments - See https://github.com/andsens/docopt.sh for the magic :)
|
||||
DOCOPT_OPTIONS_FIRST=true # treat everything after the first non-option as commands/arguments
|
||||
eval "$(docopt "$@")"
|
||||
|
||||
# --^^^-- END OF GENERATED COMMAND LINE PARSING STUFF --^^^--
|
||||
#
|
||||
|
||||
@@ -4,5 +4,10 @@ PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin/:$INSTALL_PREFIX/bin/
|
||||
# minute hour mday month wday command
|
||||
# Reference: https://www.freebsd.org/doc/handbook/configtuning-cron.html
|
||||
# Reference: crontab(5).
|
||||
@midnight root . $INSTALL_PREFIX/etc/restic/default.sh && cron_mail restic_backup.sh
|
||||
@monthly root . $INSTALL_PREFIX/etc/restic/default.sh && cron_mail restic_check.sh
|
||||
|
||||
@midnight root . $INSTALL_PREFIX/etc/restic/default.env.sh && restic_backup.sh
|
||||
@monthly root . $INSTALL_PREFIX/etc/restic/default.env.sh && restic_check.sh
|
||||
|
||||
# Email notification version. Make sure bin/cron_mail is in the above $PATH
|
||||
#@midnight root . $INSTALL_PREFIX/etc/restic/default.env.sh && cron_mail restic_backup.sh
|
||||
#@monthly root . $INSTALL_PREFIX/etc/restic/default.env.sh && cron_mail restic_check.sh
|
||||
|
||||
@@ -29,3 +29,7 @@ export RESTIC_BACKUP_EXTRA_ARGS=
|
||||
# Verbosity level from 0-3. 0 means no --verbose.
|
||||
# Override this value in a profile if needed.
|
||||
export RESTIC_VERBOSITY_LEVEL=0
|
||||
|
||||
# (optional) Desktop notifications. See restic_backup.sh for details on how to set this up.
|
||||
export RESTIC_NOTIFY_BACKUP_STATS=false
|
||||
export RESTIC_BACKUP_NOTIFICATION_FILE=
|
||||
|
||||
BIN
img/macos_notification.png
Normal file
BIN
img/macos_notification.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
BIN
img/pen-paper.png
Normal file
BIN
img/pen-paper.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
BIN
img/plus.png
Normal file
BIN
img/plus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
img/tasksched.png
Normal file
BIN
img/tasksched.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
@@ -1,13 +1,16 @@
|
||||
[Unit]
|
||||
Description=Backup with restic to Backblaze B2
|
||||
OnFailure=status-email-user@%n.service
|
||||
Requires=nm-unmetered-connection.service
|
||||
# Email on failure require special setup. See README.md
|
||||
#OnFailure=status-email-user@%n.service
|
||||
# Prevent backup on unmetered connection. Needs special setup. See README.md.
|
||||
#Requires=nm-unmetered-connection.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Nice=10
|
||||
# $HOME or $XDG_CACHE_HOME must be set for restic to find /root/.cache/restic/
|
||||
Environment="HOME=/root"
|
||||
# The random sleep (in seconds) is in the case of multiple backup profiles. Many restic instances started at the same time could case high load or network bandwith usage.
|
||||
# pipefail: so that redirecting stderr from the script to systemd-cat does not hide the failed command from OnFailure above.
|
||||
# Random sleep (in seconds): in the case of multiple backup profiles. Many restic instances started at the same time could case high load or network bandwith usage.
|
||||
# `systemd-cat` allows showing the restic output to the systemd journal
|
||||
ExecStart=bash -c 'ps cax | grep -q restic && sleep $(shuf -i 0-300 -n 1); source $INSTALL_PREFIX/etc/restic/%I.env.sh && $INSTALL_PREFIX/bin/restic_backup.sh | systemd-cat'
|
||||
ExecStart=bash -c 'set -o pipefail; ps cax | grep -q restic && sleep $(shuf -i 0-300 -n 1); source $INSTALL_PREFIX/etc/restic/%I.env.sh && $INSTALL_PREFIX/bin/restic_backup.sh 2>&1 | systemd-cat'
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[Unit]
|
||||
Description=Backup with restic on schedule
|
||||
Requires=nm-unmetered-connection.service
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
[Unit]
|
||||
Description=Check restic backup Backblaze B2 for errors
|
||||
OnFailure=status-email-user@%n.service
|
||||
# Email on failure require special setup. See README.md
|
||||
#OnFailure=status-email-user@%n.service
|
||||
Conflicts=restic-backup.service
|
||||
Requires=nm-unmetered-connection.service
|
||||
# Prevent backup on unmetered connection. Needs special setup. See README.md.
|
||||
#Requires=nm-unmetered-connection.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Nice=10
|
||||
# `systemd-cat` allows showing the restic output to the systemd journal
|
||||
ExecStart=bash -c 'source $INSTALL_PREFIX/etc/restic/%I.env.sh && $INSTALL_PREFIX/bin/restic_check.sh | systemd-cat'
|
||||
# pipefail: so that redirecting stderr from the script to systemd-cat does not hide the failed command from OnFailure above.
|
||||
# `systemd-cat`: allows showing the restic output to the systemd journal
|
||||
ExecStart=bash -c 'set -o pipefail; source $INSTALL_PREFIX/etc/restic/%I.env.sh && $INSTALL_PREFIX/bin/restic_check.sh 2>&1 | systemd-cat'
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[Unit]
|
||||
Description=Check restic backup Backblaze B2 for errors on a schedule
|
||||
Requires=nm-unmetered-connection.service
|
||||
|
||||
[Timer]
|
||||
OnCalendar=monthly
|
||||
|
||||
Reference in New Issue
Block a user