diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..46ce7d8 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,212 @@ +--- + +kind: pipeline +type: docker +name: FullBuild + +platform: + os: linux + arch: amd64 + +steps: +- name: Lint Dockerfile + image: hadolint/hadolint:latest-alpine + pull: if-not-exists + commands: + - hadolint --version + - hadolint base-fullbuild/Dockerfile* + +- name: FullBuild + image: thegeeklab/drone-docker-buildx + privileged: true + settings: + repo: modem7/borgmatic-docker + purge: true + compress: true + use_cache: true + cache_from: "modem7/borgmatic-docker:latest" + Dockerfile: base-fullbuild/Dockerfile + context: base-fullbuild/ + platforms: # if it doesn't work run docker run --privileged --rm tonistiigi/binfmt --install all + - linux/amd64 + - linux/arm/v6 + - linux/arm/v7 + - linux/arm64/v8 + username: + from_secret: docker_username + password: + from_secret: docker_password + tags: + - latest + - 1.5.18 + +- name: slack + image: themaz/drone-slack + settings: + webhook: + from_secret: slack_hook + when: + status: [ success, failure ] + +trigger: + event: + - promote + +--- + +kind: pipeline +type: docker +name: dockercli + +platform: + os: linux + arch: amd64 + +steps: +- name: Lint Dockerfile + image: hadolint/hadolint:latest-alpine + pull: if-not-exists + commands: + - hadolint --version + - hadolint base-dockercli/Dockerfile* + +- name: Docker-CLI + image: thegeeklab/drone-docker-buildx + privileged: true + settings: + repo: modem7/borgmatic-docker + purge: true + compress: true + use_cache: true + cache_from: "modem7/borgmatic-docker:dockercli" + Dockerfile: base-dockercli/Dockerfile + context: base-dockercli/ + platforms: # if it doesn't work run docker run --privileged --rm tonistiigi/binfmt --install all + - linux/amd64 + - linux/arm/v6 + - linux/arm/v7 + - linux/arm64/v8 + username: + from_secret: docker_username + password: + from_secret: docker_password + tags: + - dockercli + +- name: slack + image: themaz/drone-slack + settings: + webhook: + from_secret: slack_hook + when: + status: [ success, failure ] + +trigger: + event: + - custom + +--- + +kind: pipeline +type: docker +name: LiveInstall + +platform: + os: linux + arch: amd64 + +steps: +- name: Lint Dockerfile + image: hadolint/hadolint:latest-alpine + pull: if-not-exists + commands: + - hadolint --version + - hadolint base-liveinstall/Dockerfile* + +- name: LiveInstall + image: thegeeklab/drone-docker-buildx + privileged: true + settings: + repo: modem7/borgmatic-docker + purge: true + compress: true + use_cache: true + cache_from: "modem7/borgmatic-docker:liveinstall" + Dockerfile: base-liveinstall/Dockerfile + context: base-liveinstall/ + platforms: # if it doesn't work run docker run --privileged --rm tonistiigi/binfmt --install all + - linux/amd64 + - linux/arm/v6 + - linux/arm/v7 + - linux/arm64/v8 + username: + from_secret: docker_username + password: + from_secret: docker_password + tags: + - liveinstall + +- name: slack + image: themaz/drone-slack + settings: + webhook: + from_secret: slack_hook + when: + status: [ success, failure ] + +trigger: + event: + - custom + +--- + +kind: pipeline +type: docker +name: v1.5.14 + +platform: + os: linux + arch: amd64 + +steps: +- name: Lint Dockerfile + image: hadolint/hadolint:latest-alpine + pull: if-not-exists + commands: + - hadolint --version + - hadolint base-fullbuild-1.5.14/Dockerfile* + +- name: FullBuild + image: thegeeklab/drone-docker-buildx + privileged: true + settings: + repo: modem7/borgmatic-docker + purge: true + compress: true + use_cache: true + cache_from: "modem7/borgmatic-docker:1.5.14" + Dockerfile: base-fullbuild-1.5.14/Dockerfile + context: base-fullbuild-1.5.14/ + platforms: # if it doesn't work run docker run --privileged --rm tonistiigi/binfmt --install all + - linux/amd64 + - linux/arm/v6 + - linux/arm/v7 + - linux/arm64/v8 + username: + from_secret: docker_username + password: + from_secret: docker_password + tags: + - 1.5.14 + +- name: slack + image: themaz/drone-slack + settings: + webhook: + from_secret: slack_hook + when: + status: [ success, failure ] + +trigger: + event: + - promote \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..818d67f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,18 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + # Maintain dependencies for Docker + - package-ecosystem: "docker" # See documentation for possible values + directory: "/base-fullbuild" # Location of package manifests + schedule: + interval: "daily" + + # Maintain dependencies for PIP + - package-ecosystem: "pip" + directory: "/base-fullbuild" + schedule: + interval: "daily" \ No newline at end of file diff --git a/.hadolint.yaml b/.hadolint.yaml new file mode 100644 index 0000000..13eed0b --- /dev/null +++ b/.hadolint.yaml @@ -0,0 +1,7 @@ +override: + style: + - DL3007 + - DL3013 + - DL3018 + - DL3042 + - DL3006 \ No newline at end of file diff --git a/LICENCE.txt b/LICENCE.txt new file mode 100644 index 0000000..9449c44 --- /dev/null +++ b/LICENCE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Alex Lane + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 89733e3..2608fbf 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,34 @@ # Borgmatic Container - - -[![](https://images.microbadger.com/badges/image/b3vis/borgmatic.svg)](https://microbadger.com/images/b3vis/borgmatic "Get your own image badge on microbadger.com") +![Docker Pulls](https://img.shields.io/docker/pulls/modem7/borgmatic-docker) +![Docker Image Size (tag)](https://img.shields.io/docker/image-size/modem7/borgmatic-docker/latest) +[![Build Status](https://drone.modem7.com/api/badges/modem7/docker-borgmatic/status.svg)](https://drone.modem7.com/modem7/docker-borgmatic) +![GitHub last commit](https://img.shields.io/github/last-commit/modem7/docker-borgmatic) +[![User Guide](https://img.shields.io/badge/User_Guide-OmegaWiki-informational?style=flat&logo=bookstack)](https://www.modem7.com/books/docker-backup/page/backup-docker-using-borgmatic) ### Description +Multiarch fork of b3vis/borgmatic with latest versions so you can run Docker commands. -A little container I wrote to automate my [Borgbackup](https://github.com/borgbackup)'s using the excellent [Borgmatic](https://github.com/witten/borgmatic). +There are also tags with Docker-CLI installed. Useful for container stop/start scripts. + +### Readme + +A little container based on b3vis's work to automate my [Borgbackups](https://github.com/borgbackup) using the excellent [Borgmatic](https://github.com/witten/borgmatic). It uses cron to run the backups at a time you can configure in `data/borgmatic.d/crontab.txt`. +# Tags +| Tag | Description | +| :----: | --- | +| Latest | Latest version of Borgmatic| +| dockercli | Borgmatic with Docker-CLI baked in. | +| liveinstall | Borgmatic, with Docker-CLI downloaded and installed on container startup. | +| 1.5.xx | Specific versions of Borgmatic | + ### Usage -To set your backup timing and configuration, you will need to create [crontab.txt](data/borgmatic.d/crontab.txt) and your borgmatic [config.yaml](data/borgmatic.d/config.yaml) and mount these files into the `/etc/borgmatic.d/` directory. When the container starts it creates the crontab from `crontab.txt` and starts crond. By cloning this repo in `/opt/docker/`, you will have a working setup to get started. +Please look at this [guide](https://www.modem7.com/books/docker-backup/page/backup-docker-using-borgmatic) to help you run this container. + +To set your backup timing and configuration, you will need to create [crontab.txt](https://github.com/modem7/docker-borgmatic/blob/master/base-fullbuild/data/borgmatic.d/crontab.txt) and your borgmatic [config.yaml](https://github.com/modem7/docker-borgmatic/blob/master/base-fullbuild/data/borgmatic.d/config.yaml) and mount these files into the `/etc/borgmatic.d/` directory. When the container starts it creates the crontab from `crontab.txt` and starts crond. By cloning this repo in `/opt/docker/`, you will have a working setup to get started. If using remote repositories mount your .ssh to /root/.ssh within the container. @@ -85,4 +102,4 @@ A non-volatile place to store the borg chunk cache. 3. Fuse-mount the backup: `borg mount /mnt/borg-repository ` 4. Restore your files 5. Finally unmount and exit: `borg umount && exit`. - - In case Borg fails to create/acquire a lock: `borg break-lock /mnt/repository` \ No newline at end of file + - In case Borg fails to create/acquire a lock: `borg break-lock /mnt/repository` diff --git a/base-dockercli/Dockerfile b/base-dockercli/Dockerfile new file mode 100644 index 0000000..7e11761 --- /dev/null +++ b/base-dockercli/Dockerfile @@ -0,0 +1,9 @@ +FROM modem7/borgmatic-docker +COPY entry.sh /entry.sh +RUN apk update \ + && apk add --no-cache \ + docker-cli \ + && rm -rf /var/cache/apk/* \ + /.cache \ + && chmod 755 /entry.sh +CMD ["/entry.sh"] diff --git a/base-dockercli/entry.sh b/base-dockercli/entry.sh new file mode 100644 index 0000000..9723190 --- /dev/null +++ b/base-dockercli/entry.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# Import your cron file +/usr/bin/crontab /etc/borgmatic.d/crontab.txt +#Variables +borgver=$(borg --version) +borgmaticver=$(borgmatic --version) +#Software versions +docker --version +echo borgmatic $borgmaticver +echo $borgver +# Start cron +/usr/sbin/crond -f -L /dev/stdout diff --git a/.env.template b/base-fullbuild-1.5.14/.env.template similarity index 100% rename from .env.template rename to base-fullbuild-1.5.14/.env.template diff --git a/.gitignore b/base-fullbuild-1.5.14/.gitignore similarity index 100% rename from .gitignore rename to base-fullbuild-1.5.14/.gitignore diff --git a/Dockerfile b/base-fullbuild-1.5.14/Dockerfile similarity index 68% rename from Dockerfile rename to base-fullbuild-1.5.14/Dockerfile index e5eba96..19f8221 100644 --- a/Dockerfile +++ b/base-fullbuild-1.5.14/Dockerfile @@ -1,9 +1,7 @@ FROM alpine:3.13 as builder -LABEL mainainer='b3vis' -ARG BORG_VERSION=1.1.17 -ARG BORGMATIC_VERSION=1.5.18 -ARG LLFUSE_VERSION=1.4.1 -RUN apk upgrade --no-cache \ +COPY requirements.txt /requirements.txt +RUN apk update --no-cache \ + && apk upgrade --no-cache \ && apk add --no-cache \ alpine-sdk \ python3-dev \ @@ -15,15 +13,14 @@ RUN apk upgrade --no-cache \ fuse-dev \ attr-dev \ py3-wheel \ - && pip3 install --upgrade pip \ - && pip3 install --upgrade borgbackup==${BORG_VERSION} \ - && pip3 install --upgrade borgmatic==${BORGMATIC_VERSION} \ - && pip3 install --upgrade llfuse==${LLFUSE_VERSION} + && pip3 install -U -r requirements.txt FROM alpine:3.13 -LABEL mainainer='b3vis' +LABEL mainainer='modem7' +ARG PYTHON_VERSION=3.8 COPY entry.sh /entry.sh -RUN apk upgrade --no-cache \ +RUN apk update --no-cache \ + && apk upgrade --no-cache \ && apk add --no-cache \ tzdata \ sshfs \ @@ -44,7 +41,7 @@ VOLUME /etc/borgmatic.d VOLUME /root/.config/borg VOLUME /root/.ssh VOLUME /root/.cache/borg -COPY --from=builder /usr/lib/python3.8/site-packages /usr/lib/python3.8/ +COPY --from=builder /usr/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/ COPY --from=builder /usr/bin/borg /usr/bin/ COPY --from=builder /usr/bin/borgfs /usr/bin/ COPY --from=builder /usr/bin/borgmatic /usr/bin/ diff --git a/data/borgmatic.d/config.yaml b/base-fullbuild-1.5.14/data/borgmatic.d/config.yaml similarity index 100% rename from data/borgmatic.d/config.yaml rename to base-fullbuild-1.5.14/data/borgmatic.d/config.yaml diff --git a/data/borgmatic.d/crontab.txt b/base-fullbuild-1.5.14/data/borgmatic.d/crontab.txt similarity index 100% rename from data/borgmatic.d/crontab.txt rename to base-fullbuild-1.5.14/data/borgmatic.d/crontab.txt diff --git a/base-fullbuild-1.5.14/entry.sh b/base-fullbuild-1.5.14/entry.sh new file mode 100644 index 0000000..5723658 --- /dev/null +++ b/base-fullbuild-1.5.14/entry.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# Import your cron file +/usr/bin/crontab /etc/borgmatic.d/crontab.txt +#Variables +borgver=$(borg --version) +borgmaticver=$(borgmatic --version) +#Software versions +echo borgmatic $borgmaticver +echo $borgver +# Start cron +/usr/sbin/crond -f -L /dev/stdout diff --git a/base-fullbuild-1.5.14/requirements.txt b/base-fullbuild-1.5.14/requirements.txt new file mode 100644 index 0000000..92f981c --- /dev/null +++ b/base-fullbuild-1.5.14/requirements.txt @@ -0,0 +1,4 @@ +pip==20.2.4 +borgbackup==1.1.16 +borgmatic==1.5.14 +llfuse==1.3.8 \ No newline at end of file diff --git a/base-fullbuild/.env.template b/base-fullbuild/.env.template new file mode 100644 index 0000000..cfd6779 --- /dev/null +++ b/base-fullbuild/.env.template @@ -0,0 +1,11 @@ +TZ=Europe/Berlin +BORG_PASSPHRASE=ReplaceWithYourSecretPassPhrase +VOLUME_SOURCE=/home +VOLUME_TARGET=./data/repository +VOLUME_ETC_BORGMATIC=./data/borgmatic.d +VOLUME_DOT_BORGMATIC=./data/.borgmatic +VOLUME_BORG_CONFIG=./data/.config/borg +VOLUME_SSH=./data/.ssh +VOLUME_BORG_CACHE=./data/.cache/borg +# for NTFY flavour only +#VOLUME_NTFY=./data/ntfy diff --git a/base-fullbuild/.gitignore b/base-fullbuild/.gitignore new file mode 100644 index 0000000..01105f3 --- /dev/null +++ b/base-fullbuild/.gitignore @@ -0,0 +1,5 @@ +data/.cache/ +data/.config/ +data/.ssh/ +data/repository/ +.env diff --git a/base-fullbuild/Dockerfile b/base-fullbuild/Dockerfile new file mode 100644 index 0000000..2ab4ff1 --- /dev/null +++ b/base-fullbuild/Dockerfile @@ -0,0 +1,51 @@ +FROM alpine:3.14 as builder +COPY requirements.txt /requirements.txt +RUN apk update --no-cache \ + && apk upgrade --no-cache \ + && apk add --no-cache \ + alpine-sdk \ + python3-dev \ + py3-pip \ + openssl-dev \ + lz4-dev \ + acl-dev \ + linux-headers \ + fuse-dev \ + attr-dev \ + py3-wheel \ + && pip3 install -U -r requirements.txt + +FROM alpine:3.14 +LABEL mainainer='modem7' +ARG PYTHON_VERSION=3.9 +COPY entry.sh /entry.sh +RUN apk update --no-cache \ + && apk upgrade --no-cache \ + && apk add --no-cache \ + tzdata \ + sshfs \ + python3 \ + openssl \ + fuse \ + ca-certificates \ + lz4-libs \ + libacl \ + postgresql-client \ + mariadb-client \ + curl \ + && rm -rf /var/cache/apk/* \ + && chmod 755 /entry.sh +VOLUME /mnt/source +VOLUME /mnt/borg-repository +VOLUME /etc/borgmatic.d +VOLUME /root/.config/borg +VOLUME /root/.ssh +VOLUME /root/.cache/borg +COPY --from=builder /usr/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/ +COPY --from=builder /usr/bin/borg /usr/bin/ +COPY --from=builder /usr/bin/borgfs /usr/bin/ +COPY --from=builder /usr/bin/borgmatic /usr/bin/ +COPY --from=builder /usr/bin/generate-borgmatic-config /usr/bin/ +COPY --from=builder /usr/bin/upgrade-borgmatic-config /usr/bin/ +COPY --from=builder /usr/bin/validate-borgmatic-config /usr/bin/ +CMD ["/entry.sh"] diff --git a/base-fullbuild/data/borgmatic.d/config.yaml b/base-fullbuild/data/borgmatic.d/config.yaml new file mode 100644 index 0000000..a7ffb40 --- /dev/null +++ b/base-fullbuild/data/borgmatic.d/config.yaml @@ -0,0 +1,35 @@ +location: + source_directories: + - /mnt/source + repositories: + - /mnt/borg-repository + one_file_system: true + +storage: +# Passphase is set in varibable $BORG_PASSPHRASE +# encryption_passphrase: "DonNotMissToChangeYourPassphrase" + compression: lz4 + archive_name_format: 'backup-{now}' + +retention: + keep_hourly: 2 + keep_daily: 7 + keep_weekly: 4 + keep_monthly: 12 + keep_yearly: 10 + prefix: 'backup-' + +consistency: + checks: + - repository + - archives + check_last: 3 + prefix: 'backup-' + +hooks: + before_backup: + - echo "Starting a backup job." + after_backup: + - echo "Backup created." + on_error: + - echo "Error while creating a backup." diff --git a/base-fullbuild/data/borgmatic.d/crontab.txt b/base-fullbuild/data/borgmatic.d/crontab.txt new file mode 100644 index 0000000..55b8ab8 --- /dev/null +++ b/base-fullbuild/data/borgmatic.d/crontab.txt @@ -0,0 +1 @@ +0 1 * * * PATH=$PATH:/usr/bin /usr/bin/borgmatic --stats -v 0 2>&1 diff --git a/base-fullbuild/entry.sh b/base-fullbuild/entry.sh new file mode 100644 index 0000000..5723658 --- /dev/null +++ b/base-fullbuild/entry.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# Import your cron file +/usr/bin/crontab /etc/borgmatic.d/crontab.txt +#Variables +borgver=$(borg --version) +borgmaticver=$(borgmatic --version) +#Software versions +echo borgmatic $borgmaticver +echo $borgver +# Start cron +/usr/sbin/crond -f -L /dev/stdout diff --git a/base-fullbuild/requirements.txt b/base-fullbuild/requirements.txt new file mode 100644 index 0000000..27257c5 --- /dev/null +++ b/base-fullbuild/requirements.txt @@ -0,0 +1,4 @@ +pip>=21.2.4 +borgbackup>=1.1.17 +borgmatic>=1.5.18 +llfuse>=1.4.1 \ No newline at end of file diff --git a/base-liveinstall/Dockerfile b/base-liveinstall/Dockerfile new file mode 100644 index 0000000..093b1ce --- /dev/null +++ b/base-liveinstall/Dockerfile @@ -0,0 +1,7 @@ +FROM modem7/borgmatic-docker +COPY entry.sh /entry.sh +COPY wtfc.sh /wtfc.sh +RUN rm -rf /var/cache/apk/* \ + /.cache \ + && chmod 755 /entry.sh /wtfc.sh +CMD ["/entry.sh"] \ No newline at end of file diff --git a/base-liveinstall/entry.sh b/base-liveinstall/entry.sh new file mode 100644 index 0000000..a3b3af1 --- /dev/null +++ b/base-liveinstall/entry.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# Variables +borgver=$(borg --version) +borgmaticver=$(borgmatic --version) + +# Wait for internet connection + echo "Waiting for Internet connection...." + ./wtfc.sh -Q -T 5 ping -c 4 www.google.com + echo "Internet connection established" + +# Check variable to see if present, echo result +if [ -z "$LIVEINSTALL" ] + then + echo "Installing Docker-CLI" + else + echo "Installing $LIVEINSTALL" +fi +# Installing packages +apk update -q && apk add --no-cache -q ${LIVEINSTALL:-docker-cli} + +# Import your cron file +/usr/bin/crontab /etc/borgmatic.d/crontab.txt + +# Software versions +docker --version +echo borgmatic $borgmaticver +echo $borgver + +# Start cron +/usr/sbin/crond -f -L /dev/stdout \ No newline at end of file diff --git a/base-liveinstall/wtfc.sh b/base-liveinstall/wtfc.sh new file mode 100644 index 0000000..7805dd2 --- /dev/null +++ b/base-liveinstall/wtfc.sh @@ -0,0 +1,254 @@ +#!/bin/sh + +cmdname="${0##*/}" + +VERSION=0.0.3 + +echoto() { + # print to stderr or to stdout + out=$1 + shift 1 + + if ([ "${out}" -eq 2 ]); then + printf "$@" >&2 + else + # stdout can be silenced only + if [ "${QUIET}" -eq 0 ]; then + printf "$@" + fi + fi +} + +progress() { + if ([ "${PROGRESS}" -eq 1 ]); then + echoto 1 "." + fi +} + +usage() { + # (TODO) -F, --format-progress=FORMAT set FORMAT for progress, available: DOTS, PROGRESSBAR (default is DOTS) + OUTPUT=`cat < 0), otherwise to stdout + if ([ "$1" -gt 0 ]); then + echo "${OUTPUT}" >&2 + else + echo "${OUTPUT}" + fi + + exit $1 +} + +version() { + echo "wtfc (WaiT For the Command) version: ${VERSION}" + exit 0 +} + +wait_for(){ + if [ "${TIMEOUT}" -gt 0 ]; then + echoto 1 "$cmdname: waiting $TIMEOUT seconds for $CMD\n" + else + echoto 1 "$cmdname: waiting without a timeout for $CMD\n" + fi + + while : + do + eval $CMD >/dev/null 2>&1 + result=$? + + if ([ "${result}" -eq "${STATUS}" ]); then + break + fi + sleep $INTERVAL + + progress + done + return $result +} + +wait_for_wrapper() { + TIME_START=$(date +%s) + + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if ([ "${QUIET}" -eq 1 ]); then + eval $TIMEOUT_CMD $TIMEOUT_FLAG $TIMEOUT $0 --quiet --child --status=$STATUS --timeout=$TIMEOUT $CMD & + else + eval $TIMEOUT_CMD $TIMEOUT_FLAG $TIMEOUT $0 --child --status=$STATUS --timeout=$TIMEOUT $CMD & + fi + PID=$! + trap "kill -INT -$PID" INT + + while [ $(($(date +%s)-TIME_START)) -lt "${TIMEOUT}" ]; do + + eval $CMD >/dev/null 2>&1 + result=$? + + if ([ "${result}" -eq "${STATUS}" ]); then + break + fi + + sleep $INTERVAL + + progress + done + wait $PID + RESULT=$? + return $RESULT +} + +# process arguments +while [ $# -gt 0 ] +do + case "$1" in + --child) + CHILD=1 + shift 1 + ;; + -H | --help) + usage 0 + ;; + -I) + INTERVAL="$2" + if [ -z "${INTERVAL}" ]; then break; fi + shift 2 + ;; + --interval=*) + INTERVAL="${1#*=}" + shift 1 + ;; + -P | --progress) + PROGRESS=1 + shift 1 + ;; + -Q | --quiet) + QUIET=1 + shift 1 + ;; + -S) + STATUS="$2" + if [ -z "${STATUS}" ]; then break; fi + shift 2 + ;; + --status=*) + STATUS="${1#*=}" + shift 1 + ;; + -T) + TIMEOUT="$2" + if [ -z "${TIMEOUT}" ]; then break; fi + shift 2 + ;; + --timeout=*) + TIMEOUT="${1#*=}" + shift 1 + ;; + -V | --version) + version + ;; + -*) + echoto 2 "Unknown argument: $1" + usage 1 + ;; + *) + CMD="$@" + break + ;; + esac +done + +# read from stdin, if no cmd provided +if [ -z "${CMD}" ]; then + read CMD +fi + +if [ -z "${CMD}" ]; then + echoto 2 "Error: you need to provide a COMMAND to test as the last argument or via standard input.\n" + usage 1 +fi + +CHILD=${CHILD:-0} +INTERVAL=${INTERVAL:-1} +PROGRESS=${PROGRESS:-0} +QUIET=${QUIET:-0} +STATUS=${STATUS:-0} +TIMEOUT=${TIMEOUT:-1} + +# check to see if timeout is from busybox/alpine => '-t' switch is required or not +TIMEOUT_TEST="$(timeout 1 sleep 0 2>&1)" +case "${TIMEOUT_TEST}" in + timeout:\ can\'t\ execute\ \'1\':*) TIMEOUT_FLAG="-t" ;; + *) TIMEOUT_FLAG="" ;; +esac + +TIMEOUT_TEST="$(timeout ${TIMEOUT_FLAG} 1 sleep 0 2>&1)" +TIMEOUT_TEST_STATUS="$?" + +# fallback for osx (uses gtimeout) +if [ "${TIMEOUT_TEST_STATUS}" -eq 127 ]; then + TIMEOUT_TEST="$(gtimeout ${TIMEOUT_FLAG} 1 sleep 0 2>&1)" + TIMEOUT_TEST_STATUS="$?" + + if [ "${TIMEOUT_TEST_STATUS}" -eq 127 ]; then + TIMEOUT_TEST="$(gnu-timeout ${TIMEOUT_FLAG} 1 sleep 0 2>&1)" + TIMEOUT_TEST_STATUS="$?" + + if [ "${TIMEOUT_TEST_STATUS}" -eq 127 ]; then + echoto 2 "timeout|gtimeout|gnu-timeout is required by the script, but not found!\n" + exit 1 + fi + TIMEOUT_CMD="gnu-timeout" + else + TIMEOUT_CMD="gtimeout" + fi +else + TIMEOUT_CMD="timeout" +fi + +start_ts=$(date +%s) + +if [ "${CHILD}" -eq 1 ]; then + wait_for + RESULT=$? + exit $RESULT +else + if [ "${TIMEOUT}" -gt 0 ]; then + wait_for_wrapper + RESULT=$? + else + wait_for + RESULT=$? + fi +fi + +if [ "${RESULT}" -ne "${STATUS}" ]; then + echoto 2 "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $CMD to return status: $STATUS (was status: $RESULT)\n" + if [ "${RESULT}" -eq 0 ]; then + # exit with 1, inspite the fact original ended with 0 (as we expected non-0) + exit 1 + else + exit $RESULT + fi +else + end_ts=$(date +%s) + echoto 1 "$cmdname: $CMD finished with expected status $RESULT after $((end_ts - start_ts)) seconds\n" + exit 0 +fi diff --git a/docker-compose.restore.yml b/docker-compose.restore.yml index 435a566..1a96e87 100644 --- a/docker-compose.restore.yml +++ b/docker-compose.restore.yml @@ -1,16 +1,25 @@ -version: '3' -services: - borgmatic: - container_name: borg-restore +version: "2.4" +services: + + borgmaticrestore: + container_name: Borg-restore + volumes: + - /mnt/samba/OldHD/ServerBackup/Borgmatic/:/mnt/borg-repository + - /home/alex/DockerApps/Borgmatic/borgmatic.d/:/etc/borgmatic.d/ + - /home/alex/DockerApps/Borgmatic/.config/borg/:/root/.config/borg + - /home/alex/DockerApps/Borgmatic/.ssh/:/root/.ssh + - /home/alex/DockerApps/Borgmatic/.cache/borg/:/root/.cache/borg + - /dev/shm/Borgrestore:/RestoreMount + - /var/hda/files/drives/drive14/Test/Restore:/Restore cap_add: - SYS_ADMIN - security_opt: - apparmor:unconfined - label:disable - + environment: + - TZ=$TZ devices: - /dev/fuse:/dev/fuse - command: /bin/sh + image: modem7/borgmatic-docker \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index db8e98d..287e3c2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,8 @@ -version: '3' +version: '2.4' services: borgmatic: - image: b3vis/borgmatic - container_name: borgmatic + image: modem7/borgmatic-docker + container_name: Borgmatic volumes: - ${VOLUME_SOURCE}:/mnt/source:ro # backup source - ${VOLUME_TARGET}:/mnt/borg-repository # backup target diff --git a/entry.sh b/entry.sh deleted file mode 100644 index 9bc125f..0000000 --- a/entry.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -# Import your cron file -/usr/bin/crontab /etc/borgmatic.d/crontab.txt -# Start cron -/usr/sbin/crond -f -L /dev/stdout