# Gitea 云服务器部署指南

> 全新服务器从零搭建，含 Docker + MySQL + Nginx HTTPS + Git LFS + SSH 密钥 + GPG 签名

## 架构概览

```
                    ┌──────────────────────────────────────────┐
                    │              云服务器                      │
  用户 ───HTTPS───→ │  Nginx:443 ──→ Gitea:3000                │
  用户 ───SSH────→  │  端口:2222  ──→ Gitea SSH                 │
                    │                  ↓                        │
                    │              MySQL:3306                    │
                    │                                           │
                    │  /opt/gitea/          部署文件 (compose等) │
                    │  /var/lib/gitea/      仓库+LFS+附件+密钥   │
                    │  /var/lib/mysql/gitea/ MySQL 数据           │
                    │  /var/backups/gitea/  备份文件              │
                    └──────────────────────────────────────────┘
```

| 组件 | 版本 | 说明 |
|------|------|------|
| Gitea | 1.25 | Git 托管服务（含内置 SSH 服务器） |
| MySQL | 8.4 LTS | 数据库（utf8mb4） |
| Nginx | 系统包 | HTTPS 反向代理 |
| Certbot | 系统包 | Let's Encrypt 自动 SSL 证书 |
| Docker | 最新 | 容器运行时 |

### 已启用功能

- **HTTPS**：Nginx + Let's Encrypt 免费 SSL，自动续期
- **Git LFS**：大文件存储，支持最大 4GB 单文件上传
- **SSH 密钥**：内置 SSH 服务器，支持 Ed25519/RSA 等密钥
- **GPG 签名**：提交签名验证，显示 "Verified" 徽标

---

## 一、前置条件

| 项目 | 要求 |
|------|------|
| 服务器 | 2核 2GB+ 内存，50GB+ SSD |
| 系统 | Ubuntu 20.04+ / Debian 11+ |
| 域名 | 已解析 A 记录到服务器 IP |
| 端口 | 80、443、2222 可从外网访问 |

> 如果使用云厂商（阿里云/腾讯云/AWS），需要在**安全组**中放行上述端口。

---

## 二、一键部署（全新服务器）

### 步骤 1：上传部署文件

```bash
# 在本地执行，将文件上传到服务器
scp -r gitea/ root@服务器IP:/opt/gitea
```

### 步骤 2：首次运行，生成配置

```bash
ssh root@服务器IP
cd /opt/gitea

# 首次运行 → 自动安装系统依赖 + Docker + Nginx
# 然后生成 .env 配置文件（密码已随机生成）并退出
bash deploy.sh
```

### 步骤 3：修改域名配置

```bash
vi .env
```

**必须修改的字段：**

```ini
GITEA_DOMAIN=git.yourdomain.com    # ← 你的实际域名
CERTBOT_EMAIL=you@yourdomain.com   # ← 你的邮箱（证书通知用）
```

可选修改：

```ini
SSH_PORT=2222                  # Git SSH 端口
GPG_SIGNING_NAME=Gitea         # GPG 签名显示名称
GPG_SIGNING_EMAIL=git@xxx.com  # GPG 签名邮箱
DISABLE_REGISTRATION=false     # 部署完成后改为 true
REQUIRE_SIGNIN=false           # 私有部署改为 true
```

### 步骤 4：执行部署

```bash
bash deploy.sh
```

脚本会自动完成以下 8 个步骤：

| 步骤 | 操作 |
|------|------|
| 1/8 | 系统更新，安装基础工具（curl, git, openssl 等）|
| 2/8 | 安装 Docker + Docker Compose V2 |
| 3/8 | 安装 Nginx |
| 4/8 | 验证 .env 配置 |
| 5/8 | 创建数据目录 |
| 6/8 | 配置防火墙（UFW/Firewalld）|
| 7/8 | 申请 SSL 证书 + 配置 Nginx HTTPS 反向代理 |
| 8/8 | 拉取镜像，启动 Gitea + MySQL 容器 |

### 步骤 5：初始化 Gitea

1. 浏览器打开 `https://git.yourdomain.com`
2. 进入安装向导（数据库已自动配置好）
3. **创建管理员账户**（务必设置强密码）
4. 点击 "安装 Gitea"

### 步骤 6：安装后加固

```bash
cd /opt/gitea

# 关闭公开注册
sed -i 's/DISABLE_REGISTRATION=false/DISABLE_REGISTRATION=true/' .env
# 要求登录才能浏览
sed -i 's/REQUIRE_SIGNIN=false/REQUIRE_SIGNIN=true/' .env

# 重启生效
docker compose up -d
```

---

## 三、功能使用指南

### SSH 密钥认证

```bash
# 1. 本地生成密钥（如果还没有）
ssh-keygen -t ed25519 -C "your@email.com"

# 2. 复制公钥
cat ~/.ssh/id_ed25519.pub

# 3. 在 Gitea 中添加
#    → 头像 → 设置 → SSH/GPG 密钥 → 添加密钥 → 粘贴公钥

# 4. 测试连接
ssh -T git@git.yourdomain.com -p 2222

# 5. 克隆仓库
git clone ssh://git@git.yourdomain.com:2222/用户名/仓库.git
```

### GPG 签名提交

#### 步骤 1：确认 GPG 可用

**macOS / Linux：**

```bash
gpg --version
```

如未安装：
- macOS: `brew install gnupg`
- Ubuntu/Debian: `sudo apt-get install gnupg`

**Windows：**

Windows 系统默认**没有** `gpg` 命令。推荐使用 Git for Windows 自带的 GPG（无需额外安装）：

```powershell
# 确认 Git 自带的 GPG 可用
& "C:\Program Files\Git\usr\bin\gpg.exe" --version
# 输出类似: gpg (GnuPG) 2.4.x
```

**将 GPG 加入系统 PATH（推荐，这样可以直接使用 `gpg` 命令）：**

```powershell
# 将 Git 自带的 GPG 目录添加到用户 PATH（永久生效，需重启终端）
$gpgDir = "C:\Program Files\Git\usr\bin"
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($userPath -notlike "*$gpgDir*") {
    [Environment]::SetEnvironmentVariable("Path", "$userPath;$gpgDir", "User")
    Write-Host "已添加到 PATH，请重启终端后生效"
}

# 重启终端后验证
gpg --version
```

> 也可以通过 **系统设置 → 系统 → 关于 → 高级系统设置 → 环境变量 → 用户变量 → Path → 编辑**，手动添加 `C:\Program Files\Git\usr\bin`。

**配置 Git 使用该 GPG（必须，否则 `git commit -S` 会报错）：**

```powershell
git config --global gpg.program "C:\Program Files\Git\usr\bin\gpg.exe"
```

> 也可以安装 [Gpg4win](https://www.gpg4win.org/)，安装后 `gpg` 会自动加入 PATH，无需上述配置。

#### 步骤 2：生成 GPG 密钥

> **Windows 用户注意**：必须在 **Git Bash** 中执行以下命令（不要在 PowerShell / CMD 中执行，因为交互式密钥生成在非 TTY 环境下会失败）。

```bash
gpg --full-generate-key
```

按提示依次操作：

| 提示 | 推荐选择 |
|------|----------|
| 密钥类型 | `1`（RSA and RSA） |
| 密钥长度 | `4096` |
| 有效期 | `0`（永不过期），然后输入 `y` 确认 |
| 真实姓名 | 你的名字（将显示在签名中） |
| 电子邮箱 | **必须与 Git / Gitea 的提交邮箱一致** |
| 注释 | 可留空，直接回车 |
| 确认 | 输入 `O`（Okay） |
| 密码 | 设置一个保护密码（每次签名提交时需要输入） |

#### 步骤 3：获取密钥 ID

```bash
gpg --list-secret-keys --keyid-format=long
```

输出示例：

```
sec   rsa4096/ABCDEF1234567890 2026-04-07 [SC]
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid                 [ultimate] Your Name <your@email.com>
ssb   rsa4096/1234567890ABCDEF 2026-04-07 [E]
```

其中 `sec` 行 `rsa4096/` 后面的 **ABCDEF1234567890** 就是密钥 ID。

#### 步骤 4：配置 Git 签名

```bash
# 设置签名密钥
git config --global user.signingkey ABCDEF1234567890

# 开启自动签名（之后所有 commit 自动签名，无需每次加 -S）
git config --global commit.gpgsign true
```

#### 步骤 5：导出公钥并添加到 Gitea

```bash
# 导出 ASCII 格式公钥
gpg --armor --export ABCDEF1234567890
```

复制输出的完整内容（从 `-----BEGIN PGP PUBLIC KEY BLOCK-----` 到 `-----END PGP PUBLIC KEY BLOCK-----`），然后：

1. 登录 Gitea → 头像 → **设置** → **SSH / GPG 密钥**
2. 点击 **添加密钥**（GPG 密钥区域）
3. 粘贴公钥 → 确认添加

#### 步骤 6：验证签名提交

```bash
# 测试签名提交
git commit --allow-empty -m "test: GPG signed commit"

# 验证签名
git log --show-signature -1
```

push 到 Gitea 后，提交记录旁会显示绿色 **Verified** 徽标。

### Git LFS 大文件

```bash
# 1. 安装 Git LFS（本地）
git lfs install

# 2. 跟踪大文件类型
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "*.bin"

# 3. 提交
git add .gitattributes
git add large-file.psd
git commit -m "add large file via LFS"
git push
```

---

## 四、日常运维

### 查看状态与日志

```bash
cd /opt/gitea

# 容器状态
docker compose ps

# 实时日志
docker compose logs -f          # 所有
docker compose logs -f server   # 仅 Gitea
docker compose logs -f db       # 仅 MySQL
```

### 重启 / 停止 / 启动

```bash
docker compose restart        # 重启所有
docker compose restart server # 仅重启 Gitea
docker compose down           # 停止并移除容器
docker compose up -d          # 启动
```

### 升级组件

#### 升级 Gitea

Gitea 以 Docker 容器运行，升级 = 拉取新镜像 + 重启容器。数据库结构变更会在启动时自动迁移。

```bash
cd /opt/gitea

# 1. 备份（必须！）
bash backup.sh

# 2. 查看当前版本
curl -s http://127.0.0.1:3000/api/v1/version

# 3. 修改目标版本（编辑 .env 中的 GITEA_IMAGE）
#    ● 查看最新版本号: https://github.com/go-gitea/gitea/releases
#    ● 或访问: https://hub.docker.com/r/gitea/gitea/tags
vi .env
# 修改: GITEA_IMAGE=gitea/gitea:1.25.5  ← 替换为目标版本号

# 4. 拉取新镜像
docker compose pull server

# 5. 重启（自动执行数据库迁移）
docker compose up -d server

# 6. 检查日志确认启动成功
docker compose logs -f server
# 看到 "Starting new Web server: tcp:0.0.0.0:3000" 表示成功
# Ctrl+C 退出日志

# 7. 验证新版本
curl -s http://127.0.0.1:3000/api/v1/version
```

**注意事项：**
- 务必查阅 [Gitea 发版说明](https://github.com/go-gitea/gitea/releases) 了解 Breaking Changes
- 不支持版本降级，升级前务必备份
- 跨多个大版本建议逐版本升级（如 1.21 → 1.22 → 1.23）

#### 升级 MySQL

**小版本升级（8.0.x → 8.0.y）**— 安全，直接拉取新镜像：

```bash
cd /opt/gitea

# 1. 备份
bash backup.sh

# 2. 拉取最新 8.0 补丁
docker compose pull db

# 3. 重启 MySQL
docker compose up -d db

# 4. 等待就绪，确认版本
docker compose exec db mysql --version

# 5. 重启 Gitea 刷新连接
docker compose restart server
```

**大版本升级（8.0 → 8.4 / 9.0）**— 需要导出/导入数据：

```bash
cd /opt/gitea

# 1. 完整备份
bash backup.sh

# 2. 导出数据库
docker compose exec -T db mysqldump \
    -u root -p"${DB_ROOT_PASSWORD}" \
    --single-transaction --routines --triggers \
    --databases gitea > /tmp/gitea_mysql_export.sql

# 3. 停止所有服务
docker compose down

# 4. 备份 MySQL 数据目录
cp -a /var/lib/mysql/gitea /var/lib/mysql/gitea.bak

# 5. 清空数据目录（新版本将重新初始化）
rm -rf /var/lib/mysql/gitea/*

# 6. 修改 docker-compose.yml 中的镜像版本
#    将 image: mysql:8.0 改为 image: mysql:8.4
vi docker-compose.yml
#    MySQL 8.4+ 如不需要旧认证插件，可删除 --mysql-native-password=ON

# 7. 启动新版本 MySQL（等待初始化完成）
docker compose up -d db
docker compose logs -f db
# 看到 "ready for connections" 后 Ctrl+C

# 8. 导入数据
docker compose exec -T db mysql \
    -u root -p"${DB_ROOT_PASSWORD}" < /tmp/gitea_mysql_export.sql

# 9. 启动 Gitea
docker compose up -d

# 10. 确认版本
docker compose exec db mysql --version
```

**注意事项：**
- MySQL 仅支持相邻大版本升级（8.0 → 8.4 → 9.0），不可跨版本
- 确认 Gitea 对目标 MySQL 版本的兼容性
- 回滚方法：`docker compose down` → 恢复数据目录和 docker-compose.yml → 重启

#### 升级 Nginx

Nginx 通过系统包管理器安装，使用系统更新升级：

```bash
# 1. 查看当前版本
nginx -v

# 2. 更新 Nginx
apt-get update && apt-get install -y --only-upgrade nginx
# CentOS/RHEL: yum update -y nginx

# 3. 验证配置文件无语法错误
nginx -t

# 4. 平滑重载（不中断服务）
systemctl reload nginx

# 5. 确认新版本
nginx -v
```

> Nginx 的 `reload` 是平滑重载，不会中断现有连接。只有配置文件变化才需要重载。

#### 升级 Certbot + 续期 SSL 证书

```bash
# 1. 查看当前版本
certbot --version

# 2. 更新 Certbot
apt-get update && apt-get install -y --only-upgrade certbot python3-certbot-nginx
# CentOS/RHEL: yum update -y certbot python3-certbot-nginx

# 3. 确认新版本
certbot --version

# 4. 查看证书状态
certbot certificates

# 5. 测试续期流程（不实际续期）
certbot renew --dry-run

# 6. 查看证书到期时间
openssl x509 -enddate -noout -in /etc/letsencrypt/live/你的域名/fullchain.pem

# 如证书即将到期或需要强制续期:
certbot renew --force-renewal --post-hook 'systemctl reload nginx'
```

> 证书自动续期已由 deploy.sh 配置 cron（每天 03:00 检查），通常无需手动操作。

#### 升级 Docker

```bash
# 1. 查看当前版本
docker --version
docker compose version

# 2. 更新 Docker Engine + Compose
apt-get update && apt-get install -y --only-upgrade \
    docker-ce docker-ce-cli containerd.io docker-compose-plugin
# CentOS/RHEL: yum update -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 3. 确认版本
docker --version
docker compose version

# 4. 确认容器正常运行
docker compose ps
```

> Docker 更新后服务会自动重启，容器在 `restart: always` 策略下会自动恢复。

### 定时自动备份

```bash
# 每天凌晨 3 点自动备份
crontab -e
# 添加：
0 3 * * * /opt/gitea/backup.sh >> /var/backups/gitea/cron.log 2>&1
```

备份内容：
- `db_日期.sql.gz` — MySQL 完整转储
- `gitea_data_日期.tar.gz` — 仓库 + LFS + 附件 + 头像 (`/var/lib/gitea/`)
- `config_日期.tar.gz` — .env + docker-compose.yml + nginx 配置

### 恢复备份

```bash
cd /opt/gitea

# 1. 停止服务
docker compose down

# 2. 恢复 Gitea 数据目录
tar xzf /var/backups/gitea/gitea_data_20260406_030000.tar.gz -C /var/lib/

# 3. 恢复配置
tar xzf /var/backups/gitea/config_20260406_030000.tar.gz -C /opt/gitea/

# 4. 启动 MySQL
docker compose up -d db
sleep 10

# 5. 恢复数据库
gunzip < /var/backups/gitea/db_20260406_030000.sql.gz | \
    docker compose exec -T db mysql -u root -p"${DB_ROOT_PASSWORD}"

# 6. 启动全部
docker compose up -d
```

### 迁移到新服务器

将已部署的 Gitea 完整迁移到另一台服务器，包含数据库、仓库、LFS、配置等全部数据。

> 参考 [Gitea 官方备份与恢复文档](https://docs.gitea.com/zh-cn/administration/backup-and-restore)

```bash
# ===== 旧服务器 =====
cd /opt/gitea

# 1. 停止 Gitea
docker compose stop server

# 2. 导出数据库
docker compose exec -T db mysqldump \
    -u root -p"${DB_ROOT_PASSWORD}" \
    --single-transaction --routines --triggers \
    --databases gitea > gitea-db.sql

# 3. 停止全部
docker compose down

# 4. 打包数据
tar czf gitea-data.tar.gz -C /var/lib/gitea .

# 5. 打包配置
tar czf gitea-config.tar.gz .env docker-compose.yml nginx/ *.sh

# 6. 传输
scp gitea-db.sql gitea-data.tar.gz gitea-config.tar.gz root@新服务器:/opt/gitea/
```

```bash
# ===== 新服务器 =====
cd /opt/gitea

# 7. 恢复配置
tar xzf gitea-config.tar.gz
vi .env  # 如需修改域名

# 8. 恢复数据
mkdir -p /var/lib/gitea
tar xzf gitea-data.tar.gz -C /var/lib/gitea
chown -R 1000:1000 /var/lib/gitea

# 9. 启动 MySQL 并导入
docker compose up -d db
# 等待就绪...
docker compose exec -T db mysql \
    -u root -p"${DB_ROOT_PASSWORD}" \
    --default-character-set=utf8mb4 < gitea-db.sql

# 10. 启动 Gitea
docker compose up -d

# 11. 重新生成 Git Hooks（必须！否则 push 会失败）
docker compose exec -u git server \
    /usr/local/bin/gitea -c /data/gitea/conf/app.ini admin regenerate hooks

# 12. 运行 doctor 修复潜在问题
docker compose exec -u git server \
    /usr/local/bin/gitea -c /data/gitea/conf/app.ini doctor check --all --fix
```

**迁移后注意事项：**
- 如域名或 IP 变更，导入前需修改 `.env` 中的 `GITEA_DOMAIN`
- 域名变更后需更新 DNS 解析并重新申请 SSL 证书：`certbot certonly --webroot -w /var/www/certbot -d 新域名`
- 如新服务器未安装 Nginx/Certbot，可运行 `bash deploy.sh` 补装（脚本会跳过已有组件）
- 确保新服务器 Gitea 版本 ≥ 旧服务器版本（不支持降级）
- 官方建议使用 `mysqldump` 而非 `gitea dump` 的 XORM 导出

---

## 五、完全卸载

如果需要从服务器上完全移除 Gitea，使用卸载脚本：

```bash
cd /opt/gitea
bash uninstall.sh
```

脚本会**交互式确认**每个危险操作，按顺序执行：

| 步骤 | 操作 | 确认方式 |
|------|------|----------|
| 0 | 卸载前备份（可选） | y/N |
| 1 | 停止并删除 Gitea + MySQL 容器和卷 | 输入 YES |
| 2 | 删除 Docker 镜像 | 自动 |
| 3 | 删除 Nginx 站点配置并重载 | 自动 |
| 4 | 删除 Let's Encrypt SSL 证书 | 自动 |
| 5 | 关闭防火墙 SSH 端口 (2222) | 自动 |
| 6 | 清理 Certbot 定时任务（仅当无其他证书时） | 自动 |
| 7 | 删除数据目录（Gitea + MySQL） | 输入 DELETE |
| 8 | 删除部署目录 `/opt/gitea` | y/N |

**备份目录 `/var/backups/gitea/` 始终保留**，不会被删除。

> 卸载后如需恢复，参考上方「恢复备份」章节。

<details>
<summary>手动卸载步骤（不使用脚本）</summary>

```bash
cd /opt/gitea

# 1. 建议先备份
bash backup.sh

# 2. 停止并删除容器、网络、卷
docker compose down -v

# 3. 删除 Docker 镜像（可选）
docker image rm gitea/gitea:1.25 mysql:8.4

# 4. 删除 Nginx 配置
rm -f /etc/nginx/sites-enabled/gitea /etc/nginx/sites-available/gitea
nginx -t && systemctl reload nginx

# 5. 删除 SSL 证书
certbot delete --cert-name 你的域名

# 6. 关闭防火墙端口
ufw delete allow 2222/tcp && ufw reload

# 7. 删除数据目录（⚠ 不可恢复）
rm -rf /var/lib/gitea
rm -rf /var/lib/mysql/gitea

# 8. 删除部署目录（可选）
rm -rf /opt/gitea

# 备份目录保留在 /var/backups/gitea/
```

</details>

---

## 六、安全加固清单

- [ ] 域名已启用 HTTPS（deploy.sh 自动完成）
- [ ] SSL 证书自动续期（deploy.sh 自动配置 cron）
- [ ] 关闭公开注册（`DISABLE_REGISTRATION=true`）
- [ ] 启用登录才能浏览（`REQUIRE_SIGNIN=true`）
- [ ] 配置防火墙仅开放 80/443/2222（deploy.sh 自动完成）
- [ ] 云安全组已放行对应端口
- [ ] 服务器 SSH 改为密钥登录，禁用密码
- [ ] 定时备份已配置
- [ ] MySQL root 密码为随机强密码（deploy.sh 自动生成）
- [ ] Gitea HTTP 端口仅监听 127.0.0.1（不对外暴露）

---

## 七、常见问题

**Q: 部署完成后访问显示 502 Bad Gateway？**
- 这是正常现象，说明 Nginx 已就绪但 Gitea 容器尚未启动完成
- 步骤 8 拉取 Docker 镜像较慢（首次需要下载约 300MB），等待脚本执行完毕即可
- 如脚本已结束仍然 502，手动启动容器：`cd /opt/gitea && docker compose up -d`
- 确认容器状态：`docker compose ps`，确认 Gitea 日志：`docker compose logs -f server`

**Q: SSL 证书申请失败？**
- 确认域名 A 记录已解析到服务器 IP（用 `dig git.yourdomain.com` 验证）
- 确认 80 端口可从外网访问（云安全组 + 防火墙）
- 等 DNS 生效后重新运行 `bash deploy.sh`

**Q: 忘记管理员密码？**
```bash
docker compose exec server gitea admin user change-password -u 管理员用户名 -p 新密码
```

**Q: Git LFS push 失败 / 超时？**
- Nginx 已配置 `client_max_body_size 4G`（LFS 路径单独配置）
- 如仍超时，检查服务器带宽和磁盘空间

**Q: GPG 签名的提交不显示 "Verified"？**
- 确认 GPG 公钥已添加到 Gitea 用户设置（头像 → 设置 → SSH/GPG 密钥）
- 确认 Git 提交邮箱（`git config user.email`）与 GPG 密钥邮箱**完全一致**
- 确认密钥未过期：`gpg --list-keys`

**Q: Windows 上 `gpg` 命令找不到？**
- Windows 默认不带 GPG，推荐使用 Git for Windows 自带的 GPG：
  ```powershell
  git config --global gpg.program "C:\Program Files\Git\usr\bin\gpg.exe"
  ```
- 或安装 [Gpg4win](https://www.gpg4win.org/)
- 生成密钥时请在 **Git Bash** 中执行 `gpg --full-generate-key`（PowerShell/CMD 下交互式生成会失败）

---

## 服务器目录结构

```
/opt/gitea/                         # 部署目录（INSTALL_DIR）
├── docker-compose.yml              # Gitea + MySQL 容器编排
├── .env.example                    # 环境变量模板
├── .env                            # 运行时配置（自动生成）
├── deploy.sh                       # 全新服务器一键部署脚本
├── backup.sh                       # MySQL + 数据备份脚本
├── uninstall.sh                    # 完全卸载脚本
├── .gitignore
├── README.md
└── nginx/
    └── gitea.conf                  # Nginx HTTPS 反向代理模板

/var/lib/gitea/                     # Gitea 应用数据（GITEA_DATA_DIR）
├── gitea/
│   ├── conf/app.ini                # Gitea 运行配置（首次安装后生成）
│   ├── repositories/               # Git 仓库文件
│   ├── lfs/                        # Git LFS 对象存储
│   ├── attachments/                # Issue / Release 附件
│   ├── avatars/                    # 用户头像
│   └── ...                         # 其他运行时数据
├── git/                            # Git 用户 home
└── ssh/                            # SSH 密钥

/var/lib/mysql/gitea/               # MySQL 数据文件（MYSQL_DATA_DIR）

/var/backups/gitea/                 # 备份文件（BACKUP_DIR）
├── db_日期.sql.gz                  # MySQL 转储
├── gitea_data_日期.tar.gz          # Gitea 数据快照
├── config_日期.tar.gz              # 配置备份
└── cron.log                        # 定时备份日志

/etc/nginx/sites-available/gitea    # Nginx HTTPS 配置（由 deploy.sh 生成）
/etc/letsencrypt/live/域名/         # SSL 证书（由 Certbot 管理）
```

## 官方文档

- Gitea 官方文档（英文）：<https://docs.gitea.com/>
- Gitea 官方文档（中文）：<https://docs.gitea.com/zh-cn/>
