mirror of
https://github.com/Steffo99/backup-duplicity.git
synced 2024-12-21 11:14:19 +00:00
v0.1.0
This commit is contained in:
commit
501e421357
7 changed files with 208 additions and 0 deletions
11
.github/workflows/release.yml
vendored
Normal file
11
.github/workflows/release.yml
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
name: "Release new version"
|
||||
|
||||
on:
|
||||
# Creation of a new tag starting with v
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
ghcrio:
|
||||
uses: Steffo99/.github/.github/workflows/buildrelease-docker.yml@main
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "duplicity"]
|
||||
path = duplicity
|
||||
url = https://gitlab.com/duplicity/duplicity.git
|
32
Dockerfile
Normal file
32
Dockerfile
Normal file
|
@ -0,0 +1,32 @@
|
|||
# FROM archlinux:latest
|
||||
FROM alpine:latest
|
||||
|
||||
# Install duplicity
|
||||
# RUN pacman --noconfirm -Syu duplicity python-pip python-pydrive2
|
||||
RUN apk add duplicity
|
||||
RUN apk add py3-pip
|
||||
RUN apk add python3-dev
|
||||
RUN apk add gcc
|
||||
RUN apk add libffi-dev
|
||||
RUN apk add musl-dev
|
||||
RUN pip install pydrive2
|
||||
|
||||
WORKDIR /var/lib/duplicity
|
||||
ENV HOME="/var/lib/duplicity"
|
||||
|
||||
# Configure entrypoint and command
|
||||
ENTRYPOINT ["crond", "-f", "-d", "5"]
|
||||
CMD []
|
||||
|
||||
# Add image labels
|
||||
LABEL org.opencontainers.image.title="docker-backup-duplicity"
|
||||
LABEL org.opencontainers.image.description="Backup solution for Docker volumes based on Duplicity"
|
||||
LABEL org.opencontainers.image.licenses="AGPL-3.0-or-later"
|
||||
LABEL org.opencontainers.image.url="https://github.com/Steffo99/docker-backup-duplicity"
|
||||
LABEL org.opencontainers.image.authors="Stefano Pigozzi <me@steffo.eu>"
|
||||
|
||||
# Add duplicity to cron
|
||||
COPY ./backup.sh /etc/periodic/daily/backup.sh
|
||||
|
||||
# Configure duplicity
|
||||
ENV DUPLICITY_FULL_IF_OLDER_THAN=1M
|
103
README.md
Normal file
103
README.md
Normal file
|
@ -0,0 +1,103 @@
|
|||
# docker-backup-duplicity
|
||||
|
||||
Backup solution for Docker volumes based on Duplicity
|
||||
|
||||
## Usage
|
||||
|
||||
> **Note**: The following instructions assume Google Drive is used as a storage backend; refer to [duplicity's man page](https://duplicity.us/stable/duplicity.1.html) to find out how to configure different backends!
|
||||
|
||||
1. Create a new volume in Docker with the name `duplicity_credentials`:
|
||||
|
||||
```console
|
||||
# docker volume create duplicity_credentials
|
||||
```
|
||||
|
||||
2. Create a new file in the host system with the name `/root/secrets/backup/passphrase.txt`, and enter in it a secure passphrase to use to encrypt files:
|
||||
|
||||
```console
|
||||
# echo 'CorrectHorseBatteryStaple' >> /root/secrets/backup/passphrase.txt
|
||||
```
|
||||
|
||||
3. [Obtain *Desktop Application* OAuth credentials from the Google Cloud Console.](https://console.cloud.google.com/apis/credentials)
|
||||
|
||||
4. Create a new file in the host system with the name `/root/secrets/backup/client_config.yml`, and enter the following content in it:
|
||||
|
||||
```console
|
||||
# edit /root/secrets/backup/client_config.yml
|
||||
```
|
||||
|
||||
```yml
|
||||
client_config_backend: settings
|
||||
client_config:
|
||||
client_id: "YOUR_GOOGLE_CLIENT_ID_GOES_HERE"
|
||||
client_secret: "YOUR_GOOGLE_CLIENT_SECRET_GOES_HERE"
|
||||
save_credentials: True
|
||||
save_credentials_backend: file
|
||||
save_credentials_file: "/var/lib/duplicity/credentials"
|
||||
get_refresh_token: True
|
||||
```
|
||||
|
||||
5. Add the following keys to the `docker-compose.yml` file of the project you want to backup:
|
||||
|
||||
```console
|
||||
# edit ./docker-compose.yml
|
||||
```
|
||||
|
||||
1. If you haven't already, upgrade your `docker-compose.yml` file to version 3.9:
|
||||
|
||||
```yml
|
||||
version: "3.9"
|
||||
```
|
||||
|
||||
2. Connect the previously created `duplicity_credentials` volume to the project:
|
||||
|
||||
```yml
|
||||
volumes:
|
||||
duplicity_credentials:
|
||||
external: true
|
||||
```
|
||||
|
||||
3. Setup the two previously created files as Docker secrets:
|
||||
|
||||
```yml
|
||||
secrets:
|
||||
duplicity_passphrase:
|
||||
file: "/root/secrets/backup/passphrase.txt"
|
||||
google_client_config:
|
||||
file: "/root/secrets/backup/client_config.yml"
|
||||
```
|
||||
|
||||
4. Add the following service:
|
||||
|
||||
```yml
|
||||
services:
|
||||
backup:
|
||||
image: "ghcr.io/steffo99/backup-duplicity:latest"
|
||||
restart: unless-stopped
|
||||
secrets:
|
||||
- google_client_config
|
||||
- duplicity_passphrase
|
||||
volumes:
|
||||
- "duplicity_credentials:/var/lib/duplicity"
|
||||
# Mount whatever you want to backup in subdirectories of /mnt
|
||||
- ".:/mnt/compose" # Backup the current directory?
|
||||
- "data:/mnt/data" # Backup a named volume?
|
||||
environment:
|
||||
MODE: "backup" # Change this to "restore" to restore the latest backup
|
||||
DUPLICITY_TARGET_URL: "pydrive://YOUR_GOOGLE_CLIENT_ID_GOES_HERE/Duplicity/this" # Change this to the Drive directory you want to backup files to https://man.archlinux.org/man/duplicity.1.en#URL_FORMAT
|
||||
# Don't touch these, they allow the program to read the secrets
|
||||
DUPLICITY_PASSPHRASE_FILE: "/run/secrets/duplicity_passphrase"
|
||||
GOOGLE_DRIVE_SETTINGS: "/run/secrets/google_client_config"
|
||||
```
|
||||
|
||||
6. Log in to Google Drive and perform an initial backup with:
|
||||
|
||||
```console
|
||||
# docker compose run -i backup --entrypoint=/bin/sh /etc/periodic/daily/backup.sh
|
||||
```
|
||||
|
||||
7. Properly start the container with:
|
||||
|
||||
```console
|
||||
# docker compose up -d && docker compose logs -f
|
||||
```
|
30
backup.sh
Normal file
30
backup.sh
Normal file
|
@ -0,0 +1,30 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Get secrets from files
|
||||
# Insecure, but there's not much I can do about it
|
||||
# It's duplicity's fault!
|
||||
export PASSPHRASE=$(cat ${DUPLICITY_PASSPHRASE_FILE})
|
||||
|
||||
case "$MODE" in
|
||||
backup)
|
||||
echo "Launched in backup mode, performing backup..." >> /dev/stderr
|
||||
duplicity \
|
||||
--allow-source-mismatch \
|
||||
--full-if-older-than ${DUPLICITY_FULL_IF_OLDER_THAN} \
|
||||
/mnt \
|
||||
${DUPLICITY_TARGET_URL}
|
||||
;;
|
||||
restore)
|
||||
echo "Launched in restore mode, restoring backup..." >> /dev/stderr
|
||||
duplicity \
|
||||
--force \
|
||||
--allow-source-mismatch \
|
||||
${DUPLICITY_TARGET_URL} \
|
||||
/mnt
|
||||
;;
|
||||
*)
|
||||
echo "No such mode." >> /dev/stderr
|
||||
;;
|
||||
esac
|
0
example/.gitignore
vendored
Normal file
0
example/.gitignore
vendored
Normal file
29
test.docker-compose.yml
Normal file
29
test.docker-compose.yml
Normal file
|
@ -0,0 +1,29 @@
|
|||
version: "3.9"
|
||||
|
||||
secrets:
|
||||
google_client_config:
|
||||
file: "/root/secrets/backup/client_config.yml"
|
||||
duplicity_passphrase:
|
||||
file: "/root/secrets/backup/passphrase.txt"
|
||||
|
||||
volumes:
|
||||
duplicity_credentials:
|
||||
external: true
|
||||
|
||||
services:
|
||||
backup:
|
||||
image: "ghcr.io/steffo99/backup-duplicity:latest"
|
||||
entrypoint: "/bin/sh"
|
||||
command: "/etc/periodic/daily/backup.sh"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- "./example:/mnt/example"
|
||||
- "duplicity_credentials:/var/lib/duplicity"
|
||||
environment:
|
||||
MODE: "backup"
|
||||
DUPLICITY_PASSPHRASE_FILE: "/run/secrets/duplicity_passphrase"
|
||||
DUPLICITY_TARGET_URL: "pydrive://641079776729-90s4tnli0ao913ajrpv8cp3c4kkk77j5.apps.googleusercontent.com/Duplicity/this"
|
||||
GOOGLE_DRIVE_SETTINGS: "/run/secrets/google_client_config"
|
||||
secrets:
|
||||
- google_client_config
|
||||
- duplicity_passphrase
|
Loading…
Reference in a new issue