Files
server-deploy/gitea/README.md
2026-04-07 01:49:16 +08:00

680 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.0 | 数据库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
chmod +x deploy.sh backup.sh upgrade.sh migrate.sh
# 首次运行 → 自动安装系统依赖 + 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 签名提交
```bash
# 1. 生成 GPG 密钥
gpg --full-generate-key
# 选择 RSA and RSA → 4096 → 填写名字和邮箱
# 2. 查看密钥 ID
gpg --list-secret-keys --keyid-format=long
# 输出中 sec 行的 XXXXXXXXXXXXXXXX 就是密钥 ID
# 3. 导出公钥
gpg --armor --export XXXXXXXXXXXXXXXX
# 4. 在 Gitea 中添加
# → 头像 → 设置 → SSH/GPG 密钥 → 添加 GPG 密钥 → 粘贴公钥
# 5. 配置 Git 使用 GPG 签名
git config --global user.signingkey XXXXXXXXXXXXXXXX
git config --global commit.gpgsign true
# 6. 签名提交(之后所有 commit 自动签名)
git commit -S -m "signed commit"
```
### 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 # 启动
```
### 升级组件(一键脚本)
```bash
cd /opt/gitea
chmod +x upgrade.sh
# 交互式选择要升级的组件
bash upgrade.sh
# 或直接指定组件
bash upgrade.sh gitea # 仅升级 Gitea
bash upgrade.sh mysql # 仅升级 MySQL
bash upgrade.sh nginx # 仅升级 Nginx
bash upgrade.sh certbot # 仅升级 Certbot
bash upgrade.sh docker # 仅升级 Docker
bash upgrade.sh all # 升级全部
```
> 脚本会自动显示当前版本、执行备份、拉取新镜像、重启服务并验证。
---
### 手动升级详细步骤
#### 升级 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
chmod +x migrate.sh
# 导出迁移包(会自动停服 → mysqldump → 打包数据 → 打包配置)
bash migrate.sh export
# 生成: /var/backups/gitea/gitea_migrate_日期.tar.gz
# 传输到新服务器
scp /var/backups/gitea/gitea_migrate_*.tar.gz root@新服务器IP:/opt/gitea/
```
```bash
# ===== 新服务器 =====
# 前提:已安装 Docker可先运行 deploy.sh 的 Docker 安装步骤,或手动安装)
mkdir -p /opt/gitea
cd /opt/gitea
# 导入迁移包(会自动恢复配置 → 恢复数据 → 导入数据库 → 启动 → regenerate hooks → doctor check
bash migrate.sh import gitea_migrate_日期.tar.gz
# 验证迁移完整性
bash migrate.sh verify
```
**脚本自动完成的操作:**
| 阶段 | 操作 |
|------|------|
| 导出 | 停止 Gitea → mysqldump 导出数据库 → 打包 Gitea 数据目录 → 打包部署配置 → 生成迁移包 |
| 导入 | 解压 → 恢复配置 → 恢复数据目录 → 启动 MySQL → 导入数据库 → 启动 Gitea → regenerate hooks → doctor check |
| 验证 | 检查容器状态 → API 可达性 → 数据库连接 → 仓库/用户数量 → 数据目录完整性 → Nginx 状态 |
**迁移后注意事项:**
- 如域名或 IP 变更,导入前需修改 `.env` 中的 `GITEA_DOMAIN`
- 域名变更后需更新 DNS 解析并重新申请 SSL 证书:`certbot certonly --webroot -w /var/www/certbot -d 新域名`
- 如新服务器未安装 Nginx/Certbot可运行 `bash deploy.sh` 补装(脚本会跳过已有组件)
- 确保新服务器 Gitea 版本 ≥ 旧服务器版本(不支持降级)
- 官方建议使用 `mysqldump` 而非 `gitea dump` 的 XORM 导出(脚本已采用此方案)
<details>
<summary>手动迁移步骤(不使用脚本)</summary>
```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
```
</details>
---
## 五、安全加固清单
- [ ] 域名已启用 HTTPSdeploy.sh 自动完成)
- [ ] SSL 证书自动续期deploy.sh 自动配置 cron
- [ ] 关闭公开注册(`DISABLE_REGISTRATION=true`
- [ ] 启用登录才能浏览(`REQUIRE_SIGNIN=true`
- [ ] 配置防火墙仅开放 80/443/2222deploy.sh 自动完成)
- [ ] 云安全组已放行对应端口
- [ ] 服务器 SSH 改为密钥登录,禁用密码
- [ ] 定时备份已配置
- [ ] MySQL root 密码为随机强密码deploy.sh 自动生成)
- [ ] Gitea HTTP 端口仅监听 127.0.0.1(不对外暴露)
---
## 六、常见问题
**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 用户设置
- 确认 Git 提交邮箱与 GPG 密钥邮箱一致
**Q: 如何迁移到新服务器?**
使用迁移脚本一键完成,详见上方「迁移到新服务器」章节:
```bash
# 旧服务器导出
bash migrate.sh export
# 新服务器导入
bash migrate.sh import gitea_migrate_xxx.tar.gz
bash migrate.sh verify
```
---
## 服务器目录结构
```
/opt/gitea/ # 部署目录INSTALL_DIR
├── docker-compose.yml # Gitea + MySQL 容器编排
├── .env.example # 环境变量模板
├── .env # 运行时配置(自动生成)
├── deploy.sh # 全新服务器一键部署脚本
├── upgrade.sh # 组件升级脚本Gitea/MySQL/Nginx/Certbot/Docker
├── migrate.sh # 服务器迁移脚本(导出/导入/验证)
├── backup.sh # MySQL + 数据备份脚本
├── .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/>