Compare commits

..

11 Commits

4 changed files with 171 additions and 81 deletions

View File

@@ -13,6 +13,7 @@ A script to backup docker volumes and stack configuration on the servers.
1. Copies the result to the `/backups` folder.
1. Cleans up / removes temporary directory that was created.
1. Restarts all the services.
1. Removes backups older than 7 days.
## Setup
@@ -21,7 +22,7 @@ stored in. This is done by editing the `/etc/fstab` file, and adding the
following line.
```bash
//<nas_ip>/docker/backups/<machine> /backups cifs credentials=/home/michael/smbcredentials,uid=0,gid=0 0 0
//<nas_ip>/docker/backups/<machine> /backups cifs credentials=/path/to/smbcredentials,uid=0,gid=0 0 0
```
Once that is done:
@@ -30,6 +31,26 @@ Once that is done:
1. Reload the daemon `sudo systemctl daemon-reload`
1. Mount the folder `sudo mount -a`
### Automated Installation Script
This repository has an automated installation script that can be ran.
```bash
sudo su -c "bash <(wget -qO- https://git.housh.dev/homelab/backup/raw/branch/main/install.sh)" root
```
## Manual Installation
See [installation
script](https://git.housh.dev/homelab/backup/src/branch/main/install.sh).
### Setup the backup script
```bash
sudo wget "https://git.housh.dev/homelab/backup/raw/branch/main/docker-backup.sh" -O /usr/local/bin/docker-backup
sudo chmod +x /usr/local/bin/docker-backup
```
### Systemd Setup
Setup the systemd service and timer, so that backups are ran once a day @ 3 a.m.
@@ -44,20 +65,23 @@ sudo systemctl start backup.service
```
### Setup the backup script
1. Download the script `wget https://git.housh.dev/homelab/backup/raw/branch/main/docker-backup.sh`
1. Add any extra volumes to backup.
1. Make script executable `chmod +x docker-backup.sh`
1. Manually run the script `sudo ./docker-backup.sh`
## Restore
This repository also contains a restore script that can restore the stacks and
The backup script also contains a restore command that can restore the stacks and
volumes from a backup (hopefully it's never needed!).
### Usage
1. Download the script `wget https://git.housh.dev/homelab/backup/raw/branch/main/docker-restore.sh`
1. Make script executable `chmod +x docker-restore.sh`
1. Run the script `sudo ./docker-restore.sh /backups/<backup>.tar.gz`
You can use the restore command without an argument to use the last backup as
the archive to restore from.
```bash
sudo docker-backup restore
```
Or if you'd like to restore using a specific archive then you can pass in
argument that contains the path to the backup archive to use.
```bash
sudo docker-backup restore /backups/2025-04-21.tar.gz
```

View File

@@ -1,18 +1,44 @@
#!/bin/bash
function usage() {
cat <<EOF
docker-backup [options] [command] [args...]
COMMNADS:
run: Create a new backup (default if no options or command is passed)
restart: Restart all docker stacks.
restore: Restore from a backup, accepts argument which is path to an archive, if
no argument is supplied, then it will use the latest backup found.
OPTIONS:
-h | --help: Show this message.
--version: Show the version.
EOF
}
# ==================================================
# Variables
# ==================================================
debug=${DEBUG:-}
version=1.0.1
today=$(date +'%F')
stackdir="/etc/komodo/stacks"
backupdir="/backups"
services=()
readarray -d '' services < <(find "$stackdir" -maxdepth 1 -mindepth 1 -type d)
services=($(find "$stackdir" -maxdepth 1 -mindepth 1 -type d))
# Directories to backup.
volumes=(
"/var/lib/docker/volumes"
"/opt"
)
# ==================================================
# Helpers
# ==================================================
function stopServices() {
echo "Stopping services..."
for service in "${services[@]}"; do
@@ -27,8 +53,8 @@ function startServices() {
done
}
function copyStacks() {
echo "Copying stack configuration..."
function backupStacks() {
echo "Backing up stacks..."
local dir="$1/stacks"
mkdir "$dir"
for service in "${services[@]}"; do
@@ -36,14 +62,12 @@ function copyStacks() {
done
}
function copyVolumes() {
echo "Copying volumes..."
function backupVolumes() {
echo "Backing up volumes..."
local dir="$1/volumes"
mkdir "$dir"
for volume in "${volumes[@]}"; do
# copy only directories.
find "$volume" -maxdepth 1 -mindepth 1 -type d -print0 |
xargs -0 -I {} cp -r --parents "$volume" "{}"
cp -r --parents "$volume" "$dir"
done
}
@@ -58,11 +82,39 @@ function backup() {
function cleanBackups() {
echo "Removing old backups..."
# Remove backups older than 7 days.
find "$backupdir" -maxdepth 1 -mindepth 1 -name "*.tar.gz" -mtime +7 -print0 |
xargs -0 -I {} rm -rf "{}"
local dirs=($(find "$backupdir" -maxdepth 1 -mindepth 1 -name "*.tar.gz" -mtime +7))
for dir in "${dirs[@]}"; do
rm -rf "$dir"
done
}
function main() {
function copyIfNotDebug {
if [ -z "$debug" ]; then
cp -r "$1" "$2"
else
echo "$1 -> $2"
fi
}
function restoreVolumes() {
echo "Copying volumes..."
local volumes=($(find "$1/volumes" -maxdepth 1 -mindepth 1 -type d))
for volume in "${volumes[@]}"; do
local dest="${volume#"$1"/volumes*}"
copyIfNotDebug "$volume" "$dest"
done
}
function restoreStacks() {
echo "Copying stacks..."
local stacks=($(find "$1/stacks" -maxdepth 1 -mindepth 1 -type d))
for stack in "${stacks[@]}"; do
local dest="${stack#"$1"/stacks*}"
copyIfNotDebug "$stack" "$dest"
done
}
function run() {
# stop services.
stopServices
@@ -71,10 +123,10 @@ function main() {
mkdir "$temp"
# copy stack configuration.
copyStacks "$temp"
backupStacks "$temp"
# copy stack configuration.
copyVolumes "$temp"
backupVolumes "$temp"
# Create a tar to backup.
backup "$temp"
@@ -86,4 +138,56 @@ function main() {
cleanBackups
}
function restore() {
# Parse the backup to use, if an argument is passed in use that as the source
# for the backup, otherwise use the last backup.
local archive="$1"
if [ -z "$archive" ]; then
echo "Backup not specified using latest backup..."
archive=$(find /backups -maxdepth 1 -mindepth 1 -name "*.tar.gz" | sort -nr | head -1)
fi
local dir="${archive%*.tar.gz}"
# unzip the archive.
echo "Unzipping backup: $archive"
tar -xvf "$archive"
# copy stacks and volumes to their locations.
restoreVolumes "$dir"
restoreStacks "$dir"
# cleanup
rm -rf "$dir"
echo "Restarting services..."
startServices
}
# ==================================================
# MAIN
# ==================================================
function main() {
case "$1" in
-h | --help)
usage && return 0
;;
--version)
echo "$version" && return 0
;;
restart)
startServices && return 0
;;
restore)
shift && restore "$@" && return 0
;;
*)
run "$@" && return 0
;;
esac
}
main "$@"

View File

@@ -1,46 +0,0 @@
#!/bin/bash
debug=${DEBUG:-}
function copyIfNotDebug {
if [ -z "$debug" ]; then
cp -r "$1" "$2"
else
echo "$1 -> $2"
fi
}
function copyVolumes() {
echo "Copying volumes..."
local volumes=($(find "$1/volumes" -maxdepth 1 -mindepth 1 -type d))
for volume in "${volumes[@]}"; do
local dest="${volume#"$1"/volumes*}"
copyIfNotDebug "$volume" "$dest"
done
}
function copyStacks() {
echo "Copying stacks..."
local stacks=($(find "$1/stacks" -maxdepth 1 -mindepth 1 -type d))
for stack in "${stacks[@]}"; do
local dest="${stack#"$1"/stacks*}"
copyIfNotDebug "$stack" "$dest"
done
}
function main() {
local archive="$1"
local dir="${archive%*.tar.gz}"
# unzip the archive.
tar -xvf "$archive"
# copy stacks and volumes to their locations.
copyVolumes "$dir"
copyStacks "$dir"
# cleanup
rm -rf "$dir"
}
main "$@"

View File

@@ -4,8 +4,21 @@ baseurl="https://git.housh.dev/homelab/backup/raw/branch/main"
systemdir="/etc/systemd/system"
bindir="/usr/local/bin"
function downloadScripts() {
local script="docker-backup"
# set the destination of the script.
local dest="$bindir/$script"
# Remove the file if it exists.
[ -f "$dest" ] && rm -f "$dest"
# download the script to the destination.
wget "$baseurl/$script.sh" -O "$dest"
# make the script executable.
chmod +x "$dest"
}
# Remove backup service file if it exists and install the service file.
[ -f "$systemdir/backup.service" ] &&
systemctl stop backup.timer &&
systemctl stop backup.service &&
rm -f "$systemdir/backup.service"
wget "$baseurl/backup.service" -O "$systemdir/backup.service"
@@ -14,15 +27,10 @@ wget "$baseurl/backup.service" -O "$systemdir/backup.service"
[ ! -f "$systemdir/backup.timer" ] &&
wget "$baseurl/backup.timer" -O "$systemdir/backup.timer"
# Remove the backup script file if it exists and install the backup script.
[ -f "$bindir/docker-backup" ] && rm -f "$bindir/docker-backup"
wget "$baseurl/docker-backup.sh" -O "$bindir/docker-backup"
# Remove the restore script file if it exists and install the restore script.
[ -f "$bindir/docker-restore" ] && rm -f "$bindir/docker-restore"
wget "$baseurl/docker-restore.sh" -O "$bindir/docker-restore"
downloadScripts
# Start services
systemctl daemon-reload
systemctl start backup.timer
systemctl start backup.service
systemctl status backup.service