From 09f9f14b93856b7ffc673e32b314ffdf21546afa Mon Sep 17 00:00:00 2001 From: tech Date: Mon, 27 Apr 2026 17:22:10 +0800 Subject: [PATCH] docs: add sqlite to postgres migration runbook --- README.md | 52 +---- docs/sqlite-to-postgres-migration.md | 185 ++++++++++++++++++ .../plans/2026-03-20-gitea-lan-deployment.md | 2 +- 3 files changed, 191 insertions(+), 48 deletions(-) create mode 100644 docs/sqlite-to-postgres-migration.md diff --git a/README.md b/README.md index fb3cf67..bbb8ad0 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,8 @@ tar -czvf gitea-data-$(date +%Y%m%d).tar.gz data/ docker exec postgres pg_dump -U gitea gitea > gitea-db-$(date +%Y%m%d).sql ``` +> 如果当前生产服务仍在使用旧版 SQLite,请在迁移前停止 Gitea,并至少备份 `data/gitea/gitea.db` 和完整 `data/` 目录。完整流程见 [SQLite 迁移到 PostgreSQL](docs/sqlite-to-postgres-migration.md)。 + ### 恢复数据库 ```bash @@ -137,55 +139,11 @@ cat gitea-db-20260327.sql | docker exec -i postgres psql -U gitea gitea ## SQLite 迁移到 PostgreSQL -如果之前使用 SQLite,需执行以下步骤迁移到 PostgreSQL: +如果已有生产 Gitea 仍在使用旧版 Docker Compose 和 SQLite,不要直接启动最新 compose 覆盖数据库配置,也不要把 `gitea migrate` 当作数据搬迁命令。 -### 1. 停止 Gitea(保留 PostgreSQL 运行) +推荐流程是:停止旧 Gitea,冷备份 `data/gitea/gitea.db` 和 `data/`,更新到包含 PostgreSQL 的最新 commit,只启动空 PostgreSQL,用 `pgloader` 导入 SQLite 数据,最后启动 Gitea 并验证。 -```bash -docker compose stop gitea -``` - -### 2. 备份现有数据 - -```bash -cp data/gitea/gitea.db data/gitea/gitea.db.bak -``` - -### 3. 修改 app.ini 数据库配置 - -编辑 `data/gitea/conf/app.ini`,将 `[database]` 段改为: - -```ini -[database] -DB_TYPE = postgres -HOST = postgres:5432 -NAME = gitea -USER = gitea -PASSWD = <你的 POSTGRES_PASSWORD> -SCHEMA = -SSL_MODE = disable -PATH = -``` - -> 注意:如果 docker-compose.yml 中已通过 `GITEA__database__*` 环境变量配置,则 app.ini 中的值会被覆盖,可不修改 app.ini。 - -### 4. 执行数据迁移 - -```bash -docker compose exec gitea gitea migrate -``` - -### 5. 重启 Gitea - -```bash -docker compose start gitea -``` - -### 6. 验证 - -访问 Web 界面,确认用户、仓库数据完整。 - -> 迁移成功后 `data/gitea/gitea.db` 可以保留作为备份,不会影响 PostgreSQL 运行。 +完整步骤见 [docs/sqlite-to-postgres-migration.md](docs/sqlite-to-postgres-migration.md)。 ## 常用命令 diff --git a/docs/sqlite-to-postgres-migration.md b/docs/sqlite-to-postgres-migration.md new file mode 100644 index 0000000..1c19280 --- /dev/null +++ b/docs/sqlite-to-postgres-migration.md @@ -0,0 +1,185 @@ +# SQLite 迁移到 PostgreSQL + +本文档适用于已有 Gitea 服务仍在使用旧版 Docker Compose 和 SQLite,尚未更新到引入 PostgreSQL 的最新 commit 的场景。 + +迁移目标是把 `data/gitea/gitea.db` 中的业务数据导入到新的 PostgreSQL 数据库,同时继续复用现有的仓库、LFS、附件和配置目录。 + +> `gitea migrate` 不是 SQLite 到 PostgreSQL 的数据搬迁工具。它只会对当前 Gitea 配置指向的数据库执行 Gitea schema migration。数据库搬迁应使用 `pgloader` 完成。 + +## 迁移前准备 + +- 预留维护窗口。迁移期间必须停止 Gitea,避免 SQLite 继续写入。 +- 保持 `GITEA_VERSION` 不变。不要在同一次操作中同时升级 Gitea 版本和切换数据库。 +- 准备 `.env` 中的 PostgreSQL 配置: + +```env +POSTGRES_VERSION=16-alpine +POSTGRES_DB=gitea +POSTGRES_USER=gitea +POSTGRES_PASSWORD=<强密码> +``` + +- 确认可以运行 `sqlite3`,并能拉取或运行 `dimitri/pgloader:latest` 镜像。 +- 本文档默认 Docker Compose project 网络名为 `gitea_default`。如果实际名称不同,用下面命令查看后替换: + +```bash +docker network ls +``` + +## 1. 停止旧 Gitea + +在仍使用 SQLite 的旧版 compose 下停止 Gitea: + +```bash +docker compose stop gitea +``` + +如果启用了 Caddy,可以保持 Caddy 运行显示维护页,也可以一起停止: + +```bash +docker compose stop caddy +``` + +## 2. 冷备份 SQLite 和数据目录 + +```bash +ts=$(date +%Y%m%d-%H%M%S) +mkdir -p backups/$ts +cp data/gitea/gitea.db backups/$ts/gitea.db +cp data/gitea/conf/app.ini backups/$ts/app.ini +tar -czf backups/$ts/gitea-data.tar.gz data/git data/gitea +``` + +备份完成后,记录 SQLite 中的关键表数量,作为迁移后校验基线: + +```bash +sqlite3 data/gitea/gitea.db "select 'user', count(*) from user union all select 'repository', count(*) from repository union all select 'lfs_meta_object', count(*) from lfs_meta_object union all select 'public_key', count(*) from public_key union all select 'issue', count(*) from issue union all select 'release', count(*) from release;" +``` + +## 3. 更新代码并只启动 PostgreSQL + +更新到包含 PostgreSQL 服务的最新 commit,并补齐 `.env` 中的 PostgreSQL 配置。 + +```bash +git pull +``` + +先只启动 PostgreSQL,不要启动 Gitea: + +```bash +docker compose up -d postgres +``` + +确认 PostgreSQL 可连接: + +```bash +docker compose exec -T postgres psql -U gitea -d gitea -c "select version();" +``` + +## 4. 确认 PostgreSQL 是空库 + +检查目标库是否已有表: + +```bash +docker compose exec -T postgres psql -U gitea -d gitea -c '\dt' +``` + +如果已经有 Gitea 业务表,先确认这些表不是生产数据。确认可丢弃后,停止 PostgreSQL,备份并移走 `data/postgres/`,再重新启动空库: + +```bash +docker compose stop postgres +ts=$(date +%Y%m%d-%H%M%S) +mv data/postgres data/postgres.before-migration-$ts +docker compose up -d postgres +``` + +再次运行 `\dt`,确认目标库为空。 + +## 5. 使用 pgloader 导入 SQLite + +把 `` 替换为 `.env` 中的真实密码: + +```bash +docker run --rm \ + --network gitea_default \ + -v "$PWD/data/gitea:/data/gitea:ro" \ + dimitri/pgloader:latest \ + pgloader sqlite:///data/gitea/gitea.db postgresql://gitea:@postgres:5432/gitea +``` + +如果 compose project 网络名不是 `gitea_default`,替换 `--network` 参数。 + +导入完成后,检查目标库关键表数量: + +```bash +docker compose exec -T postgres psql -U gitea -d gitea -c "select 'user', count(*) from \"user\" union all select 'repository', count(*) from repository union all select 'lfs_meta_object', count(*) from lfs_meta_object union all select 'public_key', count(*) from public_key union all select 'issue', count(*) from issue union all select 'release', count(*) from release;" +``` + +这些数量应与第 2 步 SQLite 基线一致。 + +## 6. 启动 Gitea + +确认 `docker-compose.yml` 已通过 `GITEA__database__*` 环境变量指向 PostgreSQL,然后启动 Gitea: + +```bash +docker compose up -d gitea +docker compose logs -f gitea +``` + +Gitea 启动时会对 PostgreSQL 执行必要的 schema migration。日志中不应出现数据库连接、类型转换、唯一约束或 migration 错误。 + +如果使用 Caddy: + +```bash +docker compose up -d caddy +``` + +## 7. 迁移后验证 + +- 使用原管理员账号登录 Web UI。 +- 确认用户、组织、仓库、Issue、Release、SSH Key 等数据存在。 +- 执行一次 HTTP 或 HTTPS clone。 +- 执行一次 SSH clone。 +- 推送一个普通 commit。 +- 如果使用 Git LFS,执行一次 LFS push。 +- 检查日志: + +```bash +docker compose logs gitea postgres +``` + +## 回滚 + +如果迁移后验证失败,先停止新 Gitea: + +```bash +docker compose stop gitea +``` + +回滚到旧版 SQLite compose,或临时移除 `docker-compose.yml` 中的 `GITEA__database__*` 环境变量,避免它覆盖 `app.ini`。 + +恢复备份: + +```bash +cp backups/<备份时间>/gitea.db data/gitea/gitea.db +cp backups/<备份时间>/app.ini data/gitea/conf/app.ini +``` + +再启动旧 SQLite 版本: + +```bash +docker compose up -d gitea +``` + +在迁移完全确认前,不要删除 `data/gitea/gitea.db`、`backups/` 或迁移前的 `data/postgres.before-migration-*`。 + +## 演练建议 + +正式迁移前,建议在复制出来的目录中完整演练一次: + +```bash +cp -a gitea gitea-migration-dry-run +cd gitea-migration-dry-run +``` + +演练中也要验证空库检查、pgloader 导入、表数量对比、Gitea 启动和 Web/Git 操作。演练通过后,再在正式目录执行维护窗口迁移。 diff --git a/docs/superpowers/plans/2026-03-20-gitea-lan-deployment.md b/docs/superpowers/plans/2026-03-20-gitea-lan-deployment.md index 5be679c..b211f7e 100644 --- a/docs/superpowers/plans/2026-03-20-gitea-lan-deployment.md +++ b/docs/superpowers/plans/2026-03-20-gitea-lan-deployment.md @@ -141,7 +141,7 @@ caddy_config/ - 访问方式 - Git LFS 使用 - 数据备份(PostgreSQL pg_dump + 数据目录) -- SQLite 迁移到 PostgreSQL 步骤 +- SQLite 迁移到 PostgreSQL 的安全入口说明,链接到 `docs/sqlite-to-postgres-migration.md` - 常用命令 ---