备份

假设用户为:xxxx

Forgejo容器为:forgejo

PostgreSQL容器为:forgejo-db

1.创建备份目录

sudo mkdir -p /home/xxxx/backup/forgejo
sudo chown xxxx:xxxx /home/xxxx/backup/forgejo

2.创建脚本目录以及脚本文件

mkdir -p /home/xxxx/script

mkdir -p /home/xxxx/log

vim /home/xxxx/script/forgejo-backup.sh

脚本:

#!/bin/bash

set -Eeuo pipefail

# =====================
# Forgejo Backup Config
# =====================

DATE=$(date +%F-%H%M)

# 备份用户
BACKUP_USER="xxxx"

# 备份目录
BACKUP_DIR="/home/xxxx/backup/forgejo"

# 日志目录
LOG_DIR="/home/xxxx/log"
LOG_FILE="$LOG_DIR/forgejo-backup.log"

# Forgejo 数据目录
FORGEJO_DATA="/opt/docker/forgejo/data"

# Docker 容器
FORGEJO_CONTAINER="forgejo"
POSTGRES_CONTAINER="forgejo-db"

# PostgreSQL
DB_USER="forgejo"
DB_NAME="forgejo"

# 最低剩余空间 GB
MIN_FREE_GB=5

# 保留最近备份数量
RETENTION_COUNT=7


# =====================
# Logging
# =====================

mkdir -p "$LOG_DIR"

touch "$LOG_FILE"
chown "$BACKUP_USER:$BACKUP_USER" "$LOG_FILE"

exec > >(tee -a "$LOG_FILE") 2>&1


echo
echo "================================================"
echo "Forgejo backup start: $(date '+%F %T')"
echo "================================================"


# =====================
# Variables
# =====================

DATA_BACKUP="$BACKUP_DIR/forgejo-data-$DATE.tar.gz"
DB_BACKUP="$BACKUP_DIR/forgejo-db-$DATE.sql"



# =====================
# Check backup directory
# =====================

if [[ ! -d "$BACKUP_DIR" ]]; then
    echo "ERROR: Backup directory not found:"
    echo "$BACKUP_DIR"
    exit 1
fi



# =====================
# Check disk space
# =====================

FREE_KB=$(df -Pk "$BACKUP_DIR" | awk 'NR==2 {print $4}')
FREE_GB=$((FREE_KB / 1024 / 1024))

echo "Available disk space: ${FREE_GB}GB"

if (( FREE_GB < MIN_FREE_GB )); then
    echo "ERROR: Need at least ${MIN_FREE_GB}GB free space."
    exit 1
fi



# =====================
# Check containers
# =====================

if ! docker ps --format '{{.Names}}' | grep -qx "$FORGEJO_CONTAINER"; then
    echo "ERROR: Forgejo container is not running."
    exit 1
fi


if ! docker ps --format '{{.Names}}' | grep -qx "$POSTGRES_CONTAINER"; then
    echo "ERROR: PostgreSQL container is not running."
    exit 1
fi



# =====================
# Stop Forgejo
# =====================

echo "[1/6] Stop Forgejo..."

docker stop "$FORGEJO_CONTAINER"



# 无论成功失败,都启动 Forgejo
cleanup()
{
    echo "Restart Forgejo..."
    docker start "$FORGEJO_CONTAINER" >/dev/null 2>&1 || true
}

trap cleanup EXIT



# =====================
# Backup Forgejo data
# =====================

echo "[2/6] Backup Forgejo data..."


tar czf \
"$DATA_BACKUP" \
-C "$(dirname "$FORGEJO_DATA")" \
"$(basename "$FORGEJO_DATA")"



# =====================
# Backup PostgreSQL
# =====================

echo "[3/6] Backup PostgreSQL..."


docker exec "$POSTGRES_CONTAINER" \
pg_dump -U "$DB_USER" "$DB_NAME" \
> "$DB_BACKUP"



# =====================
# Verify backups
# =====================

echo "[4/6] Verify backup files..."


if [[ ! -s "$DATA_BACKUP" ]]; then
    echo "ERROR: Forgejo data backup failed."
    exit 1
fi


if [[ ! -s "$DB_BACKUP" ]]; then
    echo "ERROR: PostgreSQL backup failed."
    exit 1
fi


echo "Backup verified."



# =====================
# Remove old backups
# =====================

echo "[5/6] Remove old backups..."


echo "Removing old Forgejo data backups..."

ls -1t "$BACKUP_DIR"/forgejo-data-*.tar.gz 2>/dev/null \
| tail -n +$((RETENTION_COUNT + 1)) \
| xargs -r rm -f



echo "Removing old database backups..."

ls -1t "$BACKUP_DIR"/forgejo-db-*.sql 2>/dev/null \
| tail -n +$((RETENTION_COUNT + 1)) \
| xargs -r rm -f



# =====================
# Fix ownership
# =====================

echo "[6/6] Fix ownership..."


chown "$BACKUP_USER:$BACKUP_USER" \
"$DATA_BACKUP" \
"$DB_BACKUP"



# =====================
# Summary
# =====================

echo

echo "Backup files:"
ls -lh "$DATA_BACKUP"
ls -lh "$DB_BACKUP"


echo

echo "Current backups:"
ls -lh "$BACKUP_DIR"


echo
echo "================================================"
echo "Forgejo backup finished: $(date '+%F %T')"
echo "================================================"
echo

3.添加执行权限

chmod +x /home/xxxx/script/forgejo-backup.sh

4.测试

sudo /home/xxxx/script/forgejo-backup.sh

# 查看备份数据
ls /home/xxxx/backup/forgejo

5.定时执行(每天凌晨)

编辑:

sudo crontab -e

最后添加:

0 3 * * * /home/xxxx/script/forgejo-backup.sh

恢复

1.启动PostgreSQL和Forgejo 空环境

cd ~/docker/forgejo

docker compose up -d

2.停止 Forgejo

sudo docker stop forgejo

3.恢复 Forgejo data

备份数据:

forgejo-data-2026-01-01-0635.tar.gz

解压:

cd ~

tar xzf forgejo-data-2026-01-01-0635.tar.gz

恢复:

sudo cp -a data/* ~/docker/forgejo/data/

修复权限:

sudo chown -R 1000:1000 ~/docker/forgejo/data

4.恢复 PostgreSQL 数据库

备份数据:

forgejo-db-2026-01-01-0635.sql

进入数据库:

sudo docker exec -it forgejo-db psql -U forgejo forgejo

清空新数据库:

DROP SCHEMA public CASCADE;
CREATE SCHEMA public;

退出:

\q

5.导入数据

sudo docker exec -i forgejo-db \
psql -U forgejo forgejo \
< forgejo-db-2026-01-01-0635.sql

6.检查 Forgejo 配置

cat ~/docker/forgejo/data/gitea/conf/app.ini

重点:

# 如果数据库容器名字不同,需要修改
[database]
DB_TYPE = postgres
HOST = forgejo-db:5432
NAME = forgejo
USER = forgejo
# 如果域名改变,需要修改
[server]
DOMAIN = git.new.com
SSH_DOMAIN = git.new.com
ROOT_URL = https://git.new.com/

7.启动 Forgejo

sudo docker start forgejo

8.健康检查

sudo docker exec -u git -it forgejo forgejo doctor check --all --log-file /tmp/doctor.log