Compare commits

...

10 Commits

Author SHA1 Message Date
Clemens Schwaighofer ab21c2ca79 Merge branch 'development' into refactor/TTD-3115/shellcheck-cleanup 2026-04-28 11:51:57 +09:00
Clemens Schwaighofer 92225a588b v4.9.0: forgejo backup v1.0.0
Add backup to forgejo like for gitea
2026-04-28 11:44:36 +09:00
Clemens Schwaighofer 03925562ff Merge branch 'development' into refactor/TTD-3115/shellcheck-cleanup 2025-12-04 11:46:31 +09:00
Clemens Schwaighofer 924014688e Update gitignore file with backup lock files 2025-12-04 09:57:54 +09:00
Clemens Schwaighofer 783bf2adb9 Merge branch 'development' into shellcheck-cleanup 2025-12-02 10:02:17 +09:00
Clemens Schwaighofer dd2a85f5d6 Merge branch 'development' into shellcheck-cleanup 2025-12-01 18:16:01 +09:00
Clemens Schwaighofer 2e5f0648f1 Merge branch 'development' into shellcheck-cleanup 2025-08-21 10:42:20 +09:00
Clemens Schwaighofer acd5d369eb Merge branch 'development' into shellcheck-cleanup 2025-08-20 22:41:54 +09:00
Clemens Schwaighofer de9d5d3588 Zabbix backup set port to 5432 default to override internal set ports 2025-08-20 22:11:38 +09:00
Clemens Schwaighofer 8407defe4f Starting shellcheck cleanup 2024-09-04 10:58:48 +09:00
11 changed files with 177 additions and 19 deletions
+2
View File
@@ -1,5 +1,6 @@
.cache/ .cache/
.config/ .config/
# various borg files that need to be ignored
borg.backup.settings borg.backup.settings
borg.backup.*.settings borg.backup.*.settings
borg.backup.*.include borg.backup.*.include
@@ -7,3 +8,4 @@ borg.backup.*.exclude
borg.backup.*.schema-only borg.backup.*.schema-only
borg.backup.*.init borg.backup.*.init
borg.backup.*.compact borg.backup.*.compact
borg.backup.*.lock
+22 -3
View File
@@ -254,23 +254,42 @@ backup.borg.mysql.schema-only
## gitea backup settings ## gitea backup settings
Note that the backup needs the GIT_USER set that runs gitea. Note that the backup needs the GITEA_GIT_USER set that runs gitea.
This user is neede to create the temporary dump folder and access for the git files and database. This user is neede to create the temporary dump folder and access for the git files and database.
### gitea Config Variables ### gitea Config Variables
| Variable | Default | Description | | Variable | Default | Description |
| - | - | - | | - | - | - |
| GIT_USER | git | The user that runs gitea | | GITEA_GIT_USER | git | The user that runs gitea |
| GITEA_WORKING_DIR | /var/tmp/gitea/ | Where the temporary dump files from the backup are stored, as user git | | GITEA_WORKING_DIR | /var/tmp/gitea/ | Where the temporary dump files from the backup are stored, as user git |
| GITEA_TEMP_DIR | /var/tmp/ | General temporary folder | | GITEA_TEMP_DIR | /var/tmp/ | General temporary folder |
| GITEA_BIN | /usr/local/bin/gitea | Where the gitea binary is located | | GITEA_BIN | /usr/local/bin/gitea | Where the gitea binary is located |
| GITEA_CONFIG | /etc/gitea/app.ini | The configuration file for gitea | | GITEA_CONFIG | /etc/gitea/app.ini or /var/lib/gitea/custom/conf/app.ini | The configuration file for gitea |
### gitea Control files ### gitea Control files
There are no control files for gitea backup There are no control files for gitea backup
## forgejo backup settings
Note that the backup needs the FORGEJO_GIT_USER set that runs forgejo.
This user is neede to create the temporary dump folder and access for the git files and database.
### forgejo Config Variables
| Variable | Default | Description |
| - | - | - |
| FORGEJO_GIT_USER | git | The user that runs forgejo |
| FORGEJO_WORKING_DIR | /var/tmp/forgejo/ | Where the temporary dump files from the backup are stored, as user git |
| FORGEJO_TEMP_DIR | /var/tmp/ | General temporary folder |
| FORGEJO_BIN | /usr/local/bin/forgejo | Where the forgejo binary is located |
| FORGEJO_CONFIG | /etc/forgejo/app.ini or /var/lib/forgejo/custom/conf/app.ini | The configuration file for forgejo |
### forgejo Control files
There are no control files for forgejo backup
## zabbix config backup settings ## zabbix config backup settings
The `zabbix-dump` dump script must be installed from: <https://github.com/gullevek/zabbix-backup> The `zabbix-dump` dump script must be installed from: <https://github.com/gullevek/zabbix-backup>
+5 -4
View File
@@ -31,16 +31,16 @@ MODULE_LIST="file gitea mysql pgsql zabbix"
# -n for dry run test # -n for dry run test
while getopts ":c:snd" opt; do while getopts ":c:snd" opt; do
case "${opt}" in case "${opt}" in
c|config) c) # config
BASE_FOLDER=${OPTARG}; BASE_FOLDER=${OPTARG};
;; ;;
s|nosudo) s) # nosudo
PGSQL_SUDO=0; PGSQL_SUDO=0;
;; ;;
d|debug) d) # debug
DEBUG=1; DEBUG=1;
;; ;;
n|dryrun) n) # dryrun
DRYRUN=1; DRYRUN=1;
;; ;;
:) :)
@@ -64,6 +64,7 @@ if [ ! -f "${BASE_FOLDER}${SETTINGS_FILE}" ]; then
echo "Could not find: ${BASE_FOLDER}${SETTINGS_FILE}"; echo "Could not find: ${BASE_FOLDER}${SETTINGS_FILE}";
exit; exit;
fi; fi;
# shellcheck source="borg.backup.settings"
. "${BASE_FOLDER}${SETTINGS_FILE}"; . "${BASE_FOLDER}${SETTINGS_FILE}";
if [ -n "${TARGET_BORG_PATH}" ]; then if [ -n "${TARGET_BORG_PATH}" ]; then
+9
View File
@@ -0,0 +1,9 @@
# Borg backup wrapper scripts settings: forgejo
# rename to borg.backup.forgejo.settings to use
FORGEJO_GIT_USER="";
FORGEJO_WORKING_DIR="";
FORGEJO_TEMP_DIR="";
FORGEJO_BIN="";
FORGEJO_CONFIG="";
+115
View File
@@ -0,0 +1,115 @@
#!/usr/bin/env bash
# allow variables in printf format string
# shellcheck disable=SC2059
# Backup forgejo database, all git folders and forgejo settings
MODULE="forgejo"
MODULE_VERSION="1.0.0";
DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
# init system
. "${DIR}/borg.backup.functions.init.sh";
# init verify, compact and check file
BACKUP_INIT_FILE="borg.backup.${MODULE}.init";
BACKUP_COMPACT_FILE="borg.backup.${MODULE}.compact";
BACKUP_CHECK_FILE="borg.backup.${MODULE}.check";
# lock file
BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
# verify valid data
. "${DIR}/borg.backup.functions.verify.sh";
# if info print info and then abort run
. "${DIR}/borg.backup.functions.info.sh";
# NOTE: because a tmp directory is needed it is more recommended
# to run this as root and have only the dump command itself run as FORGEJO_GIT_USER
# set git user
if [ -z "${FORGEJO_GIT_USER}" ]; then
FORGEJO_GIT_USER="git";
fi;
# set FORGEJO_* if not set
if [ -z "${FORGEJO_WORKING_DIR}" ]; then
# run forgejo backup (user mktemp?)
FORGEJO_WORKING_DIR="/var/tmp/forgejo/";
fi;
# general temp folder for temporary data storage, this is not working output folder
if [ -z "${FORGEJO_TEMP_DIR}" ]; then
FORGEJO_TEMP_DIR="/var/tmp";
fi;
if [ -z "${FORGEJO_BIN}" ]; then
FORGEJO_BIN="/usr/local/bin/forgejo";
fi;
if [ -z "${FORGEJO_CONFIG}" ]; then
FORGEJO_CONFIG="/etc/forgejo/app.ini"
fi;
# This one is not advertised in the config file as it is not recommended to change
if [ -z "${FORGEJO_EXPORT_TYPE}" ]; then
FORGEJO_EXPORT_TYPE="zip";
fi;
if [ ! -f "${FORGEJO_BIN}" ]; then
echo "[! $(date +'%F %T')] Cannot find forgejo binary";
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
fi;
if [ ! -f "${FORGEJO_CONFIG}" ]; then
echo "[! $(date +'%F %T')] Cannot find forgejo config";
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
fi;
# some basic checks with abort
if [ ! -d "${FORGEJO_TEMP_DIR}" ]; then
echo "Temp directory does not exist: ${FORGEJO_TEMP_DIR}";
exit;
fi;
# we should check FORGEJO_EXPORT_TYPE too at some point for an allow list
# At the moment warn if not zip
if [ "${FORGEJO_EXPORT_TYPE}" != "zip" ]; then
echo "[!!!!] The forgejo export type has been changed from 'zip' to '${FORGEJO_EXPORT_TYPE}'. This can either break or make exports take very ling";
fi;
# Filename
FILENAME="forgejo.backup.zip";
# backup set and prefix
BACKUP_SET_PREFIX="${MODULE},";
BACKUP_SET_NAME="${ONE_TIME_TAG}${BACKUP_SET_PREFIX}${BACKUP_SET}";
# borg call
BORG_CALL=$(echo "${_BORG_CALL}" | sed -e "s/##FILENAME##/${FILENAME}/" | sed -e "s/##BACKUP_SET##/${BACKUP_SET_NAME}/");
BORG_PRUNE=$(echo "${_BORG_PRUNE}" | sed -e "s/##BACKUP_SET_PREFIX##/${BACKUP_SET_PREFIX}/");
printf "${PRINTF_SUB_BLOCK}" "BACKUP: git data and database" "$(date +'%F %T')" "${MODULE}";
if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then
echo "sudo -u ${FORGEJO_GIT_USER} ${FORGEJO_BIN} dump -c ${FORGEJO_CONFIG} -w ${FORGEJO_WORKING_DIR} -t ${FORGEJO_TEMP_DIR} --type ${FORGEJO_EXPORT_TYPE} -L -f - | ${BORG_CALL}";
if [ -z "${ONE_TIME_TAG}" ]; then
echo "${BORG_PRUNE}";
fi;
fi;
if [ ${DRYRUN} -eq 0 ]; then
(
# below was an old workaround
#export USER="${LOGNAME}" # workaround for broken forgejo EUID check
# make sure temp folder is there and is set as git. user
if [ ! -d "${FORGEJO_WORKING_DIR}" ]; then
mkdir -p "${FORGEJO_WORKING_DIR}";
fi;
chown -R ${FORGEJO_GIT_USER}: "${FORGEJO_WORKING_DIR}";
# this needs to be run in a folder that can be stat by git user
cd "${FORGEJO_WORKING_DIR}" || exit 1;
sudo -u ${FORGEJO_GIT_USER} ${FORGEJO_BIN} dump -c ${FORGEJO_CONFIG} -w ${FORGEJO_WORKING_DIR} -t ${FORGEJO_TEMP_DIR} --type ${FORGEJO_EXPORT_TYPE} -L -f - | ${BORG_CALL};
) 2>&1 | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g' # remove all ESC strings
fi;
if [ -z "${ONE_TIME_TAG}" ]; then
printf "${PRINTF_SUB_BLOCK}" "PRUNE" "$(date +'%F %T')" "${MODULE}";
echo "Prune repository with keep${KEEP_INFO:1}";
${BORG_PRUNE};
# if this is borg version >1.2 we need to run compact after prune
. "${DIR}/borg.backup.functions.compact.sh" "auto";
# check in auto mode
. "${DIR}/borg.backup.functions.check.sh" "auto";
fi;
. "${DIR}/borg.backup.functions.close.sh";
# __END__
+5
View File
@@ -10,6 +10,7 @@ fi;
# compact (only if BORG COMPACT is set) # compact (only if BORG COMPACT is set)
# only for borg 1.2 # only for borg 1.2
if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
RUN_COMPACT=0; RUN_COMPACT=0;
if [ $# -ge 1 ] && [ "$1" = "auto" ]; then if [ $# -ge 1 ] && [ "$1" = "auto" ]; then
@@ -21,10 +22,13 @@ if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
fi; fi;
# get current date timestmap # get current date timestmap
CURRENT_DATE=$(date +%s); CURRENT_DATE=$(date +%s);
if [ "${COMPACT_INTERVAL}" -eq 1 ]; then
if [ "${COMPACT_INTERVAL}" -eq 1 ]; then if [ "${COMPACT_INTERVAL}" -eq 1 ]; then
RUN_COMPACT=1; RUN_COMPACT=1;
# set new compact time here # set new compact time here
echo "${CURRENT_DATE}" > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}"; echo "${CURRENT_DATE}" > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}";
elif [ "${COMPACT_INTERVAL}" -gt 1 ]; then
echo "${CURRENT_DATE}" > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}";
elif [ "${COMPACT_INTERVAL}" -gt 1 ]; then elif [ "${COMPACT_INTERVAL}" -gt 1 ]; then
# else load last timestamp and check if today - last time stamp > days # else load last timestamp and check if today - last time stamp > days
if [ -z "${LAST_COMPACT_DATE}" ]; then if [ -z "${LAST_COMPACT_DATE}" ]; then
@@ -48,6 +52,7 @@ if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
if [ "${RUN_COMPACT}" -eq 1 ]; then if [ "${RUN_COMPACT}" -eq 1 ]; then
# reset to normal IFS, so command works here # reset to normal IFS, so command works here
IFS=${_IFS}; IFS=${_IFS};
# shellcheck disable=SC2059
printf "${PRINTF_SUB_BLOCK}" "COMPACT" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "COMPACT" "$(date +'%F %T')" "${MODULE}";
BORG_COMPACT="${BORG_COMMAND} compact ${OPT_REMOTE} -v ${OPT_PROGRESS} ${REPOSITORY}"; BORG_COMPACT="${BORG_COMMAND} compact ${OPT_REMOTE} -v ${OPT_PROGRESS} ${REPOSITORY}";
if [ "${DEBUG}" -eq 1 ]; then if [ "${DEBUG}" -eq 1 ]; then
+9 -2
View File
@@ -32,7 +32,7 @@ function version {
} }
# version for all general files # version for all general files
VERSION="4.8.0"; VERSION="4.9.0";
# borg version and borg comamnd # borg version and borg comamnd
BORG_VERSION=""; BORG_VERSION="";
@@ -166,12 +166,19 @@ DATABASE_HOST="";
MYSQL_DB_CONFIG=""; MYSQL_DB_CONFIG="";
MYSQL_DB_CONFIG_PARAM=""; MYSQL_DB_CONFIG_PARAM="";
# gitea module # gitea module
GIT_USER=""; GITEA_GIT_USER="";
GITEA_WORKING_DIR=""; GITEA_WORKING_DIR="";
GITEA_TEMP_DIR=""; GITEA_TEMP_DIR="";
GITEA_BIN=""; GITEA_BIN="";
GITEA_CONFIG=""; GITEA_CONFIG="";
GITEA_EXPORT_TYPE=""; GITEA_EXPORT_TYPE="";
# forgejo module
FORGEJO_GIT_USER="";
FORGEJO_WORKING_DIR="";
FORGEJO_TEMP_DIR="";
FORGEJO_BIN="";
FORGEJO_CONFIG="";
FORGEJO_EXPORT_TYPE="";
# zabbix module # zabbix module
ZABBIX_DUMP_BIN=""; ZABBIX_DUMP_BIN="";
ZABBIX_CONFIG=""; ZABBIX_CONFIG="";
+1 -1
View File
@@ -2,7 +2,7 @@
# rename to borg.backup.gitea.settings to use # rename to borg.backup.gitea.settings to use
GIT_USER=""; GITEA_GIT_USER="";
GITEA_WORKING_DIR=""; GITEA_WORKING_DIR="";
GITEA_TEMP_DIR=""; GITEA_TEMP_DIR="";
GITEA_BIN=""; GITEA_BIN="";
+6 -6
View File
@@ -26,10 +26,10 @@ BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
. "${DIR}/borg.backup.functions.info.sh"; . "${DIR}/borg.backup.functions.info.sh";
# NOTE: because a tmp directory is needed it is more recommended # NOTE: because a tmp directory is needed it is more recommended
# to run this as root and have only the dump command itself run as GIT_USER # to run this as root and have only the dump command itself run as GITEA_GIT_USER
# set git user # set git user
if [ -z "${GIT_USER}" ]; then if [ -z "${GITEA_GIT_USER}" ]; then
GIT_USER="git"; GITEA_GIT_USER="git";
fi; fi;
# set GITEA_* if not set # set GITEA_* if not set
if [ -z "${GITEA_WORKING_DIR}" ]; then if [ -z "${GITEA_WORKING_DIR}" ]; then
@@ -81,7 +81,7 @@ BORG_CALL=$(echo "${_BORG_CALL}" | sed -e "s/##FILENAME##/${FILENAME}/" | sed -e
BORG_PRUNE=$(echo "${_BORG_PRUNE}" | sed -e "s/##BACKUP_SET_PREFIX##/${BACKUP_SET_PREFIX}/"); BORG_PRUNE=$(echo "${_BORG_PRUNE}" | sed -e "s/##BACKUP_SET_PREFIX##/${BACKUP_SET_PREFIX}/");
printf "${PRINTF_SUB_BLOCK}" "BACKUP: git data and database" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "BACKUP: git data and database" "$(date +'%F %T')" "${MODULE}";
if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then
echo "sudo -u ${GIT_USER} ${GITEA_BIN} dump -c ${GITEA_CONFIG} -w ${GITEA_WORKING_DIR} -t ${GITEA_TEMP_DIR} --type ${GITEA_EXPORT_TYPE} -L -f - | ${BORG_CALL}"; echo "sudo -u ${GITEA_GIT_USER} ${GITEA_BIN} dump -c ${GITEA_CONFIG} -w ${GITEA_WORKING_DIR} -t ${GITEA_TEMP_DIR} --type ${GITEA_EXPORT_TYPE} -L -f - | ${BORG_CALL}";
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
echo "${BORG_PRUNE}"; echo "${BORG_PRUNE}";
fi; fi;
@@ -94,10 +94,10 @@ if [ ${DRYRUN} -eq 0 ]; then
if [ ! -d "${GITEA_WORKING_DIR}" ]; then if [ ! -d "${GITEA_WORKING_DIR}" ]; then
mkdir -p "${GITEA_WORKING_DIR}"; mkdir -p "${GITEA_WORKING_DIR}";
fi; fi;
chown -R ${GIT_USER}: "${GITEA_WORKING_DIR}"; chown -R ${GITEA_GIT_USER}: "${GITEA_WORKING_DIR}";
# this needs to be run in a folder that can be stat by git user # this needs to be run in a folder that can be stat by git user
cd "${GITEA_WORKING_DIR}" || exit 1; cd "${GITEA_WORKING_DIR}" || exit 1;
sudo -u ${GIT_USER} ${GITEA_BIN} dump -c ${GITEA_CONFIG} -w ${GITEA_WORKING_DIR} -t ${GITEA_TEMP_DIR} --type ${GITEA_EXPORT_TYPE} -L -f - | ${BORG_CALL}; sudo -u ${GITEA_GIT_USER} ${GITEA_BIN} dump -c ${GITEA_CONFIG} -w ${GITEA_WORKING_DIR} -t ${GITEA_TEMP_DIR} --type ${GITEA_EXPORT_TYPE} -L -f - | ${BORG_CALL};
) 2>&1 | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g' # remove all ESC strings ) 2>&1 | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g' # remove all ESC strings
fi; fi;
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
+1 -1
View File
@@ -55,7 +55,7 @@ if [ ! -f "${ZABBIX_DUMP_BIN}" ]; then
exit 1; exit 1;
fi; fi;
# -i (ignore)/ -f (backup) # -i (ignore)/ -f (backup)
if [ ! -z "${ZABBIX_UNKNOWN_TABLES}" ]; then if [ -n "${ZABBIX_UNKNOWN_TABLES}" ]; then
OPT_ZABBIX_UNKNOWN_TABLES="-f"; OPT_ZABBIX_UNKNOWN_TABLES="-f";
else else
OPT_ZABBIX_UNKNOWN_TABLES="-i"; OPT_ZABBIX_UNKNOWN_TABLES="-i";
+2 -2
View File
@@ -80,7 +80,7 @@ if [ ${UMOUNT} -eq 0 ]; then
. ${BASE_FOLDER}${SETTINGS_FILE} . ${BASE_FOLDER}${SETTINGS_FILE}
# set the borg backup file base on the settings data # set the borg backup file base on the settings data
# if we have user/host then we build the ssh command # if we have user/host then we build the ssh command
if [ ! -z "${TARGET_USER}" ] && [ ! -z "${TARGET_HOST}" ]; then if [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER=${TARGET_USER}"@"${TARGET_HOST}":"; TARGET_SERVER=${TARGET_USER}"@"${TARGET_HOST}":";
fi; fi;
REPOSITORY=${TARGET_SERVER}${TARGET_FOLDER}${BACKUP_FILE}; REPOSITORY=${TARGET_SERVER}${TARGET_FOLDER}${BACKUP_FILE};
@@ -90,7 +90,7 @@ if [ ${UMOUNT} -eq 0 ]; then
# check that the repostiory exists # check that the repostiory exists
REPOSITORY_OK=0; REPOSITORY_OK=0;
if [ ! -z "${TARGET_SERVER}" ]; then if [ -n "${TARGET_SERVER}" ]; then
# remove trailing : for this # remove trailing : for this
TARGET_SERVER=${TARGET_SERVER/:}; TARGET_SERVER=${TARGET_SERVER/:};
# use ssh command to check remote existense # use ssh command to check remote existense