Compare commits
11 Commits
c59fb1df18
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
d1ecf93610
|
|||
|
6fe58e6126
|
|||
|
c6f35cb86b
|
|||
|
879de32228
|
|||
|
0924791310
|
|||
|
af5b9f90e6
|
|||
|
c8aeafe1a6
|
|||
|
c779861eed
|
|||
|
649490f7f1
|
|||
|
6af877123f
|
|||
|
36c7d24d04
|
48
README.md
48
README.md
@@ -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
|
||||
```
|
||||
|
||||
136
docker-backup.sh
136
docker-backup.sh
@@ -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 "$@"
|
||||
|
||||
@@ -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 "$@"
|
||||
22
install.sh
22
install.sh
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user