ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

本地代码托管 + CI/Workflow(FreeBSD 自建 Gitea Actions)

本地代码托管 + CI/Workflow(FreeBSD 自建 Gitea Actions)

问题

我在近期开发项目的时候,碰到github时通时断的情况,非常影响项目进度。备用库用gitcode,但是没有CI那些功能服务。
我在想,能否在本地搭建一套库服务,能够提供github CI ,Workflow等服务,那多好啊!
服务器放在192.168.1.5 ,用户workbuddy ,密码放在.env文件中。你来帮我规划和实践一下!

AI帮我完成

目标:在192.168.1.5(FreeBSD 14.3)上自建一套类 GitHub 的代码托管 + CI 服务, 彻底摆脱 GitHub 时通时断对研发进度的影响。结论:不需要换成 Ubuntu,FreeBSD 原生即可。


1. TL;DR(已验证结论)

议题

结论

是否必须换 Ubuntu Linux?

。FreeBSD 14.3 + Gitea 1.24 + act_runner 0.4 完全够用。

CI 跑得动吗?

。host 模式单 job 实测0.22 秒跑通(uname/whoami/版本探测 + 单测)。

需要 Docker/Podman 吗?

不需要。采用host 模式(runner 直接在本机执行,无容器)。

actions/checkout 依赖 GitHub 吗?

已解除。裸写uses: actions/checkout@v4走本地匿名拉取。

开机自启吗?

gitea_enable=YESact_runner_enable=YES

服务地址:http://192.168.1.5:3000 | SSH 端口:2222


2. 架构概览

  • Gitea:pkg 安装(/usr/local/sbin/gitea),配置/usr/local/etc/gitea/conf/app.ini
  • act_runner:pkg 安装(/usr/local/bin/act_runner),以act_runner用户降权运行,由daemon(8)监护 +rc.d/act_runner开机自启。
  • Actions 日志/var/db/gitea/data/actions_log/<owner>/<repo>/<run>/<job>.log.zst(zstd 压缩)。

3. 部署脚本清单(deploy/

脚本

作用

01_setup_gitea.sh

初始化 Gitea 配置并启动(幂等;DEFAULT_ACTIONS_URL已固化为本地)。

02_setup_runner.sh

注册 act_runner 到 Gitea(host 模式)。

03_fix_runner_rc.sh

修复 rc 双重降权 bug(见 §4),设act_runner_enable=YES

04_cleanup_and_check.sh

清理诊断残留 daemon,确认工具链可用。

05_ci_smoke.sh

skywalk/ci-smoke仓库,跑冒烟 CI。

06_ci_logs.sh

演示如何读取 zstd 压缩的 actions 日志。

07~11_*.sh

探索过程脚本(已弃用):从尝试镜像 GitHub actions 到最终确定「自定义DEFAULT_ACTIONS_URL」方案。日常无需执行。

12_provision_local_actions.sh

幂等创建actions/checkout仓库(含action.ymlv1~v5标签)。用于从零复建或恢复。

凭据集中放在仓库根.envGITEA_URL/GITEA_ADMIN_USER/GITEA_ADMIN_PASS/GITEA_TOKEN)。 服务器上 token 同时存于/root/.gitea_token。 Windows 侧用tools/ssh_run.py远程执行(从.env读 SSH 凭据,避免明文散落)。


4. 关键修复:rc 双重降权 bug

现象:最初service act_runner start后,daemon监护进程本身以act_runner身份运行, 并以非 root 调-u act_runnersetusercontext()失败,陷入「failed to set user environment」无限重启。

根因:port 自带 rc 脚本使用${name}_user/${name}_group变量,会触发rc.subr自动su -m降权; 随后daemon -u再做一次降权,二次降权必然失败。

修复(03_fix_runner_rc.sh,已应用到服务器):把 rc 变量改名避开rc.subr的 su 钩子——

这样daemonroot启动、用-u ${act_runner_runas}完成唯一一次降权。 修复后进程树:daemon(root) → act_runner(act_runner),日志稳定打印declare successfully


5. host 模式验证结果(实测)

skywalk/ci-smoke仓库一次真实推送触发的 run:

  • whoami=act_runnerpwd=/var/db/act_runner/workspace/.../hostexecutor无容器
  • 内核:FreeBSD 14.3git/python3/node均在 PATH
  • python3 -c "print(2**32)"=4294967296
  • Job succeeded,总耗时 0.22 秒

工具链(runner 可见):git 2.52 / python3 3.11.14 / node v24.12.0 / bash 5.3 / go / make / gmake。


6. actions/checkout 去 GitHub 依赖

6.1 背景

GitHub 彻底不可达,无法镜像官方actions/checkout仓库。三种uses写法实测对比:

写法

结果

说明

uses: actions/checkout@v4(裸写)

✅ 成功

需配合下面「自定义DEFAULT_ACTIONS_URL

uses: http://192.168.1.5:3000/actions/checkout@v4(完整 URL)

✅ 成功

永远走本地,但业务 workflow 要写长 URL

run: git clone ...(手搓)

✅ 成功

最直观,但每次都要重复写

注意:裸写actions/checkout@v4DEFAULT_ACTIONS_URL=github时,runner 会去 GitHub 拉 action 本体(曾实测耗366 秒且常失败)——这正是要摆脱的痛点。

6.2 最终方案(业务 workflow 零改动)

app.ini[actions]段:

含义:当 workflow 裸写uses: actions/checkout@v4时,Gitea 把actions/checkout解析到本实例actions/checkout仓库(匿名 clone,公开仓库无需 token),从而完全不碰 GitHub。

配套仓库actions/checkout(组织actions,公开)已建好,含:

  • action.yml:纯compositeaction,用git直接检出(支持ref/token/path/fetch-depth/submodules/clean/lfs),不依赖 node / GitHub
  • 标签v1~v5(均为同一份action.yml,满足不同@vx写法)。

6.3 复建 / 恢复

若服务器清空需重建本地actions/checkout

脚本幂等:仓库/标签已存在则跳过,可安全反复执行。


7. 给真实仓库接入 CI(最小示例)

在你的仓库根放.gitea/workflows/ci.yml

推送到192.168.1.5:3000上的同名仓库即自动触发。查看运行:仓库页面 →Actions


8. 常用运维命令


9. 排错速查

症状

可能原因 / 处置

act_runner反复重启、日志failed to set user environment

rc 双重降权 bug → 重跑03_fix_runner_rc.sh

uses: actions/checkout@v4卡 300+ 秒或失败

DEFAULT_ACTIONS_URL仍是github→ 改成http://192.168.1.5:3000并重启 Gitea;确认actions/checkout仓库存在。

runner 不接单

检查runs-on标签与 runnerlabels是否匹配;service act_runner status;Gitea 后台 Actions 是否ENABLED

authentication required拉本地 action 仓库报错

仓库未公开或REQUIRE_SIGNIN_VIEW=true;确保仓库 public、REQUIRE_SIGNIN_VIEW=false(本部署已设)。

SSH 执行时会话 EOF

切勿在远程命令里用pkill -f act_runner(会误杀ssh_run.py自身命令行);改用pkill -x act_runner/pkill -x daemon


10. 已知约束 / 后续

  • host 模式无隔离:job 直接在 runner 本机跑,与宿主机共享文件系统(workspace 在/var/db/act_runner/workspace/)。只用于可信的内部仓库。
  • 未启用 Docker 执行:需要容器化 step 的场景当前不支持(本部署刻意不用 Docker)。
  • 僵死的 ubuntu1 虚拟机:按既定决策未动,保持现状,避免引入新变量。
  • python命令缺失:runner 上只有python3,业务脚本需用python3(或自行alias)。

实践

真不错,AI自动就帮着把所有的细节搞定了!

现在再跑CI,比github方便多了!

返回列表