# 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 导出(脚本已采用此方案)
手动迁移步骤(不使用脚本) ```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 ```
--- ## 五、安全加固清单 - [ ] 域名已启用 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: 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 官方文档(英文): - Gitea 官方文档(中文):