mirror of
https://github.com/lobaro/restic-backup-docker.git
synced 2026-04-04 12:18:50 +00:00
Compare commits
36 Commits
1.3.0-0.9.
...
v1.3.2+res
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a018fdc2ec | ||
|
|
1d222b9798 | ||
|
|
e09de3ee18 | ||
|
|
33d48e8e0d | ||
|
|
412a96877f | ||
|
|
ffcf548155 | ||
|
|
5fab635af0 | ||
|
|
389fcaa995 | ||
|
|
beb5fa841c | ||
|
|
bc000ef4f8 | ||
|
|
5155c3b351 | ||
|
|
fa34734660 | ||
|
|
7e0b0706c1 | ||
|
|
820fabb1e6 | ||
|
|
e94df72518 | ||
|
|
36f771b781 | ||
|
|
f308eca25b | ||
|
|
0b72ec94a7 | ||
|
|
84c8ed0c0d | ||
|
|
a118fb5594 | ||
|
|
0c32b273e9 | ||
|
|
5110483351 | ||
|
|
93e76c46fe | ||
|
|
4d2034ccd4 | ||
|
|
265c33f2d9 | ||
|
|
268987fd8e | ||
|
|
4f60e830af | ||
|
|
925930000c | ||
|
|
ed609ae89d | ||
|
|
317ecba765 | ||
|
|
46df366e4c | ||
|
|
23a05d88b9 | ||
|
|
d3297615e2 | ||
|
|
a07b831d78 | ||
|
|
b85c6d9603 | ||
|
|
5b4d050643 |
95
.github/workflows/docker-publish.yml
vendored
Normal file
95
.github/workflows/docker-publish.yml
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
name: Docker
|
||||
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
# Publish semver tags as releases.
|
||||
tags: [ 'v*.*.*' ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
env:
|
||||
# Use docker.io for Docker Hub if empty
|
||||
REGISTRY: ghcr.io
|
||||
# github.repository as <account>/<repo>
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
# This is used to complete the identity challenge
|
||||
# with sigstore/fulcio when running outside of PRs.
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Install the cosign tool except on PR
|
||||
# https://github.com/sigstore/cosign-installer
|
||||
- name: Install cosign
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 #v3.1.1
|
||||
with:
|
||||
cosign-release: 'v2.1.1'
|
||||
|
||||
# Workaround: https://github.com/docker/build-push-action/issues/461
|
||||
- name: Setup Docker buildx
|
||||
uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf
|
||||
|
||||
# Login against a Docker registry except on PR
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Extract metadata (tags, labels) for Docker
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
|
||||
# Sign the resulting Docker image digest except on PRs.
|
||||
# This will only write to the public Rekor transparency log when the Docker
|
||||
# repository is public to avoid leaking data. If you would like to publish
|
||||
# transparency data even for private images, pass --force to cosign below.
|
||||
# https://github.com/sigstore/cosign
|
||||
- name: Sign the published Docker image
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
env:
|
||||
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
|
||||
TAGS: ${{ steps.meta.outputs.tags }}
|
||||
DIGEST: ${{ steps.build-and-push.outputs.digest }}
|
||||
# This step uses the identity token to provision an ephemeral certificate
|
||||
# against the sigstore community Fulcio instance.
|
||||
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
|
||||
48
CHANGELOG.md
Normal file
48
CHANGELOG.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
## v1.3.2+restic-0-16-0
|
||||
|
||||
### Changed
|
||||
* Base image directly on official restic image
|
||||
* [Semver](https://semver.org/) aligned version naming including restic version
|
||||
|
||||
### Added
|
||||
* rclone to docker image
|
||||
* Implemented a simple mail notification after backups using mailx
|
||||
* MAILX_ARGS environment variable
|
||||
|
||||
## v1.3.1-0.9.6
|
||||
|
||||
### Changed
|
||||
* Update to Restic v0.9.5
|
||||
* Reduced the number of layers in the Docker image
|
||||
|
||||
### Fixed
|
||||
* Check if a repo already exists works now for all repository types
|
||||
|
||||
### Added
|
||||
* shh added to container
|
||||
* fuse added to container
|
||||
* support to send mails using external SMTP server after backups
|
||||
|
||||
## v1.2-0.9.4
|
||||
|
||||
### Added
|
||||
* AWS Support
|
||||
|
||||
## v1.1
|
||||
|
||||
### Fixed
|
||||
* `--prune` must be passed to `RESTIC_FORGET_ARGS` to execute prune after forget.
|
||||
|
||||
### Changed
|
||||
* Switch to base Docker container to `golang:1.7-alpine` to support latest restic build.
|
||||
|
||||
## v1.0
|
||||
|
||||
Initial release.
|
||||
|
||||
The container has proper logs now and was running for over a month in production.
|
||||
There are still some features missing. Sticking to semantic versioning we do not expect any breaking changes in the 1.x releases.
|
||||
33
Dockerfile
33
Dockerfile
@@ -4,10 +4,9 @@ FROM alpine:latest as rclone
|
||||
ADD https://downloads.rclone.org/rclone-current-linux-amd64.zip /
|
||||
RUN unzip rclone-current-linux-amd64.zip && mv rclone-*-linux-amd64/rclone /bin/rclone && chmod +x /bin/rclone
|
||||
|
||||
FROM restic/restic:0.9.6
|
||||
FROM restic/restic:0.16.0
|
||||
|
||||
# install mailx
|
||||
RUN apk add --update --no-cache heirloom-mailx fuse
|
||||
RUN apk add --update --no-cache curl mailx
|
||||
|
||||
COPY --from=rclone /bin/rclone /bin/rclone
|
||||
|
||||
@@ -20,18 +19,40 @@ ENV RESTIC_PASSWORD=""
|
||||
ENV RESTIC_TAG=""
|
||||
ENV NFS_TARGET=""
|
||||
ENV BACKUP_CRON="0 */6 * * *"
|
||||
ENV CHECK_CRON=""
|
||||
ENV RESTIC_INIT_ARGS=""
|
||||
ENV RESTIC_FORGET_ARGS=""
|
||||
ENV RESTIC_JOB_ARGS=""
|
||||
ENV RESTIC_DATA_SUBSET=""
|
||||
ENV MAILX_ARGS=""
|
||||
ENV OS_AUTH_URL=""
|
||||
ENV OS_PROJECT_ID=""
|
||||
ENV OS_PROJECT_NAME=""
|
||||
ENV OS_USER_DOMAIN_NAME="Default"
|
||||
ENV OS_PROJECT_DOMAIN_ID="default"
|
||||
ENV OS_USERNAME=""
|
||||
ENV OS_PASSWORD=""
|
||||
ENV OS_REGION_NAME=""
|
||||
ENV OS_INTERFACE=""
|
||||
ENV OS_IDENTITY_API_VERSION=3
|
||||
|
||||
# openshift fix
|
||||
RUN mkdir /.cache && \
|
||||
chgrp -R 0 /.cache && \
|
||||
chmod -R g=u /.cache && \
|
||||
chgrp -R 0 /mnt && \
|
||||
chmod -R g=u /mnt && \
|
||||
chgrp -R 0 /var/spool/cron/crontabs/root && \
|
||||
chmod -R g=u /var/spool/cron/crontabs/root && \
|
||||
chgrp -R 0 /var/log/cron.log && \
|
||||
chmod -R g=u /var/log/cron.log
|
||||
|
||||
# /data is the dir where you have to put the data to be backed up
|
||||
VOLUME /data
|
||||
|
||||
COPY backup.sh /bin/backup
|
||||
COPY check.sh /bin/check
|
||||
COPY entry.sh /entry.sh
|
||||
|
||||
|
||||
WORKDIR "/"
|
||||
|
||||
ENTRYPOINT ["/entry.sh"]
|
||||
CMD ["tail","-fn0","/var/log/cron.log"]
|
||||
|
||||
169
README.md
169
README.md
@@ -7,45 +7,55 @@ This container runs restic backups in regular intervals.
|
||||
* Support for different targets (tested with: Local, NFS, SFTP, AWS)
|
||||
* Support `restic mount` inside the container to browse the backup files
|
||||
|
||||
**Container**: [lobaro/restic-backup-docker](https://hub.docker.com/r/lobaro/restic-backup-docker/)
|
||||
**Container**:
|
||||
* [ghcr.io/lobaro/restic-backup-docker](https://github.com/lobaro/restic-backup-docker/pkgs/container/restic-backup-docker)
|
||||
* Old: [lobaro/restic-backup-docker](https://hub.docker.com/r/lobaro/restic-backup-docker/)
|
||||
|
||||
Stable
|
||||
Latest (experimental):
|
||||
```
|
||||
docker pull lobaro/restic-backup-docker:1.2-0.9.4
|
||||
docker pull ghcr.io/lobaro/restic-backup-docker:master
|
||||
```
|
||||
|
||||
Latest (experimental)
|
||||
# Contributing
|
||||
Pull Requests to improve the image are always wellcome. Please create an issue about the PR first.
|
||||
|
||||
When behaviour of the image changes (Features, Bugfixes, Changes in the API) please update the "Unreleased" section of the [CHANGELOG.md](https://github.com/lobaro/restic-backup-docker/blob/master/CHANGELOG.md)
|
||||
|
||||
|
||||
## Hooks
|
||||
|
||||
If you need to execute a script before or after each backup or check, you need to add your hook scripts in the container folder `/hooks`:
|
||||
```
|
||||
docker pull lobaro/restic-backup-docker:latest
|
||||
-v ~/home/user/hooks:/hooks
|
||||
```
|
||||
|
||||
Please don't hesitate to report any issue you find. **Thanks.**
|
||||
Call your pre-backup script `pre-backup.sh` and post-backup script `post-backup.sh`. You can also have separate scripts when running data verification checks `pre-check.sh` and `post-check.sh`.
|
||||
|
||||
Please don't hesitate to report any issues you find. **Thanks.**
|
||||
|
||||
# Test the container
|
||||
|
||||
Clone this repository
|
||||
|
||||
Clone this repository:
|
||||
```
|
||||
git clone https://github.com/Lobaro/restic-backup-docker.git
|
||||
cd restic-backup-docker
|
||||
```
|
||||
|
||||
Build the container. The container is named `backup-test`
|
||||
Build the container (the container is named `backup-test`):
|
||||
```
|
||||
./build.sh
|
||||
```
|
||||
|
||||
Run the container.
|
||||
Run the container:
|
||||
```
|
||||
./run.sh
|
||||
```
|
||||
|
||||
This will run the container `backup-test` with the name `backup-test`. Existing containers with that names are completly removed automatically.
|
||||
This will run the container `backup-test` with the name `backup-test`. Existing containers with that name are completely removed automatically.
|
||||
|
||||
The container will backup `~/test-data` to a repository with password `test` at `~/test-repo` every minute. The repository is initialized automatically by the container.
|
||||
|
||||
To enter your container execute
|
||||
The container will back up `~/test-data` to a repository with password `test` at `~/test-repo` every minute. The repository is initialized automatically by the container. If you'd like to change the arguments passed to `restic init`, you can do so using the `RESTIC_INIT_ARGS` env variable.
|
||||
|
||||
To enter your container execute:
|
||||
```
|
||||
docker exec -ti backup-test /bin/sh
|
||||
```
|
||||
@@ -53,31 +63,80 @@ docker exec -ti backup-test /bin/sh
|
||||
Now you can use restic [as documented](https://restic.readthedocs.io/en/stable/), e.g. try to run `restic snapshots` to list all your snapshots.
|
||||
|
||||
## Logfiles
|
||||
Logfiles are inside the container. If needed you can create volumes for them.
|
||||
|
||||
Logfiles are inside the container. If needed, you can create volumes for them.
|
||||
```
|
||||
docker logs
|
||||
```
|
||||
Shows `/var/log/cron.log`
|
||||
Shows `/var/log/cron.log`.
|
||||
|
||||
Additionally you can see the the full log, including restic output, of the last execution in `/var/log/backup-last.log`. When the backup fails the log is copied to `/var/log/restic-error-last.log`. If configured, you can find the full output of the mail notification in `/var/log/mail-last.log`.
|
||||
Additionally you can see the full log, including restic output, of the last execution in `/var/log/backup-last.log`. When the backup fails, the log is copied to `/var/log/restic-error-last.log`. If configured, you can find the full output of the mail notification in `/var/log/mail-last.log`.
|
||||
|
||||
# Use the running container
|
||||
|
||||
Assuming the container name is `restic-backup-var`, you can execute restic with:
|
||||
|
||||
docker exec -ti restic-backup-var restic
|
||||
|
||||
## Backup
|
||||
|
||||
To execute a backup manually, independent of the CRON, run:
|
||||
|
||||
docker exec -ti restic-backup-var /bin/backup
|
||||
|
||||
Back up a single file or directory:
|
||||
|
||||
docker exec -ti restic-backup-var restic backup /data/path/to/dir --tag my-tag
|
||||
|
||||
## Data verification check
|
||||
|
||||
To verify backup integrity and consistency manually, independent of the CRON, run:
|
||||
|
||||
docker exec -ti restic-backup-var /bin/check
|
||||
|
||||
## Restore
|
||||
|
||||
You might want to mount a separate host volume at e.g. `/restore` to not override existing data while restoring.
|
||||
|
||||
Get your snapshot ID with:
|
||||
|
||||
docker exec -ti restic-backup-var restic snapshots
|
||||
|
||||
e.g. `abcdef12`
|
||||
|
||||
docker exec -ti restic-backup-var restic restore --include /data/path/to/files --target / abcdef12
|
||||
|
||||
The target is `/` since all data backed up should be inside the host mounted `/data` dir. If you mount `/restore` you should set `--target /restore` and the data will end up in `/restore/data/path/to/files`.
|
||||
|
||||
# Customize the Container
|
||||
|
||||
The container is setup by setting [environment variables](https://docs.docker.com/engine/reference/run/#/env-environment-variables) and [volumes](https://docs.docker.com/engine/reference/run/#volume-shared-filesystems).
|
||||
The container is set up by setting [environment variables](https://docs.docker.com/engine/reference/run/#/env-environment-variables) and [volumes](https://docs.docker.com/engine/reference/run/#volume-shared-filesystems).
|
||||
|
||||
## Environment variables
|
||||
|
||||
* `RESTIC_REPOSITORY` - the location of the restic repository. Default `/mnt/restic`. For S3: `s3:https://s3.amazonaws.com/BUCKET_NAME`
|
||||
* `RESTIC_PASSWORD` - the password for the restic repository. Will also be used for restic init during first start when the repository is not initialized.
|
||||
* `RESTIC_TAG` - Optional. To tag the images created by the container.
|
||||
* `NFS_TARGET` - Optional. If set the given NFS is mounted, i.e. `mount -o nolock -v ${NFS_TARGET} /mnt/restic`. `RESTIC_REPOSITORY` must remain it's default value!
|
||||
* `BACKUP_CRON` - A cron expression to run the backup. Note: cron daemon uses UTC time zone. Default: `0 */6 * * *` aka every 6 hours.
|
||||
* `RESTIC_FORGET_ARGS` - Optional. Only if specified `restic forget` is run with the given arguments after each backup. Example value: `-e "RESTIC_FORGET_ARGS=--prune --keep-last 10 --keep-hourly 24 --keep-daily 7 --keep-weekly 52 --keep-monthly 120 --keep-yearly 100"`
|
||||
* `RESTIC_JOB_ARGS` - Optional. Allows to specify extra arguments to the back up job such as limiting bandwith with `--limit-upload` or excluding file masks with `--exclude`.
|
||||
* `NFS_TARGET` - Optional. If set, the given NFS is mounted, i.e. `mount -o nolock -v ${NFS_TARGET} /mnt/restic`. `RESTIC_REPOSITORY` must remain its default value!
|
||||
* `BACKUP_CRON` - A cron expression to run the backup. Note: The cron daemon uses UTC time zone. Default: `0 */6 * * *` aka every 6 hours.
|
||||
* `CHECK_CRON` - Optional. A cron expression to run data integrity check (`restic check`). If left unset, data will not be checked. Note: The cron daemon uses UTC time zone. Example: `0 23 * * 3` to run 11PM every Tuesday.
|
||||
* `RESTIC_FORGET_ARGS` - Optional. Only if specified, `restic forget` is run with the given arguments after each backup. Example value: `-e "RESTIC_FORGET_ARGS=--prune --keep-last 10 --keep-hourly 24 --keep-daily 7 --keep-weekly 52 --keep-monthly 120 --keep-yearly 100"`
|
||||
* `RESTIC_INIT_ARGS` - Optional. Allows specifying extra arguments to `restic init` such as a password file with `--password-file`.
|
||||
* `RESTIC_JOB_ARGS` - Optional. Allows specifying extra arguments to the backup job such as limiting bandwith with `--limit-upload` or excluding file masks with `--exclude`.
|
||||
* `RESTIC_DATA_SUBSET` - Optional. You can pass a value to `--read-data-subset` when a repository check is run. If left unset, only the structure of the repository is verified. Note: `CHECK_CRON` must be set for check to be run automatically.
|
||||
* `AWS_ACCESS_KEY_ID` - Optional. When using restic with AWS S3 storage.
|
||||
* `AWS_SECRET_ACCESS_KEY` - Optional. When using restic with AWS S3 storage.
|
||||
* `MAILX_ARGS` - Optional. If specified, the content of `/var/log/backup-last.log` is sent via mail after each backup using an *external SMTP*. To have maximum flexibility, you have to specify the mail/smtp parameters by your own. Have a look at the [mailx manpage](https://linux.die.net/man/1/mailx) for further information. Example value: `-e "MAILX_ARGS=-r 'from@example.de' -s 'Result of the last restic backup run' -S smtp='smtp.example.com:587' -S smtp-use-starttls -S smtp-auth=login -S smtp-auth-user='username' -S smtp-auth-password='password' 'to@example.com'"`.
|
||||
* `TEAMS_WEBHOOK_URL` - Optional. If specified, the content of `/var/log/backup-last.log` and `/var/log/check-last.log` is sent to your Microsoft Teams channel after each backup and data integrity check.
|
||||
* `MAILX_ARGS` - Optional. If specified, the content of `/var/log/backup-last.log` and `/var/log/check-last.log` is sent via mail after each backup and data integrity check using an *external SMTP*. To have maximum flexibility, you have to specify the mail/smtp parameters on your own. Have a look at the [mailx manpage](https://linux.die.net/man/1/mailx) for further information. Example value: `-e "MAILX_ARGS=-r 'from@example.de' -s 'Result of the last restic run' -S smtp='smtp.example.com:587' -S smtp-use-starttls -S smtp-auth=login -S smtp-auth-user='username' -S smtp-auth-password='password' 'to@example.com'"`.
|
||||
* `OS_AUTH_URL` - Optional. When using restic with OpenStack Swift container.
|
||||
* `OS_PROJECT_ID` - Optional. When using restic with OpenStack Swift container.
|
||||
* `OS_PROJECT_NAME` - Optional. When using restic with OpenStack Swift container.
|
||||
* `OS_USER_DOMAIN_NAME` - Optional. When using restic with OpenStack Swift container.
|
||||
* `OS_PROJECT_DOMAIN_ID` - Optional. When using restic with OpenStack Swift container.
|
||||
* `OS_USERNAME` - Optional. When using restic with OpenStack Swift container.
|
||||
* `OS_PASSWORD` - Optional. When using restic with OpenStack Swift container.
|
||||
* `OS_REGION_NAME` - Optional. When using restic with OpenStack Swift container.
|
||||
* `OS_INTERFACE` - Optional. When using restic with OpenStack Swift container.
|
||||
* `OS_IDENTITY_API_VERSION` - Optional. When using restic with OpenStack Swift container.
|
||||
|
||||
## Volumes
|
||||
|
||||
@@ -85,13 +144,13 @@ The container is setup by setting [environment variables](https://docs.docker.co
|
||||
|
||||
## Set the hostname
|
||||
|
||||
Since restic saves the hostname with each snapshot and the hostname of a docker container is derived from it's id you might want to customize this by setting the hostname of the container to another value.
|
||||
Since restic saves the hostname with each snapshot and the hostname of a docker container is derived from its id, you might want to customize this by setting the hostname of the container to another value.
|
||||
|
||||
Set `--hostname` in the [network settings](https://docs.docker.com/engine/reference/run/#network-settings)
|
||||
|
||||
## Backup via SFTP
|
||||
|
||||
Since restic needs a **password less login** to the SFTP server make sure you can do `sftp user@host` from inside the container. If you can do so from your host system, the easiest way is to just mount your `.ssh` folder conaining the authorized cert into the container by specifying `-v ~/.ssh:/root/.ssh` as argument for `docker run`.
|
||||
Since restic needs a **passwordless login** to the SFTP server, make sure you can do `sftp user@host` from inside the container. If you can do so from your host system, the easiest way is to just mount your `.ssh` folder containing the authorized cert into the container by specifying `-v ~/.ssh:/root/.ssh` as an argument for `docker run`.
|
||||
|
||||
Now you can simply specify the restic repository to be an [SFTP repository](https://restic.readthedocs.io/en/stable/Manual/#create-an-sftp-repository).
|
||||
|
||||
@@ -99,16 +158,68 @@ Now you can simply specify the restic repository to be an [SFTP repository](http
|
||||
-e "RESTIC_REPOSITORY=sftp:user@host:/tmp/backup"
|
||||
```
|
||||
|
||||
## Backup via OpenStack Swift
|
||||
|
||||
Restic can back up data to an OpenStack Swift container. Because Swift supports various authentication methods, credentials are passed through environment variables. In order to help integration with existing OpenStack installations, the naming convention of those variables follows the official Python Swift client.
|
||||
|
||||
Now you can simply specify the restic repository to be a [Swift repository](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#openstack-swift).
|
||||
|
||||
```
|
||||
-e "RESTIC_REPOSITORY=swift:backup:/"
|
||||
-e "RESTIC_PASSWORD=password"
|
||||
-e "OS_AUTH_URL=https://auth.cloud.ovh.net/v3"
|
||||
-e "OS_PROJECT_ID=xxxx"
|
||||
-e "OS_PROJECT_NAME=xxxx"
|
||||
-e "OS_USER_DOMAIN_NAME=Default"
|
||||
-e "OS_PROJECT_DOMAIN_ID=default"
|
||||
-e "OS_USERNAME=username"
|
||||
-e "OS_PASSWORD=password"
|
||||
-e "OS_REGION_NAME=SBG"
|
||||
-e "OS_INTERFACE=public"
|
||||
-e "OS_IDENTITY_API_VERSION=3"
|
||||
```
|
||||
|
||||
## Backup via rclone
|
||||
|
||||
To use rclone as a backend for restic, simply add the rclone config file as a volume with `-v /absolute/path/to/rclone.conf:/root/.config/rclone/rclone.conf`.
|
||||
|
||||
# Versioning & Changelog
|
||||
Note that for some backends (Among them Google Drive and Microsoft OneDrive), rclone writes data back to the `rclone.conf` file. In this case it needs to be writable by Docker.
|
||||
|
||||
If the container fails to write the new `rclone.conf` file with the error message `Failed to save config after 10 tries: Failed to move previous config to backup location`, add the entire `rclone` directory as a volume: `-v /absolute/path/to/rclone-dir:/root/.config/rclone`.
|
||||
|
||||
## Example docker-compose
|
||||
|
||||
This is an example `docker-compose.yml`. The container will back up two directories to an SFTP server and check data integrity once a week.
|
||||
|
||||
```
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
restic:
|
||||
image: lobaro/restic-backup-docker:latest
|
||||
hostname: nas # This will be visible in restic snapshot list
|
||||
restart: always
|
||||
privileged: true
|
||||
volumes:
|
||||
- /volume1/Backup:/data/Backup:ro # Backup /volume1/Backup from host
|
||||
- /home/user:/data/home:ro # Backup /home/user from host
|
||||
- ./post-backup.sh:/hooks/post-backup.sh:ro # Run script post-backup.sh after every backup
|
||||
- ./post-check.sh:/hooks/post-check.sh:ro # Run script post-check.sh after every check
|
||||
- ./ssh:/root/.ssh # SSH keys and config so we can login to "storageserver" without password
|
||||
environment:
|
||||
- RESTIC_REPOSITORY=sftp:storageserver:/storage/nas # Backup to server "storageserver"
|
||||
- RESTIC_PASSWORD=passwordForRestic # Password restic uses for encryption
|
||||
- BACKUP_CRON=0 22 * * 0 # Start backup every Sunday 22:00 UTC
|
||||
- CHECK_CRON=0 22 * * 3 # Start check every Wednesday 22:00 UTC
|
||||
- RESTIC_DATA_SUBSET=50G # Download 50G of data from "storageserver" every Wednesday 22:00 UTC and check the data integrity
|
||||
- RESTIC_FORGET_ARGS=--prune --keep-last 12 # Only keep the last 12 snapshots
|
||||
```
|
||||
|
||||
# Versioning
|
||||
|
||||
Starting from v1.3.0 versioning follows [Semantic versioning](http://semver.org/)
|
||||
|
||||
Build metadata is used to declare the Restic version.
|
||||
|
||||
**Example:** 1.3.0+0.9.5 (includes Restic 0.9.5)
|
||||
**Example:** v1.3.2+restic-0-16-0 (includes Restic 0.16.0)
|
||||
|
||||
For changelog see: https://github.com/lobaro/restic-backup-docker/releases
|
||||
|
||||
42
backup.sh
42
backup.sh
@@ -2,6 +2,7 @@
|
||||
|
||||
lastLogfile="/var/log/backup-last.log"
|
||||
lastMailLogfile="/var/log/mail-last.log"
|
||||
lastMicrosoftTeamsLogfile="/var/log/microsoft-teams-last.log"
|
||||
|
||||
copyErrorLog() {
|
||||
cp ${lastLogfile} /var/log/backup-error-last.log
|
||||
@@ -11,6 +12,13 @@ logLast() {
|
||||
echo "$1" >> ${lastLogfile}
|
||||
}
|
||||
|
||||
if [ -f "/hooks/pre-backup.sh" ]; then
|
||||
echo "Starting pre-backup script ..."
|
||||
/hooks/pre-backup.sh
|
||||
else
|
||||
echo "Pre-backup script not found ..."
|
||||
fi
|
||||
|
||||
start=`date +%s`
|
||||
rm -f ${lastLogfile} ${lastMailLogfile}
|
||||
echo "Starting Backup at $(date +"%Y-%m-%d %H:%M:%S")"
|
||||
@@ -24,24 +32,23 @@ logLast "AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}"
|
||||
|
||||
# Do not save full backup log to logfile but to backup-last.log
|
||||
restic backup /data ${RESTIC_JOB_ARGS} --tag=${RESTIC_TAG?"Missing environment variable RESTIC_TAG"} >> ${lastLogfile} 2>&1
|
||||
rc=$?
|
||||
backupRC=$?
|
||||
logLast "Finished backup at $(date)"
|
||||
if [[ $rc == 0 ]]; then
|
||||
echo "Backup Successfull"
|
||||
if [[ $backupRC == 0 ]]; then
|
||||
echo "Backup Successful"
|
||||
else
|
||||
echo "Backup Failed with Status ${rc}"
|
||||
echo "Backup Failed with Status ${backupRC}"
|
||||
restic unlock
|
||||
copyErrorLog
|
||||
kill 1
|
||||
fi
|
||||
|
||||
if [ -n "${RESTIC_FORGET_ARGS}" ]; then
|
||||
if [[ $backupRC == 0 ]] && [ -n "${RESTIC_FORGET_ARGS}" ]; then
|
||||
echo "Forget about old snapshots based on RESTIC_FORGET_ARGS = ${RESTIC_FORGET_ARGS}"
|
||||
restic forget ${RESTIC_FORGET_ARGS} >> ${lastLogfile} 2>&1
|
||||
rc=$?
|
||||
logLast "Finished forget at $(date)"
|
||||
if [[ $rc == 0 ]]; then
|
||||
echo "Forget Successfull"
|
||||
echo "Forget Successful"
|
||||
else
|
||||
echo "Forget Failed with Status ${rc}"
|
||||
restic unlock
|
||||
@@ -52,11 +59,30 @@ fi
|
||||
end=`date +%s`
|
||||
echo "Finished Backup at $(date +"%Y-%m-%d %H:%M:%S") after $((end-start)) seconds"
|
||||
|
||||
if [ -n "${TEAMS_WEBHOOK_URL}" ]; then
|
||||
teamsTitle="Restic Last Backup Log"
|
||||
teamsMessage=$( cat ${lastLogfile} | sed 's/"/\"/g' | sed "s/'/\'/g" | sed ':a;N;$!ba;s/\n/\n\n/g' )
|
||||
teamsReqBody="{\"title\": \"${teamsTitle}\", \"text\": \"${teamsMessage}\" }"
|
||||
sh -c "curl -H 'Content-Type: application/json' -d '${teamsReqBody}' '${TEAMS_WEBHOOK_URL}' > ${lastMicrosoftTeamsLogfile} 2>&1"
|
||||
if [ $? == 0 ]; then
|
||||
echo "Microsoft Teams notification successfully sent."
|
||||
else
|
||||
echo "Sending Microsoft Teams notification FAILED. Check ${lastMicrosoftTeamsLogfile} for further information."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "${MAILX_ARGS}" ]; then
|
||||
sh -c "mailx -v -S sendwait ${MAILX_ARGS} < ${lastLogfile} > ${lastMailLogfile} 2>&1"
|
||||
sh -c "mail -v -S sendwait ${MAILX_ARGS} < ${lastLogfile} > ${lastMailLogfile} 2>&1"
|
||||
if [ $? == 0 ]; then
|
||||
echo "Mail notification successfully sent."
|
||||
else
|
||||
echo "Sending mail notification FAILED. Check ${lastMailLogfile} for further information."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "/hooks/post-backup.sh" ]; then
|
||||
echo "Starting post-backup script ..."
|
||||
/hooks/post-backup.sh $backupRC
|
||||
else
|
||||
echo "Post-backup script not found ..."
|
||||
fi
|
||||
|
||||
76
check.sh
Executable file
76
check.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/bin/sh
|
||||
|
||||
lastLogfile="/var/log/check-last.log"
|
||||
lastMailLogfile="/var/log/check-mail-last.log"
|
||||
lastMicrosoftTeamsLogfile="/var/log/check-microsoft-teams-last.log"
|
||||
|
||||
copyErrorLog() {
|
||||
cp ${lastLogfile} /var/log/check-error-last.log
|
||||
}
|
||||
|
||||
logLast() {
|
||||
echo "$1" >> ${lastLogfile}
|
||||
}
|
||||
|
||||
if [ -f "/hooks/pre-check.sh" ]; then
|
||||
echo "Starting pre-check script ..."
|
||||
/hooks/pre-check.sh
|
||||
else
|
||||
echo "Pre-check script not found ..."
|
||||
fi
|
||||
|
||||
start=`date +%s`
|
||||
rm -f ${lastLogfile} ${lastMailLogfile}
|
||||
echo "Starting Check at $(date +"%Y-%m-%d %H:%M:%S")"
|
||||
echo "Starting Check at $(date)" >> ${lastLogfile}
|
||||
logLast "CHECK_CRON: ${CHECK_CRON}"
|
||||
logLast "RESTIC_DATA_SUBSET: ${RESTIC_DATA_SUBSET}"
|
||||
logLast "RESTIC_REPOSITORY: ${RESTIC_REPOSITORY}"
|
||||
logLast "AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}"
|
||||
|
||||
# Do not save full check log to logfile but to check-last.log
|
||||
if [ -n "${RESTIC_DATA_SUBSET}" ]; then
|
||||
restic check --read-data-subset=${RESTIC_DATA_SUBSET} >> ${lastLogfile} 2>&1
|
||||
else
|
||||
restic check >> ${lastLogfile} 2>&1
|
||||
fi
|
||||
checkRC=$?
|
||||
logLast "Finished check at $(date)"
|
||||
if [[ $checkRC == 0 ]]; then
|
||||
echo "Check Successful"
|
||||
else
|
||||
echo "Check Failed with Status ${checkRC}"
|
||||
restic unlock
|
||||
copyErrorLog
|
||||
fi
|
||||
|
||||
end=`date +%s`
|
||||
echo "Finished Check at $(date +"%Y-%m-%d %H:%M:%S") after $((end-start)) seconds"
|
||||
|
||||
if [ -n "${TEAMS_WEBHOOK_URL}" ]; then
|
||||
teamsTitle="Restic Last Check Log"
|
||||
teamsMessage=$( cat ${lastLogfile} | sed 's/"/\"/g' | sed "s/'/\'/g" | sed ':a;N;$!ba;s/\n/\n\n/g' )
|
||||
teamsReqBody="{\"title\": \"${teamsTitle}\", \"text\": \"${teamsMessage}\" }"
|
||||
sh -c "curl -H 'Content-Type: application/json' -d '${teamsReqBody}' '${TEAMS_WEBHOOK_URL}' > ${lastMicrosoftTeamsLogfile} 2>&1"
|
||||
if [ $? == 0 ]; then
|
||||
echo "Microsoft Teams notification successfully sent."
|
||||
else
|
||||
echo "Sending Microsoft Teams notification FAILED. Check ${lastMicrosoftTeamsLogfile} for further information."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "${MAILX_ARGS}" ]; then
|
||||
sh -c "mail -v -S sendwait ${MAILX_ARGS} < ${lastLogfile} > ${lastMailLogfile} 2>&1"
|
||||
if [ $? == 0 ]; then
|
||||
echo "Mail notification successfully sent."
|
||||
else
|
||||
echo "Sending mail notification FAILED. Check ${lastMailLogfile} for further information."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "/hooks/post-check.sh" ]; then
|
||||
echo "Starting post-check script ..."
|
||||
/hooks/post-check.sh $checkRC
|
||||
else
|
||||
echo "Post-check script not found ..."
|
||||
fi
|
||||
20
entry.sh
20
entry.sh
@@ -1,25 +1,19 @@
|
||||
#!bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
echo "Starting container ..."
|
||||
|
||||
RESTIC_CMD=restic
|
||||
|
||||
if [ -n "${ROOT_CERT}" ]; then
|
||||
RESTIC_CMD="${RESTIC_CMD} --cert ${ROOT_CERT}"
|
||||
fi
|
||||
|
||||
if [ -n "${NFS_TARGET}" ]; then
|
||||
echo "Mounting NFS based on NFS_TARGET: ${NFS_TARGET}"
|
||||
mount -o nolock -v ${NFS_TARGET} /mnt/restic
|
||||
fi
|
||||
|
||||
restic snapshots &>/dev/null
|
||||
restic snapshots ${RESTIC_INIT_ARGS} &>/dev/null
|
||||
status=$?
|
||||
echo "Check Repo status $status"
|
||||
|
||||
if [ $status != 0 ]; then
|
||||
echo "Restic repository '${RESTIC_REPOSITORY}' does not exists. Running restic init."
|
||||
restic init
|
||||
restic init ${RESTIC_INIT_ARGS}
|
||||
|
||||
init_status=$?
|
||||
echo "Repo init status $init_status"
|
||||
@@ -33,7 +27,13 @@ fi
|
||||
|
||||
|
||||
echo "Setup backup cron job with cron expression BACKUP_CRON: ${BACKUP_CRON}"
|
||||
echo "${BACKUP_CRON} /bin/backup >> /var/log/cron.log 2>&1" > /var/spool/cron/crontabs/root
|
||||
echo "${BACKUP_CRON} /usr/bin/flock -n /var/run/backup.lock /bin/backup >> /var/log/cron.log 2>&1" > /var/spool/cron/crontabs/root
|
||||
|
||||
# If CHECK_CRON is set we will enable automatic backup checking
|
||||
if [ -n "${CHECK_CRON}" ]; then
|
||||
echo "Setup check cron job with cron expression CHECK_CRON: ${CHECK_CRON}"
|
||||
echo "${CHECK_CRON} /usr/bin/flock -n /var/run/backup.lock /bin/check >> /var/log/cron.log 2>&1" >> /var/spool/cron/crontabs/root
|
||||
fi
|
||||
|
||||
# Make sure the file exists before we start tail
|
||||
touch /var/log/cron.log
|
||||
|
||||
Reference in New Issue
Block a user