mirror of
https://github.com/edv-pi/pbs-client-docker.git
synced 2025-04-20 05:52:55 +02:00
Add cronjob functionality.
This commit is contained in:
parent
33ef7afc93
commit
cf3abb37d7
@ -12,7 +12,9 @@
|
|||||||
|
|
||||||
## Longer summary
|
## 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
|
## Table of Contents
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
# The 3 variables below are required.
|
# The 4 variables below are required.
|
||||||
PBS_ENCRYPTION_PASSWORD="123456789abcdefghijklmn"
|
PBS_ENCRYPTION_PASSWORD="123456789abcdefghijklmn"
|
||||||
PBS_ENDPOINT="pbs.mydomain.com"
|
PBS_ENDPOINT="pbs.mydomain.com"
|
||||||
PBS_DATASTORE="test-datastore"
|
PBS_DATASTORE="test-datastore"
|
||||||
|
CRON_SCHEDULE="0 */4 * * *"
|
||||||
|
|
||||||
# Use of the PBS_API_KEY_NAME and PBS_API_KEY_SECRET is recommended!
|
# Use of the PBS_API_KEY_NAME and PBS_API_KEY_SECRET is recommended!
|
||||||
# If unset, ensure PBS_USER and PBS_PASSWORD are set.
|
# If unset, ensure PBS_USER and PBS_PASSWORD are set.
|
||||||
|
@ -13,4 +13,4 @@ services:
|
|||||||
- ./pbsconfig/:/root/.config/proxmox-backup/
|
- ./pbsconfig/:/root/.config/proxmox-backup/
|
||||||
- ./backups/test1:/backups/test1:ro
|
- ./backups/test1:/backups/test1:ro
|
||||||
- ./backups/test2:/backups/test2: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"
|
LABEL maintainer="Aterfax"
|
||||||
|
|
||||||
# Get initial required packages
|
# 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
|
# 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 && \
|
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
|
COPY ./src/s6-services/backup /etc/s6-overlay/s6-rc.d/backup
|
||||||
RUN touch etc/s6-overlay/s6-rc.d/user/contents.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
|
#!/usr/bin/with-contenv bash
|
||||||
# shellcheck shell=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.
|
# Define a logging function to prefix output to the docker logs.
|
||||||
output_to_log() {
|
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
|
# Redirect all subsequent command outputs to output_to_log
|
||||||
exec > >(output_to_log)
|
exec > >(output_to_log)
|
||||||
@ -16,63 +19,4 @@ handle_error() {
|
|||||||
}
|
}
|
||||||
trap handle_error ERR
|
trap handle_error ERR
|
||||||
|
|
||||||
path_to_filename() {
|
/etc/s6-overlay/s6-rc.d/backup/run_include
|
||||||
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
|
|
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
|
#!/usr/bin/with-contenv bash
|
||||||
# shellcheck shell=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.
|
# Define a logging function to prefix output to the docker logs.
|
||||||
output_to_log() {
|
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
|
# Redirect all subsequent command outputs to output_to_log
|
||||||
exec > >(output_to_log)
|
exec > >(output_to_log)
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
#!/usr/bin/with-contenv bash
|
||||||
# shellcheck shell=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.
|
# Define a logging function to prefix output to the docker logs.
|
||||||
output_to_log() {
|
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
|
# Redirect all subsequent command outputs to output_to_log
|
||||||
exec > >(output_to_log)
|
exec > >(output_to_log)
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
#!/usr/bin/with-contenv bash
|
||||||
# shellcheck shell=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.
|
# Define a logging function to prefix output to the docker logs.
|
||||||
output_to_log() {
|
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
|
# Redirect all subsequent command outputs to output_to_log
|
||||||
exec > >(output_to_log)
|
exec > >(output_to_log)
|
||||||
|
Loading…
Reference in New Issue
Block a user