mirror of
https://github.com/edv-pi/pbs-client-docker.git
synced 2025-04-16 19:42:55 +02:00
Add cronjob functionality.
This commit is contained in:
parent
33ef7afc93
commit
cf3abb37d7
@ -12,7 +12,9 @@
|
||||
|
||||
## Longer summary
|
||||
|
||||
This container is still a work in progress and backups are not currently cron jobbed (a backup is only taken on re/start). Reading and using the ``docker-compose\docker-compose.yml`` and example ``.env.example`` file should be illustrative on how to use this container. See also: [Using-the-DockerHub-provided-image](#Using-the-DockerHub-provided-image)
|
||||
This container is still a work in progress but the main feature (cronjob'd backups) now works.
|
||||
|
||||
Reading and using the ``docker-compose\docker-compose.yml`` and example ``.env.example`` file should be illustrative on how to use this container. See also: [Using-the-DockerHub-provided-image](#Using-the-DockerHub-provided-image)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
# The 3 variables below are required.
|
||||
# The 4 variables below are required.
|
||||
PBS_ENCRYPTION_PASSWORD="123456789abcdefghijklmn"
|
||||
PBS_ENDPOINT="pbs.mydomain.com"
|
||||
PBS_DATASTORE="test-datastore"
|
||||
CRON_SCHEDULE="0 */4 * * *"
|
||||
|
||||
# Use of the PBS_API_KEY_NAME and PBS_API_KEY_SECRET is recommended!
|
||||
# If unset, ensure PBS_USER and PBS_PASSWORD are set.
|
||||
|
@ -13,4 +13,4 @@ services:
|
||||
- ./pbsconfig/:/root/.config/proxmox-backup/
|
||||
- ./backups/test1:/backups/test1:ro
|
||||
- ./backups/test2:/backups/test2:ro
|
||||
- ./backups/test3:/backups/test3:ro
|
||||
- ./backups/test3:/backups/test3:ro
|
@ -7,7 +7,7 @@ FROM ghcr.io/linuxserver/baseimage-debian:bookworm
|
||||
LABEL maintainer="Aterfax"
|
||||
|
||||
# Get initial required packages
|
||||
RUN apt-get update && apt-get install -y wget nano procps less expect
|
||||
RUN apt-get update && apt-get install -y wget cron expect
|
||||
|
||||
# Get the Proxmox signing keys and add to trust store
|
||||
RUN curl -o /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg && \
|
||||
@ -38,3 +38,6 @@ RUN touch etc/s6-overlay/s6-rc.d/user/contents.d/setup_check
|
||||
|
||||
COPY ./src/s6-services/backup /etc/s6-overlay/s6-rc.d/backup
|
||||
RUN touch etc/s6-overlay/s6-rc.d/user/contents.d/backup
|
||||
|
||||
COPY ./src/s6-services/cron-backup /etc/s6-overlay/s6-rc.d/cron-backup
|
||||
RUN touch etc/s6-overlay/s6-rc.d/user/contents.d/cron-backup
|
@ -1,9 +1,12 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# This script runs once as the container starts to get an immediate backup.
|
||||
|
||||
# Define a logging function to prefix output to the docker logs.
|
||||
output_to_log() {
|
||||
sed 's/^/[backup] /'
|
||||
while IFS= read -r line; do
|
||||
echo "[backup] $(date +"%Y-%m-%d %H:%M:%S") $line"
|
||||
done
|
||||
}
|
||||
# Redirect all subsequent command outputs to output_to_log
|
||||
exec > >(output_to_log)
|
||||
@ -16,63 +19,4 @@ handle_error() {
|
||||
}
|
||||
trap handle_error ERR
|
||||
|
||||
path_to_filename() {
|
||||
local path="$1"
|
||||
local path_no_trailing_slash="${path%/}" # Remove the trailing slash, if any
|
||||
local path_no_first_slash="${path_no_trailing_slash#\/}" # Remove the first slash
|
||||
local filename="${path_no_first_slash//\//-}" # Replace slashes with dashes
|
||||
echo "${filename}"
|
||||
}
|
||||
|
||||
BACKUP_DIRECTORIES=()
|
||||
# Iterate over each subdirectory under /backup and add its full path to the array
|
||||
for dir in /backups/*; do
|
||||
if [[ -d "$dir" ]]; then
|
||||
BACKUP_DIRECTORIES+=("$dir/")
|
||||
fi
|
||||
done
|
||||
|
||||
# Print the contents of the array
|
||||
echo "## Detected backup directories:"
|
||||
echo -e "#"
|
||||
if [ ${#BACKUP_DIRECTORIES[@]} -eq 0 ]; then
|
||||
echo "# Nothing to backup."
|
||||
else
|
||||
for path in "${BACKUP_DIRECTORIES[@]}"; do
|
||||
echo -e "# $path"
|
||||
done
|
||||
echo -e "#\n"
|
||||
fi
|
||||
|
||||
# Construct the directory target list with the proxmox-backup-client syntax.
|
||||
# This makes 1 .pxar file per path.
|
||||
TARGETS=""
|
||||
for dir in "${BACKUP_DIRECTORIES[@]}"; do
|
||||
TARGET=$(path_to_filename "$dir").pxar:$dir
|
||||
TARGETS="${TARGETS} ${TARGET}"
|
||||
done
|
||||
|
||||
# Build the backup command we want to execute.
|
||||
BACKUPCMD="proxmox-backup-client backup ${TARGETS}"
|
||||
|
||||
if [ -n "$PBS_DATASTORE_NS" ]; then
|
||||
BACKUPCMD+=" --ns ${PBS_DATASTORE_NS}"
|
||||
fi
|
||||
|
||||
|
||||
# Source the variables from the setup_check scripting include file.
|
||||
source /etc/s6-overlay/s6-rc.d/setup_check/run_include
|
||||
|
||||
echo -e "## Backing up to repository: \n# ${PBS_REPOSITORY}\n"
|
||||
echo -e "## Executing backup command: \n# ${BACKUPCMD}\n"
|
||||
|
||||
if [ -n "$HEALTHCHECKSURL" ]; then
|
||||
curl -fsS -m 10 --retry 5 $HEALTHCHECKSURL/start
|
||||
fi
|
||||
|
||||
${BACKUPCMD} 2>&1
|
||||
BACKUP_EXIT_CODE=$?
|
||||
|
||||
if [ -n "$HEALTHCHECKSURL" ]; then
|
||||
curl -fsS -m 10 --retry 5 ${HEALTHCHECKSURL}/${BACKUP_EXIT_CODE}
|
||||
fi
|
||||
/etc/s6-overlay/s6-rc.d/backup/run_include
|
62
docker/src/s6-services/backup/run_include
Normal file
62
docker/src/s6-services/backup/run_include
Normal file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
path_to_filename() {
|
||||
local path="$1"
|
||||
local path_no_trailing_slash="${path%/}" # Remove the trailing slash, if any
|
||||
local path_no_first_slash="${path_no_trailing_slash#\/}" # Remove the first slash
|
||||
local filename="${path_no_first_slash//\//-}" # Replace slashes with dashes
|
||||
echo "${filename}"
|
||||
}
|
||||
|
||||
BACKUP_DIRECTORIES=()
|
||||
# Iterate over each subdirectory under /backup and add its full path to the array
|
||||
for dir in /backups/*; do
|
||||
if [[ -d "$dir" ]]; then
|
||||
BACKUP_DIRECTORIES+=("$dir/")
|
||||
fi
|
||||
done
|
||||
|
||||
# Print the contents of the array
|
||||
echo "## Detected backup directories:"
|
||||
echo -e "#"
|
||||
if [ ${#BACKUP_DIRECTORIES[@]} -eq 0 ]; then
|
||||
echo "# Nothing to backup."
|
||||
else
|
||||
for path in "${BACKUP_DIRECTORIES[@]}"; do
|
||||
echo -e "# $path"
|
||||
done
|
||||
echo -e "#\n"
|
||||
fi
|
||||
|
||||
# Construct the directory target list with the proxmox-backup-client syntax.
|
||||
# This makes 1 .pxar file per path.
|
||||
TARGETS=""
|
||||
for dir in "${BACKUP_DIRECTORIES[@]}"; do
|
||||
TARGET=$(path_to_filename "$dir").pxar:$dir
|
||||
TARGETS="${TARGETS} ${TARGET}"
|
||||
done
|
||||
|
||||
# Build the backup command we want to execute.
|
||||
BACKUPCMD="proxmox-backup-client backup ${TARGETS}"
|
||||
|
||||
if [ -n "$PBS_DATASTORE_NS" ]; then
|
||||
BACKUPCMD+=" --ns ${PBS_DATASTORE_NS}"
|
||||
fi
|
||||
|
||||
|
||||
# Source the variables from the setup_check scripting include file.
|
||||
source /etc/s6-overlay/s6-rc.d/setup_check/run_include
|
||||
|
||||
echo -e "## Backing up to repository: \n# ${PBS_REPOSITORY}\n"
|
||||
echo -e "## Executing backup command: \n# ${BACKUPCMD}\n"
|
||||
|
||||
if [ -n "$HEALTHCHECKSURL" ]; then
|
||||
curl -fsS -m 10 --retry 5 $HEALTHCHECKSURL/start
|
||||
fi
|
||||
|
||||
${BACKUPCMD} 2>&1
|
||||
BACKUP_EXIT_CODE=$?
|
||||
|
||||
if [ -n "$HEALTHCHECKSURL" ]; then
|
||||
curl -fsS -m 10 --retry 5 ${HEALTHCHECKSURL}/${BACKUP_EXIT_CODE}
|
||||
fi
|
64
docker/src/s6-services/cron-backup/run
Normal file
64
docker/src/s6-services/cron-backup/run
Normal file
@ -0,0 +1,64 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# This script instates the cron job to take regular backups.
|
||||
|
||||
|
||||
# Define a logging function to prefix output to the docker logs.
|
||||
output_to_log() {
|
||||
while IFS= read -r line; do
|
||||
echo "[cron-backup] $(date +"%Y-%m-%d %H:%M:%S") $line"
|
||||
done
|
||||
}
|
||||
# Redirect all subsequent command outputs to output_to_log
|
||||
exec > >(output_to_log)
|
||||
|
||||
# Set up error handling
|
||||
handle_error() {
|
||||
local exit_code="$?"
|
||||
echo -e "Error occurred (Exit code: $exit_code)"
|
||||
exit "$exit_code"
|
||||
}
|
||||
trap handle_error ERR
|
||||
|
||||
validate_cron_expression() {
|
||||
local cron_expression="$1"
|
||||
# https://stackoverflow.com/a/57639657
|
||||
local regex='(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)*\d+|(\d+(/|-)\d+)|\d+|\*) ?){5,7})'
|
||||
|
||||
if echo "$cron_expression" | grep -Pq "$regex"; then
|
||||
return 0 # Valid cron expression
|
||||
else
|
||||
return 1 # Invalid cron expression
|
||||
fi
|
||||
}
|
||||
|
||||
if ! validate_cron_expression "$CRON_SCHEDULE"; then
|
||||
echo -e "Invalid cron expression: $CRON_SCHEDULE \n"
|
||||
echo "Please define a valid cron time expression for CRON_SCHEDULE, e.g. \"*/5 * * * *\" "
|
||||
sleep 60
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CRONLOG_FILE="/root/.config/proxmox-backup/cron.log"
|
||||
CRON_FILE="/etc/cron.d/cron-backup"
|
||||
CRON_LINE="${CRON_SCHEDULE} root bash -c '/etc/s6-overlay/s6-rc.d/backup/run_include' >> $CRONLOG_FILE 2>&1 "
|
||||
TIMEOUT=60
|
||||
|
||||
touch "${CRONLOG_FILE}"
|
||||
echo "${CRON_LINE}" > "${CRON_FILE}"
|
||||
chmod +x "${CRON_FILE}"
|
||||
|
||||
service cron start
|
||||
echo "Cron service is now running with: \"${CRON_LINE}\" "
|
||||
|
||||
# We only want new lines added, not existing log content on startup.
|
||||
tail -n 0 -f "${CRONLOG_FILE}" &
|
||||
|
||||
# Check if cron service is running
|
||||
while :; do
|
||||
if ! service cron status > /dev/null; then
|
||||
echo "Error: Cron service is not running. Restarting cron."
|
||||
exit 1
|
||||
fi
|
||||
sleep ${TIMEOUT}
|
||||
done
|
1
docker/src/s6-services/cron-backup/type
Normal file
1
docker/src/s6-services/cron-backup/type
Normal file
@ -0,0 +1 @@
|
||||
longrun
|
1
docker/src/s6-services/cron-backup/up
Normal file
1
docker/src/s6-services/cron-backup/up
Normal file
@ -0,0 +1 @@
|
||||
/etc/s6-overlay/s6-rc.d/cron-backup/run
|
@ -1,9 +1,12 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# This script runs once as the container starts to get a snapshot of the environment variables.
|
||||
|
||||
# Define a logging function to prefix output to the docker logs.
|
||||
output_to_log() {
|
||||
sed 's/^/[env-test] /'
|
||||
while IFS= read -r line; do
|
||||
echo "[env-test] $(date +"%Y-%m-%d %H:%M:%S") $line"
|
||||
done
|
||||
}
|
||||
# Redirect all subsequent command outputs to output_to_log
|
||||
exec > >(output_to_log)
|
||||
|
@ -1,9 +1,13 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# This script runs once as the container starts to ensure key setup is functional
|
||||
# for backups. (Either checking keys or generating new ones).
|
||||
|
||||
# Define a logging function to prefix output to the docker logs.
|
||||
output_to_log() {
|
||||
sed 's/^/[key_setup] /'
|
||||
while IFS= read -r line; do
|
||||
echo "[key_setup] $(date +"%Y-%m-%d %H:%M:%S") $line"
|
||||
done
|
||||
}
|
||||
# Redirect all subsequent command outputs to output_to_log
|
||||
exec > >(output_to_log)
|
||||
|
@ -1,9 +1,13 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
# This script runs once as the container starts to ensure variables are set
|
||||
# correctly and any dependent variables also get set.
|
||||
|
||||
# Define a logging function to prefix output to the docker logs.
|
||||
output_to_log() {
|
||||
sed 's/^/[setup_check] /'
|
||||
while IFS= read -r line; do
|
||||
echo "[setup_check] $(date +"%Y-%m-%d %H:%M:%S") $line"
|
||||
done
|
||||
}
|
||||
# Redirect all subsequent command outputs to output_to_log
|
||||
exec > >(output_to_log)
|
||||
|
Loading…
Reference in New Issue
Block a user