Initial sanitized deployment snapshot
This commit is contained in:
526
git-kc/docs/PLAN.md
Normal file
526
git-kc/docs/PLAN.md
Normal file
@@ -0,0 +1,526 @@
|
||||
# vps.git Docker 迁移方案 v1
|
||||
|
||||
## 目标
|
||||
|
||||
把 `vps.git` 上当前裸机部署的:
|
||||
|
||||
- Gitea
|
||||
- Keycloak
|
||||
- MySQL
|
||||
|
||||
迁移为 Docker 版本,并满足以下约束:
|
||||
|
||||
- `gitea`、`keycloak`、`mysql` 位于同一个 Docker 网络
|
||||
- MySQL 只保留一个容器实例,但实例内分两个独立库:
|
||||
- `<gitea_db>`
|
||||
- `<keycloak_db>`
|
||||
- 宿主机 `nginx` 架构不变,继续保留在宿主机上
|
||||
- Gitea 直接挂载现有数据目录
|
||||
- Keycloak 从 H2 迁移到 MySQL
|
||||
- 敏感信息统一放在 `.env`
|
||||
- Docker 部署根目录放在 `~/git-kc`
|
||||
- 本次迁移不顺手升级大版本,优先保持现有版本基线
|
||||
- 本次迁移默认先不启用 Git over SSH,仅保证 HTTPS Git 正常
|
||||
|
||||
---
|
||||
|
||||
## 当前现状摘要
|
||||
|
||||
### 服务现状
|
||||
|
||||
宿主机当前运行:
|
||||
|
||||
- `nginx`
|
||||
- `gitea.service`
|
||||
- `keycloak.service`
|
||||
- `mysql.service`
|
||||
|
||||
### 监听关系
|
||||
|
||||
- `nginx`:对外 `80/443`
|
||||
- `gitea`:宿主机监听 `3000`
|
||||
- `keycloak`:宿主机监听 `8443`
|
||||
- `mysql`:宿主机监听 `localhost:3306`
|
||||
|
||||
### 当前数据位置
|
||||
|
||||
- Gitea 配置:`/etc/gitea/app.ini`
|
||||
- Gitea 数据:`/var/lib/gitea`
|
||||
- Keycloak 配置:`/opt/keycloak/conf/keycloak.conf`
|
||||
- Keycloak H2 数据:`/opt/keycloak/data/h2`
|
||||
- MySQL 数据:`/var/lib/mysql`
|
||||
|
||||
### 当前版本基线
|
||||
|
||||
- Gitea:`1.22.4`
|
||||
- Keycloak:`26.0.6`
|
||||
- MySQL:`8.0.x`
|
||||
|
||||
迁移时保持同代版本,不使用 `latest`。
|
||||
|
||||
---
|
||||
|
||||
## 目标架构
|
||||
|
||||
### 宿主机保留
|
||||
|
||||
- `nginx`
|
||||
- 当前证书与域名
|
||||
- 宿主机 SSH 运维入口
|
||||
|
||||
### Docker 内运行
|
||||
|
||||
- `mysql`
|
||||
- `gitea`
|
||||
- `keycloak`
|
||||
|
||||
三者放在同一个 Docker 网络中,例如:
|
||||
|
||||
- `git-kc-net`
|
||||
|
||||
### 端口策略
|
||||
|
||||
- `mysql`
|
||||
- 不对宿主机发布端口
|
||||
- 仅允许 Docker 内部网络访问
|
||||
- `gitea`
|
||||
- 发布到 `localhost:3000`
|
||||
- `keycloak`
|
||||
- 发布到 `localhost:8080`
|
||||
|
||||
### nginx 反代目标
|
||||
|
||||
- `git.hangman-lab.top` → `http://localhost:3000`
|
||||
- `login.hangman-lab.top` → `http://localhost:8080`
|
||||
|
||||
说明:
|
||||
|
||||
- Gitea 迁移后,对外域名不变
|
||||
- Keycloak 迁移后,对外域名不变
|
||||
- Keycloak 容器内不再自行持有 HTTPS,TLS 由宿主机 nginx 负责终止
|
||||
|
||||
---
|
||||
|
||||
## 部署目录设计
|
||||
|
||||
Docker 部署根目录:
|
||||
|
||||
- `~/git-kc`
|
||||
|
||||
建议结构:
|
||||
|
||||
- `~/git-kc/compose.yaml`
|
||||
- `~/git-kc/.env`
|
||||
- `~/git-kc/backups/`
|
||||
- `~/git-kc/mysql/`
|
||||
- `~/git-kc/gitea/`
|
||||
- `~/git-kc/keycloak/`
|
||||
- `~/git-kc/keycloak/import/`
|
||||
- `~/git-kc/docs/`
|
||||
|
||||
用途说明:
|
||||
|
||||
- `compose.yaml`:Compose 主文件
|
||||
- `.env`:敏感配置
|
||||
- `backups/`:迁移专用备份
|
||||
- `gitea/`:Gitea 容器使用的配置副本
|
||||
- `keycloak/import/`:Keycloak realm 导入文件
|
||||
- `docs/`:迁移记录与回滚说明
|
||||
|
||||
---
|
||||
|
||||
## 数据与配置保留策略
|
||||
|
||||
### Gitea
|
||||
|
||||
Gitea 采用“保留原数据目录,容器挂载使用”的方式:
|
||||
|
||||
- 直接挂载现有数据目录:`/var/lib/gitea`
|
||||
|
||||
配置文件策略:
|
||||
|
||||
- 不直接原地修改宿主机当前使用的 `/etc/gitea/app.ini`
|
||||
- 先复制一份到:`~/git-kc/gitea/app.ini`
|
||||
- Docker Gitea 使用这份配置副本
|
||||
- 原始 `/etc/gitea/app.ini` 保留不动,用于快速回滚
|
||||
|
||||
### Keycloak
|
||||
|
||||
Keycloak 不直接复用当前运行目录作为 Docker 运行目录,而是:
|
||||
|
||||
1. 从旧 Keycloak 执行 realm export
|
||||
2. 在 Docker Keycloak 中导入 realm
|
||||
3. 新容器改用 MySQL 存储
|
||||
|
||||
旧目录保留:
|
||||
|
||||
- `/opt/keycloak/conf`
|
||||
- `/opt/keycloak/data/h2`
|
||||
|
||||
### MySQL
|
||||
|
||||
MySQL 不直接接管旧宿主机 datadir,而采用逻辑导出 / 导入迁移:
|
||||
|
||||
- 导出旧 `<gitea_db>`
|
||||
- 在 Docker MySQL 内创建新实例环境
|
||||
- 导入 `<gitea_db>`
|
||||
- 新建 `<keycloak_db>`
|
||||
|
||||
---
|
||||
|
||||
## 数据库设计
|
||||
|
||||
Docker MySQL 容器内使用一个实例,分为两个独立数据库:
|
||||
|
||||
- `<gitea_db>`
|
||||
- `<keycloak_db>`
|
||||
|
||||
分别创建独立账户:
|
||||
|
||||
- `gitea`
|
||||
- `keycloak`
|
||||
|
||||
权限原则:
|
||||
|
||||
- `gitea` 仅访问 `<gitea_db>`
|
||||
- `keycloak` 仅访问 `<keycloak_db>`
|
||||
|
||||
字符集与排序规则保持与当前环境一致:
|
||||
|
||||
- `utf8mb4`
|
||||
- `utf8mb4_0900_ai_ci`
|
||||
|
||||
说明:
|
||||
|
||||
- 是“共用一个 MySQL 容器实例”
|
||||
- 不是“共用同一个 database/schema”
|
||||
|
||||
---
|
||||
|
||||
## Gitea 容器设计
|
||||
|
||||
### 运行目标
|
||||
|
||||
迁移后保持:
|
||||
|
||||
- 域名不变
|
||||
- 数据目录不变
|
||||
- 仓库、用户、OIDC、package 等数据保留
|
||||
- 本次先不启用 Git over SSH
|
||||
|
||||
### 配置原则
|
||||
|
||||
基于现有 `app.ini` 的副本进行调整,重点改动:
|
||||
|
||||
- `[database] HOST`
|
||||
- 从 `localhost:3306`
|
||||
- 改为 `mysql:3306`
|
||||
|
||||
其余核心配置尽量保持不变,例如:
|
||||
|
||||
- `ROOT_URL`
|
||||
- `APP_DATA_PATH`
|
||||
- `repository ROOT`
|
||||
- `oauth2/openid`
|
||||
- `security`
|
||||
- `service`
|
||||
- `package/lfs/queue`
|
||||
|
||||
### 端口
|
||||
|
||||
- 宿主机:`localhost:3000`
|
||||
- 容器内:`3000`
|
||||
|
||||
### SSH 策略
|
||||
|
||||
本次迁移默认:
|
||||
|
||||
- 不启用 Git over SSH
|
||||
- 不抢占宿主机 `22`
|
||||
- 所有 Git 操作先走 HTTPS
|
||||
- Gitea 配置中应显式关闭 SSH(例如 `DISABLE_SSH = true`;若存在 `START_SSH_SERVER`,则设为 `false`)
|
||||
|
||||
后续如需恢复 Git over SSH,再单独设计第二阶段方案。
|
||||
|
||||
---
|
||||
|
||||
## Keycloak 容器设计
|
||||
|
||||
### 迁移原则
|
||||
|
||||
Keycloak 从:
|
||||
|
||||
- 裸机
|
||||
- H2
|
||||
- 自身提供 HTTPS 8443
|
||||
|
||||
迁移为:
|
||||
|
||||
- Docker
|
||||
- MySQL
|
||||
- 容器内部 HTTP
|
||||
- 宿主机 nginx 负责 TLS 终止
|
||||
|
||||
### 数据库连接
|
||||
|
||||
Keycloak 容器连接:
|
||||
|
||||
- Host:`mysql`
|
||||
- Port:`3306`
|
||||
- Database:`<keycloak_db>`
|
||||
|
||||
### 对外行为保持不变
|
||||
|
||||
- 域名:`login.hangman-lab.top`
|
||||
- Realm:`Hangman-Lab`
|
||||
- OIDC issuer 保持不变
|
||||
- 尽量保持原有 client 与集成关系不变
|
||||
|
||||
### 端口
|
||||
|
||||
- 宿主机:`localhost:8080`
|
||||
- 容器内:`8080`
|
||||
|
||||
### 容器配置原则
|
||||
|
||||
通过 `.env` 注入:
|
||||
|
||||
- `KC_DB=mysql`
|
||||
- `KC_DB_URL_HOST=mysql`
|
||||
- `KC_DB_URL_DATABASE=<keycloak_db>`
|
||||
- `KC_DB_USERNAME`
|
||||
- `KC_DB_PASSWORD`
|
||||
- `KC_HOSTNAME=login.hangman-lab.top`
|
||||
- `KC_HTTP_ENABLED=true`
|
||||
- `KC_PROXY_HEADERS=xforwarded`
|
||||
|
||||
说明:
|
||||
|
||||
- Docker Keycloak 不再自行持有 TLS 证书
|
||||
- nginx 负责 HTTPS
|
||||
|
||||
---
|
||||
|
||||
## nginx 变更原则
|
||||
|
||||
宿主机 nginx 架构保持不变。
|
||||
|
||||
### Gitea
|
||||
|
||||
继续反代到:
|
||||
|
||||
- `http://localhost:3000`
|
||||
|
||||
如容器沿用相同宿主端口,Gitea 对应 nginx 配置可能无需变更。
|
||||
|
||||
### Keycloak
|
||||
|
||||
需要把 upstream 从:
|
||||
|
||||
- `https://localhost:8443`
|
||||
|
||||
改为:
|
||||
|
||||
- `http://localhost:8080`
|
||||
|
||||
并保留以下头:
|
||||
|
||||
- `Host`
|
||||
- `X-Real-IP`
|
||||
- `X-Forwarded-For`
|
||||
- `X-Forwarded-Proto`
|
||||
|
||||
---
|
||||
|
||||
## 迁移实施步骤
|
||||
|
||||
### Phase A:准备阶段
|
||||
|
||||
1. 在 `vps.git` 上安装 Docker Engine 与 Docker Compose Plugin
|
||||
2. 创建目录:
|
||||
- `~/git-kc`
|
||||
- `~/git-kc/backups`
|
||||
- `~/git-kc/mysql`
|
||||
- `~/git-kc/gitea`
|
||||
- `~/git-kc/keycloak/import`
|
||||
- `~/git-kc/docs`
|
||||
3. 编写 `compose.yaml` 与 `.env`
|
||||
4. 复制 Gitea 当前配置:
|
||||
- `/etc/gitea/app.ini` → `~/git-kc/gitea/app.ini`
|
||||
5. 调整 Gitea 容器配置副本中的数据库地址
|
||||
6. 准备 Keycloak 容器参数
|
||||
7. 预拉取固定版本镜像
|
||||
|
||||
### Phase B:备份阶段
|
||||
|
||||
正式切换前执行迁移专用备份:
|
||||
|
||||
1. 备份 `/etc/gitea/app.ini`
|
||||
2. 记录并确认 `/var/lib/gitea` 当前状态
|
||||
3. 导出 Gitea 数据库:`mysqldump <gitea_db>`
|
||||
4. 从旧 Keycloak 导出 realm / users
|
||||
5. 备份 nginx 相关站点配置
|
||||
|
||||
说明:
|
||||
|
||||
- 即使整机已有备份,仍建议保留迁移专用备份,以便快速回滚
|
||||
|
||||
### Phase C:切换阶段
|
||||
|
||||
建议顺序:
|
||||
|
||||
1. 进入维护窗口
|
||||
2. 停止旧 Gitea:`systemctl stop gitea`
|
||||
3. 停止旧 Keycloak:`systemctl stop keycloak`
|
||||
4. 执行 Gitea 最终 SQL 导出
|
||||
5. 执行 Keycloak 最终 export
|
||||
6. 停止旧 MySQL:`systemctl stop mysql`
|
||||
7. 启动 Docker MySQL
|
||||
8. 初始化 Docker MySQL:
|
||||
- 创建 `<gitea_db>`
|
||||
- 创建 `<keycloak_db>`
|
||||
- 创建 `gitea` 用户
|
||||
- 创建 `keycloak` 用户
|
||||
9. 导入 Gitea SQL 到 Docker MySQL
|
||||
10. 启动 Docker Keycloak,并导入 realm
|
||||
11. 启动 Docker Gitea
|
||||
12. 修改 nginx 的 Keycloak upstream:
|
||||
- 从 `https://localhost:8443`
|
||||
- 改为 `http://localhost:8080`
|
||||
13. 执行 `nginx -t`
|
||||
14. 执行 `systemctl reload nginx`
|
||||
15. 执行完整验证
|
||||
|
||||
---
|
||||
|
||||
## 验证清单
|
||||
|
||||
### Gitea
|
||||
|
||||
- `https://git.hangman-lab.top/` 可访问
|
||||
- 首页正常
|
||||
- 用户可登录
|
||||
- 仓库列表正常
|
||||
- 既有仓库可见
|
||||
- Package 功能正常
|
||||
- HTTPS clone 正常
|
||||
- HTTPS push 正常
|
||||
- OIDC 登录可正常跳转到 Keycloak 并返回
|
||||
|
||||
### Keycloak
|
||||
|
||||
- `https://login.hangman-lab.top/` 可访问
|
||||
- Realm `Hangman-Lab` 正常
|
||||
- OIDC discovery 正常
|
||||
- 管理后台可登录
|
||||
- 普通用户可登录
|
||||
- 原有 client 保留
|
||||
- issuer 与原环境一致
|
||||
|
||||
### MySQL
|
||||
|
||||
- `<gitea_db>` 表完整
|
||||
- `<keycloak_db>` 表完整
|
||||
- Gitea 可正常连接数据库
|
||||
- Keycloak 可正常连接数据库
|
||||
- 容器重启后数据不丢失
|
||||
|
||||
### nginx
|
||||
|
||||
- HTTPS 证书正常
|
||||
- 无重定向循环
|
||||
- 无 mixed content
|
||||
- 代理头工作正常
|
||||
|
||||
---
|
||||
|
||||
## 回滚方案
|
||||
|
||||
如果迁移后验证失败,按以下顺序回滚:
|
||||
|
||||
1. 停止 Docker 容器:
|
||||
- `gitea`
|
||||
- `keycloak`
|
||||
- `mysql`
|
||||
2. 恢复 nginx 的 Keycloak upstream:
|
||||
- 改回 `https://localhost:8443`
|
||||
3. 启动旧宿主机服务:
|
||||
- `systemctl start mysql`
|
||||
- `systemctl start keycloak`
|
||||
- `systemctl start gitea`
|
||||
4. 执行 `nginx -t`
|
||||
5. 执行 `systemctl reload nginx`
|
||||
|
||||
回滚前提:
|
||||
|
||||
- 不删除旧数据
|
||||
- 不覆盖旧宿主配置
|
||||
- Gitea 使用配置副本而不是原地覆盖
|
||||
- MySQL 使用逻辑迁移而不是直接接管 datadir
|
||||
|
||||
---
|
||||
|
||||
## 主要风险点
|
||||
|
||||
### 1. Keycloak H2 → MySQL
|
||||
|
||||
这是整个迁移中最高风险点。
|
||||
|
||||
控制策略:
|
||||
|
||||
- 必须走 export / import
|
||||
- 不采用“直接改 DB 配置试运行”的方式
|
||||
|
||||
### 2. Gitea 与 Keycloak 的 OIDC 一致性
|
||||
|
||||
控制策略:
|
||||
|
||||
- 不改域名
|
||||
- 不改 realm 名称
|
||||
- 不改 issuer
|
||||
- 尽量不重建 client
|
||||
|
||||
### 3. Gitea 直接挂载旧目录
|
||||
|
||||
控制策略:
|
||||
|
||||
- 切换时必须先彻底停止旧 Gitea
|
||||
- 避免新旧环境同时访问同一数据目录
|
||||
|
||||
### 4. Keycloak 容器改为 HTTP
|
||||
|
||||
控制策略:
|
||||
|
||||
- 确保 nginx 传递正确代理头
|
||||
- 确保 Keycloak hostname 与 proxy 配置正确
|
||||
- 仅绑定到 `localhost`
|
||||
|
||||
---
|
||||
|
||||
## 已确定的关键决策
|
||||
|
||||
- 宿主机 nginx 架构不动
|
||||
- Docker 部署根目录使用 `~/git-kc`
|
||||
- Gitea 直接挂载现有数据目录
|
||||
- MySQL 采用逻辑迁移,不直接接管旧 datadir
|
||||
- Keycloak 改为 MySQL,走 export / import 迁移
|
||||
- 敏感信息统一放 `.env`
|
||||
- 版本先保持现状,不升级大版本
|
||||
- Git over SSH 本次先不启用;必要时后续单独设计第二阶段方案
|
||||
|
||||
---
|
||||
|
||||
## 结论
|
||||
|
||||
本方案的核心原则是:
|
||||
|
||||
- 先完成 Docker 化迁移
|
||||
- 保持外部域名与功能语义不变
|
||||
- 优先控制风险与保留回滚能力
|
||||
- 不把“迁移”与“升级”混在同一轮进行
|
||||
|
||||
在此基础上,下一步可进一步补充:
|
||||
|
||||
- `compose.yaml` 草案
|
||||
- `.env` 模板
|
||||
- 精确到命令级的实施 checklist
|
||||
Reference in New Issue
Block a user