159 lines
5.1 KiB
Markdown
159 lines
5.1 KiB
Markdown
# Zorruno Docker Backup Scripts
|
|
|
|
Modular backup scripts for Docker Compose servers such as Panda and Beaver.
|
|
Each server has its own untracked `.env` and `containers.txt`, while all script
|
|
logic remains common and can be updated through Git.
|
|
|
|
## Pipeline
|
|
|
|
`backup.sh` runs these stages in order:
|
|
|
|
1. `stages/10-containers.sh` — stop, archive, pull, start and verify projects.
|
|
2. `methods/20-rclone.sh` — copy archives to an rclone destination when enabled.
|
|
3. `methods/30-smb.sh` — copy archives to a mounted SMB share when enabled.
|
|
4. `stages/90-prune.sh` — retain the newest configured number of `.zst`
|
|
archives locally, including legacy `.zst` and current `.tar.zst` names.
|
|
|
|
Every stage can also be run directly. The old `docker-backup.sh` name invokes
|
|
the container archive stage, while `dockerbackup_prune.sh` invokes the local
|
|
prune stage. Use the new `backup.sh` for the complete pipeline.
|
|
|
|
## Requirements
|
|
|
|
- Bash 4 or later
|
|
- Docker with `docker compose`, or legacy `docker-compose`
|
|
- GNU `tar` with zstd support
|
|
- `flock`
|
|
- `rclone` only when the rclone method is enabled
|
|
- `rsync` and `mountpoint` only when the SMB method is enabled
|
|
|
|
The account running the scripts must be allowed to control Docker and read all
|
|
files under `/dockervolumes`.
|
|
|
|
## Installation on Beaver
|
|
|
|
```bash
|
|
sudo git clone https://home.fox.co.nz/gitea/zorruno/zorruno-backupdockerscript.git /backupdockerscripts
|
|
cd /backupdockerscripts
|
|
sudo cp .env.example .env
|
|
sudo cp containers.txt containers.local.txt
|
|
sudo chmod 600 .env
|
|
sudo chmod +x backup.sh docker-backup.sh dockerbackup_prune.sh stages/*.sh methods/*.sh
|
|
```
|
|
|
|
Edit `.env`. Beaver's Docker source is already represented by:
|
|
|
|
```bash
|
|
SOURCE_BASE_DIR="/dockervolumes"
|
|
BACKUP_HOSTNAME="beaver"
|
|
```
|
|
|
|
Choose and create a local staging path for `BACKUP_ROOT`. `/dockerbackups` is
|
|
the default, but it should be on a filesystem with enough free space to hold
|
|
at least `KEEP_COUNT` copies of every listed project.
|
|
|
|
Edit Beaver's untracked `containers.local.txt`. Each active line can be either a running
|
|
container name or a directory name beneath `/dockervolumes`. Blank lines and
|
|
text after `#` are ignored. If several entries resolve to the same Compose
|
|
project directory, that project is backed up only once. Keeping this host-local
|
|
file out of Git prevents a pull on Panda or Beaver from replacing its list.
|
|
|
|
## Configuration
|
|
|
|
Copy `.env.example` to `.env`; `.env` is ignored by Git. Important values:
|
|
|
|
| Variable | Purpose |
|
|
|---|---|
|
|
| `SOURCE_BASE_DIR` | Parent of Compose project directories |
|
|
| `BACKUP_ROOT` | Local archive staging and retention tree |
|
|
| `CONTAINERS_FILE` | Absolute path, or path relative to this repository |
|
|
| `BACKUP_HOSTNAME` | Host folder/name embedded in archive filenames |
|
|
| `BACKUP_METHODS` | Ordered method names, default `rclone smb` |
|
|
| `ZSTD_EXTRA_OPTS` | Options passed to `zstd`, default `-T0 -12` |
|
|
| `KEEP_COUNT` | Local archives retained per Compose project |
|
|
| `PULL_IMAGES` | Pull images before restarting (`1` or `0`) |
|
|
|
|
### Rclone
|
|
|
|
```bash
|
|
RCLONE_ENABLED=1
|
|
RCLONE_REMOTE="gdrive:dockerbackups"
|
|
```
|
|
|
|
Archives are copied beneath `<remote>/<BACKUP_HOSTNAME>/`. The method uses
|
|
`rclone copy`, so it does not delete older destination files. Set
|
|
`RCLONE_HOST_SUBDIR=0` when `RCLONE_REMOTE` already names the final host-specific
|
|
destination; otherwise the host name is appended automatically.
|
|
|
|
### SMB
|
|
|
|
Mount the SMB share through `/etc/fstab` or a systemd mount unit; do not put SMB
|
|
credentials in this repository. Then configure:
|
|
|
|
```bash
|
|
SMB_ENABLED=1
|
|
SMB_MOUNT="/mnt/dockerbackups"
|
|
SMB_HOST_SUBDIR=1
|
|
```
|
|
|
|
The script refuses to copy unless `SMB_MOUNT` is an actual mount point. This
|
|
prevents a failed network mount from silently filling the server's root disk.
|
|
|
|
## Running
|
|
|
|
Run the complete pipeline:
|
|
|
|
```bash
|
|
sudo /backupdockerscripts/backup.sh
|
|
```
|
|
|
|
Preview all stages without stopping containers, copying, or deleting:
|
|
|
|
```bash
|
|
sudo /backupdockerscripts/backup.sh --dry-run
|
|
```
|
|
|
|
Run individual parts:
|
|
|
|
```bash
|
|
sudo stages/10-containers.sh --dry-run
|
|
sudo methods/20-rclone.sh --dry-run --force
|
|
sudo methods/30-smb.sh --dry-run --force
|
|
sudo stages/90-prune.sh --dry-run
|
|
```
|
|
|
|
`--force` runs a transfer method even when its `*_ENABLED` value is false. It
|
|
still requires the method's destination to be configured and available.
|
|
|
|
## Adding another backup method
|
|
|
|
Add an executable script named `methods/NN-name.sh`, for example
|
|
`methods/40-restic.sh`. It should load `lib/common.sh`, accept `--dry-run`, and
|
|
return a non-zero status on failure. Add its short name to `.env`:
|
|
|
|
```bash
|
|
BACKUP_METHODS="rclone smb restic"
|
|
```
|
|
|
|
The main pipeline discovers the numbered file from the short name and runs it
|
|
after the earlier methods. A failed method stops the pipeline, so pruning will
|
|
not run after a failed transfer.
|
|
|
|
## Archive and restore format
|
|
|
|
Archives are stored as:
|
|
|
|
```text
|
|
<BACKUP_ROOT>/<project>/<host>.<project>.<date_time>.tar.zst
|
|
```
|
|
|
|
Each archive contains the project's top-level directory rather than absolute
|
|
paths. Example restore into an empty temporary directory:
|
|
|
|
```bash
|
|
mkdir -p /tmp/docker-restore
|
|
tar --zstd -xf backup.tar.zst -C /tmp/docker-restore
|
|
```
|
|
|
|
Inspect and verify restored content before replacing a live project.
|