跳到主要内容

Gitea

Gitea 是一个轻量级的 DevOps 平台。它为团队和开发人员带来了从规划到生产的高效且轻松的操作。

以前选择使用 Gitea 二进制可执行文件在服务器上进行部署,现在觉得部署和备份成本太高,还是 Docker镜像 比较方便快捷。

id amass # 确认amass用户的uid、gid
docker run -d --restart=always --name=gitea \
-p 2022:2022 -p 3000:3000 \
-e USER_UID=1000 -e USER_GID=100 \
-e TZ="Asia/Shanghai" \
-v /mnt/user/appdata/gitea:/data \
gitea/gitea:1.24.6

参考 反向代理 一节,修改配置文件:/mnt/user/appdata/gitea/gitea/conf/app.ini。

因为 actions/checkout 不支持设置 Sub Path,所以我们也不使用 Gitea 的 Sub Path 以用来节省域名了。(自己实现 checkout 很繁琐,对于跨平台也有很多细节需要考虑。)

SSH 端口要经 frp 穿透出去,但经过 frp 转发后,Gitea 看到的来源地址全是 frpc 所在主机,日志和安全审计里拿不到客户端真实 IP。解决办法是让 frpc 在连接开头附带 PROXY protocol 头,再由 Gitea 解析。容器里自带的 OpenSSH 不认这个头,只有 Gitea 内置的 SSH 服务器能解析,所以 SSH 改用内置服务器:

[server]
ROOT_URL = https://gitea.amass.fun/
DOMAIN = gitea.amass.fun
SSH_DOMAIN = gitea.amass.fun
# 使用 Gitea 内置 SSH 服务器(PROXY protocol 只对它生效)
START_SSH_SERVER = true
# 内置 SSH 服务器监听的 SSH_LISTEN_PORT 默认等于该值
SSH_PORT = 2022
# 内置 SSH 服务器解析 PROXY protocol 头,拿到客户端真实 IP
SSH_SERVER_USE_PROXY_PROTOCOL = true

[service]
# 禁止外部用户自己注册,只能管理员创建账号
DISABLE_REGISTRATION = true

ENABLE_CAPTCHA = true

# 强制每次登录都必须输入验证码 (推荐开启)
REQUIRE_CAPTCHA_FOR_LOGIN = true

内置 SSH 服务器在容器内监听 2022,Unraid 的容器端口映射也要跟着改:删除原来的映射 1022:22(指向容器内的 OpenSSH),改为宿主机 2022 → 容器 2022。

frpc 一侧给对应的 proxy 加上 transport.proxyProtocolVersion = "v2",frpc 连上 Gitea 后会先发送带有访问者真实 IP 的 PROXY 头(官方说明):

frpc.toml
[[proxies]]
name = "gitea_ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 2022
remotePort = 2022
transport.proxyProtocolVersion = "v2"
注意

开启 SSH_SERVER_USE_PROXY_PROTOCOL 后,该端口只接受带 PROXY 头的连接,不带头的连接会被 Gitea 直接断开(日志 Failed to read proxy prefix)。所以内网直连 2022 端口的 SSH 会失败,SSH 都得走 frp;Gitea 和 frpc 两端也要同时改,只改一边都会连不上。

MySQL配置​

数据库准备:字符集用 utf8mb4,排序规则用区分大小写的 utf8mb4_0900_as_cs。[database] CHARSET_COLLATION 留空时,Gitea 也会自动挑一个区分大小写的排序规则。

Gitea Runner​

unRaid 应用市场的 Gitea-Runner 不支持 Docker-in-Docker,所以我们用 Dockyard 的 gitea_runner.dockerfile 自建镜像:

docker rm -f gitea-runner
rm -f /mnt/user/appdata/gitea-runner/.runner # 只删注册状态,强制重新注册,保留 config.yaml
docker run -d --name='gitea-runner' --restart=always \
-e TZ="Asia/Shanghai" \
-e GITEA_RUNNER_REGISTRATION_TOKEN='your_token' \
-e GITEA_RUNNER_NAME='unraid_gitea_runner' \
-e GITEA_RUNNER_LABELS='ubuntu-26.04-x64,ubuntu-latest-x64' \
-e GITEA_INSTANCE_URL='https://gitea.amass.fun' \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /mnt/user/appdata/gitea-runner:/data \
registry.cn-shenzhen.aliyuncs.com/amass_law/gitea_runner:5.1.1

GITEA_RUNNER_REGISTRATION_TOKEN:在Actions设置的创建 Runner的下拉框可以找到。

Windows​

这里我们记录Windows下的搭建步骤。从 dl.gitea.com/gitea-runner 下载 gitea-runner-<版本>-windows-amd64.exe,重命名为 gitea-runner.exe,以后升级直接替换这个文件。然后生成配置文件,并向Gitea服务器进行注册:

.\gitea-runner.exe config init # 在当前目录写一个只有注释的 config.yaml
.\gitea-runner.exe config set runner.capacity 1 # 同时跑几个 job,默认 1
.\gitea-runner.exe config set host.workdir_parent D:\Softwares\gitea-runner\work # job 工作目录,默认在 %USERPROFILE%\.cache\act
.\gitea-runner.exe register --no-interactive `
--instance https://gitea.amass.fun `
--token your_token `
--name windows11_unraid `
--labels windows11-x64

注册成功后会在当前文件夹下生成一个.runner文件。如果想重新进行修改注册,可以删掉这个文件然后再次执行上述命令。

执行:

.\gitea-runner.exe -c config.yaml daemon

即可启动 Gitea Runner 以接收并执行后续对应Gitea服务器的 actions。不过为了使得其可以开机运行,我们借助WinSW创建Windows服务,下载WinSW的可执行程序WinSW-x64.exe,拷贝到gitea-runner.exe所在的目录下。注意目录路径不能有空格和非ASCII字符。

将WinSW-x64.exe命名成gitea-runner-service.exe(事实上名字任意,只要和后面的xml文件同名即可),再创建配置文件:

D:\Softwares\gitea-runner\gitea-runner-service.xml
<!-- gitea-runner-service.xml -->
<service>
<id>gitea-runner</id>
<name>gitea-runner</name>
<description>Gitea runner is a runner for Gitea based on Gitea fork of act.</description>
<executable>D:\Softwares\gitea-runner\gitea-runner.exe</executable>
<onfailure action="restart" delay="5 sec" />
<resetfailure>1 day</resetfailure>
<!-- daemon 不会自动读当前目录的 config.yaml,所以要带上 -c config.yaml,而且这个文件必须存在,否则服务起不来 -->
<arguments>-c config.yaml daemon</arguments>
<workingdirectory>D:\Softwares\gitea-runner</workingdirectory>
<priority>AboveNormal</priority>
<stoptimeout>15 sec</stoptimeout>
<stopparentprocessfirst>false</stopparentprocessfirst>
<startmode>Automatic</startmode>
<waithint>15 sec</waithint>
<sleeptime>1 sec</sleeptime>
<logpath>D:\Softwares\gitea-runner\logs</logpath>
<log mode="roll-by-time">
<pattern>yyyyMMdd</pattern>
</log>
</service>

然后执行如下命令:

.\gitea-runner-service.exe install # 安装这个service
.\gitea-runner-service.exe start # 启动这个service

下载并安装Node.js、Git for Windows。执行如下命令,以让Windows可以成功执行任何 PowerShell 脚本:

Set-ExecutionPolicy Unrestricted
提示

在 Windows 服务找到我们注册的 Service(例如上述文件配置的 gitea-runner),双击其打开属性面板,在登录页面,我们选择以本地用户运行。这样 gitea-runner 执行的环境就和我们实际编译环境一致。服务默认以 LocalSystem(本地系统账户)运行,其用户目录、环境变量与 PATH 均与我们的用户不同,会导致环境不一致。

多机分流​

两台机器(N355 / 32G 与 Ultra 7 265K / 64G)各跑一个 Docker Runner 和一个 Windows 虚拟机 Runner,轻量项目哪台都能跑,大项目只进 265K。Gitea 没有调度器,分流只靠两条规则:

  • 匹配:job 的 runs-on 是一组标签,Runner 必须同时拥有全部标签才能领取(子集匹配,与 GitHub Actions 一致)。
  • 分配:Runner 按 runner.fetch_interval 轮询拉任务,谁空闲谁先领。所以“随机分配”不用配,capacity 用满的 Runner 不再领,任务自然流向另一台。

所以只要给 265K 上的 Runner 多挂一个 heavy 标签:

Runner标签capacity
unraid_gitea_runnerubuntu-26.04-x64,ubuntu-latest-x642
windows11_unraidwindows11-x641(默认)
ultra_gitea_runnerubuntu-26.04-x64,ubuntu-latest-x64,heavy4
windows11_ultrawindows11-x64,heavy1(默认)

架构后缀用 x64 / arm64:最短,也是 GitHub Actions 自托管 Runner 默认标签与 runner.arch 的叫法,以后接入 RK3576 这类 ARM 板子时就挂 arm64。

各 Runner 只有名字、标签和并发数不同。Docker 改上文 docker run 的这两行,Windows 改 register 的 --name 与 --labels:

-e GITEA_RUNNER_NAME='ultra_gitea_runner' \
-e GITEA_RUNNER_LABELS='ubuntu-26.04-x64,ubuntu-latest-x64,heavy' \
# Docker:Dockyard 镜像的配置在卷上的 /data/config.yaml
docker exec gitea-runner gitea-runner -c /data/config.yaml config set runner.capacity 4
docker restart gitea-runner
# Windows:在 gitea-runner.exe 所在目录执行,再重启服务
.\gitea-runner.exe config set runner.capacity 2
.\gitea-runner-service.exe restart

工作流里写:

jobs:
light:
runs-on: ubuntu-latest-x64 # 两台 Docker Runner 都能领
heavy:
runs-on: [ubuntu-latest-x64, heavy] # 只有 ultra_gitea_runner 两个标签都有
heavy-windows:
runs-on: [windows11-x64, heavy] # 只有 windows11_ultra
注意
  • 不要单写 runs-on: heavy,它会同时匹配 265K 上的 Linux 和 Windows 两个 Runner。
  • 带同一个平台标签的 Runner 环境必须一致:两台 NAS 要跑同一个 tag 的 Dockyard 镜像,两台 Windows 虚拟机要装同样的工具链,否则轻量任务落到哪台全凭运气,时好时坏。
  • heavy 的 schema 要跟平台标签一致。现在的标签都不写 schema(host 模式),heavy 也不写。如果平台标签改成 name:docker://镜像,heavy 也要写成同一个 docker://镜像:Runner 按 runs-on 的顺序取第一个它认得的标签来决定执行环境,heavy 一排到前面,任务就会改在 Runner 本机上跑。

迁移、备份​

打包数据目录:

cd /mnt/user/appdata/
tar czvf gitea.tar.gz ./gitea

数据库导出​

使用 HeidiSQL 备份数据库:

为了确保所有数据都能完成导出,建议将 最大 INSERT 大小 的值尽可能加大。

数据库导入​

首先选中 MySQL 实例:

然后导入sql:

选择我们之前导出的文件 gitea.sql,按提示确认之后,数据库即可导入完成。

评论

如果内容有勘误、补充或不同看法,可以直接写在这里。

邮箱用于回复通知和显示头像,地址不会公开

删除评论

将删除 的这条评论,以及它下面的全部回复。删除后无法恢复。