Gitea MySQL 后端安装与迁移
ChatTea 现在支持两种 Gitea 数据库后端:
sqlite3:默认值,最轻量,适合本机开发和临时实践。mysql:通过 ChatData 管理 MySQL 二进制 runtime,不使用 Docker,适合需要长期运行和后续扩展的实例。
新实例推荐在安装/初始化时直接选择 MySQL;已有 SQLite 实例再使用迁移命令切换。
新装时直接选择 MySQL
最短路径是用 server bootstrap 一次完成 Gitea binary、MySQL runtime、app.ini、管理员和 token 初始化:
export GITEA_ADMIN_PASSWORD='[REDACTED]'
chattea server bootstrap \
--database-backend mysql \
--mysql-instance default \
--mysql-version 8.4.6 \
--mysql-database gitea \
--admin-password-env GITEA_ADMIN_PASSWORD \
--start-service \
-I
这个流程会做这些事:
- 下载或复用 ChatArch Gitea binary。
- 通过 ChatData 下载或复用 MySQL 官方二进制 tarball。
- 初始化
defaultMySQL 实例,写入 user-level systemd unit。 - 启动
chatdata-mysql-default.service,等待mysqladmin ping通过。 - 创建
giteadatabase,默认CHARACTER SET utf8mb4 COLLATE utf8mb4_bin。 - 如果传了
--mysql-user/--mysql-password-env,创建对应 MySQL 用户并授权该 database。 - 生成 MySQL 版 Gitea
app.ini。 - 运行
gitea migrate初始化 schema。 - 创建初始管理员和 token,并写入 ChatTea 凭据。
- 启动
chattea-gitea.service。
生成的 Gitea service 会自动依赖 ChatData MySQL service:
After=network.target chatdata-mysql-default.service
Requires=chatdata-mysql-default.service
这样重启机器后,Gitea 会等本机 MySQL service 先起来。
分步安装
如果不想一次 bootstrap,可以先准备二进制和数据库后端:
chattea server install \
--database-backend mysql \
--mysql-instance default \
--mysql-version 8.4.6 \
-I
再初始化 Gitea 配置:
chattea server init \
--database-backend mysql \
--mysql-instance default \
--mysql-version 8.4.6 \
--mysql-database gitea \
-I
最后按需创建管理员和 token,或直接使用 server bootstrap。
默认路径
ChatData-managed MySQL 不写系统目录,默认都在 ChatArch home 下:
~/.chatarch/chatdata/runtimes/mysql/8.4.6/
~/.chatarch/chatdata/instances/mysql/default/
~/.chatarch/chatdata/instances/mysql/default/run/mysql.sock
ChatTea 写入 Gitea app.ini 的数据库段类似:
[database]
DB_TYPE = mysql
HOST = ~/.chatarch/chatdata/instances/mysql/default/run/mysql.sock
NAME = gitea
USER = root
PASSWD =
SSL_MODE = disable
LOG_SQL = false
默认本机 ChatData MySQL 用 Unix socket 和无密码的本机 root 用户。需要 service user 时,请同时传 --mysql-user gitea --mysql-password-env MYSQL_PASSWORD;不要给默认 root 用户配置密码,因为 ChatData 本地开发实例的 root 用户已经存在,ChatTea 不会隐式修改 root 密码。
MySQL backend 需要 ChatData 0.1.1 或更新版本;0.1.1 提供了 ChatTea 依赖的 database user 创建/授权能力。
真实用例:本机 Gitea 切到 MySQL
本轮真实环境使用的是已有 ChatTea-managed Gitea,所以走的是“先迁移,再把安装流程补进 CLI”的路线。最终状态可用以下证据复现:
chattea server config get --section database --key DB_TYPE -I
# mysql
chattea server health
# ok: http://127.0.0.1:3000 (1.0.0)
systemctl --user is-active chatdata-mysql-default.service
# active
systemctl --user is-active chattea-gitea.service
# active
Gitea user service 已经能识别 MySQL socket,并依赖 ChatData MySQL service:
[Unit]
Description=ChatTea managed Gitea service
After=network.target chatdata-mysql-default.service
Requires=chatdata-mysql-default.service
这个改动只影响后端和 service 依赖,Gitea Web 页面本身没有视觉变化,所以当前文档不放页面截图;验证以后端配置、服务依赖、health 和 MySQL 表数据为准。
完整流程记录在 project 笔记中:
/home/zhihong/Playground/projects/07-18-chattea-mysql-backend/progress.md
低停机 side-by-side 迁移
更稳的生产迁移不是直接改当前 app.ini,而是在独立目录先起一个 shadow Gitea:
旧服务:127.0.0.1:3000 / chattea-gitea.service / 当前 work path
新服务:127.0.0.1:3001 / chattea-gitea-shadow.service / 独立 work path
入口:nginx proxy_pass 最后从 3000 切到 3001
第一轮可以在线预热:
export NEW_HOME="$HOME/.chatarch/chattea-shadow"
export NEW_WORK="$NEW_HOME/gitea"
export NEW_CONFIG="$NEW_WORK/custom/conf/app.ini"
export NEW_SERVICE="chattea-gitea-shadow.service"
export NEW_DB="gitea_shadow"
export MYSQL_PASSWORD='[REDACTED]'
# 先写 shadow app.ini 和 MySQL database/user,但暂不跑 gitea migrate,避免导入 dump 前创建空 schema。
chattea server init \
--work-path "$NEW_WORK" \
--config "$NEW_CONFIG" \
--base-url https://gitea.local.wzhecnu.cn \
--http-port 3001 \
--database-backend mysql \
--mysql-database "$NEW_DB" \
--mysql-user gitea \
--mysql-password-env MYSQL_PASSWORD \
--skip-gitea-migrate \
--force \
-I
# 复制仓库和附件类文件。保留 shadow app.ini,不复制旧 SQLite DB、日志和备份。
rsync -a --delete \
--exclude 'custom/conf/app.ini' \
--exclude 'data/gitea.db' \
--exclude 'log/' \
--exclude 'backups/' \
"$CHATTEA_WORK_PATH/" "$NEW_WORK/"
# 导出当前 DB 为 MySQL SQL,并导入 shadow database。
chattea server backup dump --database mysql --db-only --output "$NEW_WORK/backups/preheat-db.zip"
unzip -p "$NEW_WORK/backups/preheat-db.zip" '*gitea-db.sql' > "$NEW_WORK/backups/gitea-db.sql"
chatdata mysql client import --database "$NEW_DB" --file "$NEW_WORK/backups/gitea-db.sql"
# 对 shadow config 指向的新库跑 schema migration,然后启动 shadow service。
"$CHATTEA_BINARY" --config "$NEW_CONFIG" --work-path "$NEW_WORK" migrate
chattea server start --config "$NEW_CONFIG" --work-path "$NEW_WORK" --service-name "$NEW_SERVICE"
chattea server health --url http://127.0.0.1:3001
最终切换窗口只做增量和入口切换:
- 停旧服务或进入维护窗口,阻止新写入。
- 对旧 work path 再做一次
rsync -a --delete到 shadow work path。 - 对旧实例再做一次最新
chattea server backup dump --database mysql --db-only。 - 导入到一个新的空目标库,或清空 shadow 目标库后重新导入。
- 对 shadow 跑
gitea migrate,确认chattea server health --url http://127.0.0.1:3001正常。 - 修改 nginx
proxy_pass,把127.0.0.1:3000切到127.0.0.1:3001,nginx -t后 reload。 - 保留旧服务、旧目录和旧数据库一段时间;回滚就是把 nginx upstream 切回 3000。
这个方案不能保证真正 0 停机,因为 SQLite 或旧 Gitea 写入期间没有可靠双写到新 MySQL 的链路;但可以把停写窗口压缩到“最终增量 rsync + 最新 DB dump/import + nginx reload”的时间。
已有 SQLite 实例的备份能力
Gitea binary 自带这些相关命令:
gitea dump # 整站 dump:数据库、仓库、custom、data 等
gitea dump-repo # 仓库级导出
gitea restore-repo # 仓库级导入
gitea migrate # 对当前 app.ini 指向的 DB 执行 schema migration
当前没有一条对称的整站 gitea restore 命令。因此 ChatTea 的 SQLite -> MySQL 第一版迁移不走“整站 restore”,而是利用:
gitea dump --database mysql --skip-repository ...
Gitea 会把 SQLite 数据库导出成 MySQL SQL,dump 包里包含 gitea-db.sql。ChatTea 再把这个 SQL 导入 MySQL,然后切换 app.ini 的 [database]。
ChatTea 封装了备份命令:
chattea server backup dump --database sqlite3
chattea server backup dump --database mysql --db-only
--db-only 会跳过仓库、日志、custom、LFS、附件、packages 和 index,适合生成迁移 SQL;完整备份不要加 --db-only。
已有 SQLite 实例迁移
先建议做完整备份:
chattea server stop
chattea server backup dump \
--database sqlite3 \
--output /path/to/gitea-pre-mysql-full.zip
然后迁移:
chattea server migrate mysql \
--yes \
--mysql-instance default \
--mysql-version 8.4.6 \
--database gitea \
--stop-service \
--restart-service
迁移命令做这些事:
- 可选停止
chattea-gitea.service。 - 运行
gitea dump --database mysql --db-only生成 MySQL SQL。 - 从 dump zip 里抽取
gitea-db.sql。 - 通过 ChatData 创建 MySQL database。
- 创建并授权目标 MySQL 用户;默认 root 用户必须保持无密码,带密码时请使用非 root service user。
- 导入
gitea-db.sql。 - 备份
app.ini为app.ini.backup-<timestamp>。 - 更新
[database]为 MySQL。 - 运行
gitea migrate验证并补齐 schema。 - 可选重启
chattea-gitea.service。
命令默认要求 --yes,避免误切当前服务后端。
迁移后检查
chattea server config get --section database --key DB_TYPE -I
chattea server health
chattea repo list --limit 5
chatdata mysql client query \
--name default \
--version 8.4.6 \
--database gitea \
--sql 'SELECT COUNT(*) AS repos FROM repository;'
期望:
DB_TYPE是mysql;chattea server health返回 ok;chattea repo list能列出原有仓库;- MySQL 中
repository、user等表有数据。
回滚
迁移不会删除原来的 SQLite 文件。回滚时:
- 停 Gitea:
chattea server stop。 - 把
app.ini.backup-<timestamp>复制回app.ini。 - 启动 Gitea:
chattea server start。 - 检查
DB_TYPE是否回到sqlite3。
MySQL database 可以保留作为迁移证据,确认不再需要后再手动删除。