self-hosting/roles/forgejo/templates/forgejo-backup.sh.j2

147 lines
4.3 KiB
Django/Jinja

#!/bin/bash
# Use forgejo dump to make a backup of Forgejo
# Also restore from a previously made backup
# https://docs.gitea.io/en-us/backup-and-restore/
set -eu
set -o pipefail
IFS="$(printf '\n\t')"
PROGRAM="${0##*/}"
INSTALL_DIR=/usr/local/bin
TMP_DIR={{ forgejo_run_dir }}/tmp
WORK_DIR={{ forgejo_run_dir }}
DATA_DIR={{ forgejo_data_dir }}
LOG_DIR={{ forgejo_log_dir }}
REPO_DIR={{ forgejo_run_dir }}/forgejo-repositories/
CONFIG_FILE={{ forgejo_conf_dir }}/app.ini
DUMP_DIR={{ forgejo_run_dir }}/forgejo-dumps
MYSQL_USER={{ forgejo_db_user }}
MYSQL_DB={{ forgejo_db_name }}
MYSQL_PW={{ forgejo_db_pass }}
{% raw %}
if [ "$USER" != git ]; then
echo "You must run this as user 'git'" && exit 1
fi
print_help() {
cat <<-_EOF
$PROGRAM
Usage:
$PROGRAM {backup|restore <forgejo_dump_file>|prune <int>}
Commands:
backup Create a backup. Will save to $DUMP_DIR.
restore Restore a previously created backup, given on the command line:
<forgejo_dump_file>, absolute path or relative to $PWD.
prune Remove previously dumped backups and keep <int> backups.
Options:
-h Print this help message and quit.
_EOF
}
do_backup() {
echo "Backing up Forgejo..."
mkdir -p "$DUMP_DIR"
mkdir -p "$TMP_DIR"
stop_service
output_dump_file="$DUMP_DIR/forgejo-dump-$(date +'%Y%m%d').tar"
mysql_dump_file="$DUMP_DIR/forgejo-db.sql"
cd "$INSTALL_DIR" || exit 1
./forgejo dump -V -f "$output_dump_file" -c "$CONFIG_FILE" -t "$TMP_DIR" --skip-lfs-data -w "$WORK_DIR" --type tar
mysqldump -u"$MYSQL_USER" -p"$MYSQL_PW" "$MYSQL_DB" > "$mysql_dump_file"
cd "$DUMP_DIR" || exit 1
tar --delete -f "$output_dump_file" forgejo-db.sql
tar --append -f "$output_dump_file" "$(basename $mysql_dump_file)"
rm "$mysql_dump_file"
chmod 640 "$output_dump_file" # Make the file readable by group for scp to different host by different user
gzip "$output_dump_file"
restart_service
echo "Done."
}
do_restore() {
echo "Restoring Forgejo backup..."
start_dir="$PWD"
tar_file="$1"
tar_dir="${tar_file%.tar.gz}" # Remove file extension
chmod 600 "$tar_file" # Backup has changed permissions, restore them here
echo "Extracting $tar_file..." && mkdir "$tar_dir" && tar xvzf "$tar_file" -C "$tar_dir" && echo " OK."
cd "$tar_dir" || exit 1
rm app.ini
echo -n "Restoring $DATA_DIR..." && rsync -avz --delete data/ "$DATA_DIR" && rm -rf data && echo " OK."
echo -n "Restoring $LOG_DIR..." && rsync -avz log/ "$LOG_DIR" && rm -rf log && echo " OK."
echo -n "Restoring $REPO_DIR..." && mkdir -p "$REPO_DIR" && rsync -avz --delete repos/ "$REPO_DIR" && rm -rf repos && echo " OK."
echo -n "Changing ownership..." && chown -R git:git "$CONFIG_FILE" "$WORK_DIR" && echo " OK."
echo -n "Restoring MySQL database..." && mysql --default-character-set=utf8mb4 -u"$MYSQL_USER" -p"$MYSQL_PW" "$MYSQL_DB" < forgejo-db.sql && rm forgejo-db.sql && echo " OK."
cd "$start_dir" || exit 1
rmdir "$tar_dir"
restart_service
regenerate_hooks
echo "Done."
}
do_prune() {
echo "Pruning Forgejo backups and keeping $1 of them..."
dumps=("$DUMP_DIR"/forgejo-dump-*.tar.gz)
nb_of_dumps="${#dumps[@]}"
nb_to_keep="$1"
nb_to_prune=$((nb_of_dumps - nb_to_keep))
if [ "$nb_to_prune" -gt "$nb_of_dumps" ]; then
echo "There are only $nb_of_dumps backups, quitting." && exit 1
fi
if [ "$nb_to_prune" -le 0 ]; then
echo "Nothing to do" && exit 1
else
for ((i=0; i < nb_to_prune; i++)); do
echo -n "Removing ${dumps[$i]}..." && rm "${dumps[$i]}" && echo " OK."
done
fi
}
regenerate_hooks() {
echo "Regenerating hooks..."
cd "$INSTALL_DIR" || exit 1
./forgejo admin regenerate hooks --config "$CONFIG_FILE" && echo "Done."
}
stop_service() {
echo -n "Stopping service..." && sudo systemctl stop forgejo.service && echo " OK."
}
restart_service() {
echo -n "Restarting service..." && sudo systemctl restart forgejo.service && echo " OK."
}
[ "$#" = 0 ] || [ "$1" = '-h' ] && print_help && exit 1
if [ "$#" = 2 ]; then
if [ "$1" = restore ]; then
echo "STARTING restore"
do_restore "$2"
echo "DONE restore"
elif [ "$1" = prune ]; then
echo "STARTING prune"
do_prune "$2"
echo "DONE prune"
else
print_help && exit 1
fi
elif [ "$#" = 1 ]; then
if [ "$1" != backup ]; then
print_help && exit 1
fi
echo "STARTING backup"
do_backup
echo "DONE backup"
else
print_help && exit 1
fi
exit 0
{% endraw %}