先把结论放在前面:如果你手头有 Mac mini、MacBook 或者黑苹果主机,想用它跑 Gitea Actions,完全可行。而且相比租用云上的 macOS 构建机,自建 Runner 更省钱、更可控,尤其适合需要做 iOS 签名、多架构编译、本地联调的场景。
这篇文章会从 Gitea Actions 的基本概念讲起,带你完成 Runner 的安装、注册、配置,再给一个能在 Apple 硬件上直接运行的 Workflow 示例。最后会整理常见报错和排查思路,方便你照着配置、照着排错。
文章内容适用于 Apple Silicon(M 系列)和 Intel 芯片的 Mac,重点讲思路和步骤,版本差异会在关键位置提醒你按实际环境调整。
1. Gitea Actions 是什么,为什么要在 Apple 硬件上跑
1.1 Gitea 与 Gitea Actions 的关系
Gitea 是一个轻量级的自托管 Git 服务,可以用很低的内存跑起来,适合个人、团队或企业内部使用。它提供仓库管理、Issue、Pull Request、Wiki 等常用功能,界面和 GitHub 很像。
Gitea Actions 是 Gitea 从 1.19 版本开始内置的 CI/CD 功能。它兼容 GitHub Actions 的工作流语法,也就是说,你可以在 Gitea 仓库里创建.gitea/workflows/*.yaml文件,用类似 GitHub Actions 的写法定义自动化任务。
一个 Gitea Actions 任务由两部分组成:
- Gitea 服务端:负责解析 Workflow、调度任务、记录日志。
- Runner:真正执行任务的机器,需要单独安装和注册。
Runner 可以跑在 Linux、Windows、macOS 等系统上。官网和多数教程默认使用 Linux 服务器作为 Runner,这很常见,但如果你需要在 Apple 硬件上跑任务,就要手动把 Runner 部署到 Mac 上。
1.2 为什么需要 Apple 硬件上的 Runner
最常见的需求是 iOS 或 macOS 应用的自动构建。Xcode 只能运行在 macOS 系统上,如果你用 Gitea 管理代码,又希望提交代码后自动触发xcodebuild、fastlane或pod install,就必须有一个 macOS 环境的 Runner。
即使你不做 iOS 开发,也有其他场景值得在 Apple 硬件上跑 Runner:
| 场景 | 原因 |
|---|---|
| iOS/macOS 应用编译 | 依赖 Xcode、Command Line Tools |
| Apple Silicon 专属构建 | 某些依赖或二进制只提供 arm64 macOS 版本 |
| Unity 构建 | Unity 的 macOS 版本更适合在 Mac 上执行 |
| 多架构验证 | 同一份代码既要在 amd64 上跑,也要在 arm64 上跑 |
| 本地调试 CI 流程 | Runner 就在旁边,出问题可以直接看进程和日志 |
如果你用的是 GitHub,官方虽然有 macOS Runner,但排队时间长、费用也高。Gitea Actions 自建 Runner 可以让你用现有的 Mac mini 或 MacBook 作为任务执行机,成本和自由度都更好。
1.3 Gitea Actions 的执行流程
先看整体流程:
开发者推送代码到 Gitea 仓库 ↓ Gitea 服务端检测到 .gitea/workflows/*.yaml 文件 ↓ Gitea 创建任务并发送给已注册的 Runner ↓ Runner 根据 Workflow 中的 jobs 步骤执行任务 ↓ 执行日志回传到 Gitea Web 界面这个流程里,Runner 是关键角色。Runner 不一定需要和 Gitea 服务端在同一台机器,你可以让 Gitea 跑在一台低配 Linux 服务器上,然后让一台 Mac mini 作为 Runner 连接过去。
2. 环境准备与前置条件
2.1 本文使用的环境说明
因为硬件和系统版本会影响具体命令,这里先说明我假设的环境:
- Apple 硬件:Mac mini / MacBook(Apple Silicon 或 Intel 均可)
- 操作系统:macOS(建议较新的稳定版本)
- Gitea:较新的稳定版本,至少为 1.19 或更高
- Runner:act_runner(Gitea 官方推荐的 Runner 实现)
- 依赖工具:Git、Go(可选,用于源码编译)
版本需要根据你的项目实际情况调整。本文重点演示配置思路,如果你的 Gitea 版本较老,建议先升级到较新稳定版,因为 Gitea Actions 的很多功能在旧版本上不可用。
2.2 确认芯片架构
Apple Silicon 和 Intel Mac 的架构不同,下载 Runner 时要选择对应的版本。执行以下命令确认:
uname -m输出结果:
arm64:Apple Silicon(M1、M2、M3、M4 系列)x86_64:Intel Mac
后续下载 Runner 时,需要根据这个结果选择对应的二进制文件。
2.3 检查必要工具
在 Mac 终端里确认 Git 是否已安装:
git --version如果提示找不到命令,可以先安装 Command Line Tools:
xcode-select --install这个命令会弹出图形化安装窗口,安装完成后 Git、make等常用命令基本就齐了。
如果你准备从源码编译 act_runner,还需要安装 Go:
go version如果 Go 不存在,可以使用 Homebrew 安装:
brew install go2.4 准备一台独立 Mac 作为 Runner(安全提醒)
在开始之前,有一个非常重要的安全提醒:
Gitea Actions 的工作流代码可能会被执行任意命令。如果 Runner 注册到公开仓库,仓库的贡献者可以通过修改 Workflow 来执行命令。建议不要使用日常办公或存放敏感数据的 Mac 作为 Runner,最好准备一台专用测试机,或者至少使用独立的用户账号、独立的文件目录。
后面在第 7 节还会展开说安全策略。
3. 安装并注册 act_runner
3.1 act_runner 是什么
act_runner 是 Gitea 官方提供的 Runner 程序,用于接收 Gitea 服务端下发的任务,然后执行 Workflow 中定义的步骤。
act_runner 有两种运行模式:
host模式:直接在宿主机上执行命令,适合需要 Xcode、系统签名等 macOS 原生能力的任务。docker模式:通过 Docker 容器执行命令,隔离性更好,但 macOS 上使用 Docker 需要额外安装 Docker Desktop 或 colima,且无法直接访问 Xcode。
在 Apple 硬件上,最常用的模式是host模式。这样 Workflow 里可以直接调用xcodebuild、fastlane等工具。
3.2 下载 act_runner
act_runner 可以从 Gitea 官方仓库的 Release 页面下载,也可以在安装了 Go 的机器上编译。这里以二进制下载为例。
打开终端,创建一个用于存放 Runner 的目录:
sudo mkdir -p /opt/act_runner sudo chown $(whoami) /opt/act_runner cd /opt/act_runner然后根据你的芯片架构下载对应文件。以 Apple Silicon 为例,大致命令如下(注意版本号请以官方 Release 页面为准):
curl -L -o act_runner https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-darwin-arm64如果是 Intel Mac,换成对应的darwin-amd64文件名即可。
下载后赋予执行权限:
chmod +x act_runner验证是否可运行:
./act_runner --version如果输出版本信息,说明二进制正常。
3.3 获取 Runner 注册令牌
在 Gitea Web 界面中,有两种方式可以创建 Runner Token:
- 站点管理员:进入“站点管理”→“Runner”,可以创建全局 Runner。
- 仓库所有者:进入仓库的“设置”→“Actions”,可以创建当前仓库可用的 Runner。
以仓库级别为例:
- 打开 Gitea 仓库页面。
- 点击顶部“设置”。
- 在左侧菜单中选择“Actions”。
- 点击“创建新 Token”或类似按钮。
- 复制生成的 Token。
Token 是 Runner 连接 Gitea 的凭证,请妥善保存,不要提交到 Git 仓库。
3.4 注册 Runner
回到终端,执行注册命令:
./act_runner register \ --instance http://127.0.0.1:3000 \ --token <你的Token> \ --name mac-runner \ --labels macos-latest:host参数说明:
| 参数 | 含义 |
|---|---|
--instance | Gitea 服务的地址,如果 Gitea 在其他机器,改成对应的 IP 或域名 |
--token | 上一步复制的注册令牌 |
--name | Runner 显示名称,方便在管理界面识别 |
--labels | Runner 可以执行的任务标签,macos-latest:host表示使用宿主机模式执行 |
注意macos-latest:host的格式:冒号前面是标签名,冒号后面是执行器类型。host表示直接在宿主机上执行,不是启动容器。
注册成功后,目录下会生成一个.runner文件。这个文件包含 Runner 的 ID、密钥等信息,不要删除,也不要提交到仓库。
3.5 启动 Runner
注册完成后,启动 Runner:
./act_runner daemon看到类似下面的日志,说明 Runner 已成功连接 Gitea:
INFO[0000] Starting runner daemon INFO[0000] Successfully connected to Gitea此时回到 Gitea 管理界面,可以看到名为mac-runner的 Runner 显示为在线状态。
daemon命令会占据当前终端,你可以保持终端打开,或者使用nohup放到后台:
nohup ./act_runner daemon > act_runner.log 2>&1 &如果需要开机自启,可以配置 macOS 的 launchd,后面第 7 节会说到。
4. 编写 Workflow 在 Apple 硬件上执行任务
4.1 创建 Workflow 文件
在 Gitea 仓库中,创建一个目录:
.gitea/workflows/然后新建一个 YAML 文件,例如build.yml。
下面是一个最简单的 Workflow,用于验证 Runner 是否正常工作:
name: Test on macOS on: push: workflow_dispatch: jobs: test-macos: runs-on: macos-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Show system info run: | uname -a uname -m sw_vers说明:
on.push:代码推送到仓库时触发。workflow_dispatch:允许在 Gitea 页面手动触发任务。runs-on: macos-latest:对应注册 Runner 时的标签macos-latest:host。actions/checkout@v4:从 Gitea 拉取当前仓库代码。Gitea Actions 兼容这个 Action。
保存并推送代码后,在 Gitea 仓库的“Actions”页面可以看到任务开始执行。点击任务可以查看实时日志。
预期日志会输出类似:
Darwin mac-mini.local 23.4.0 Darwin Kernel Version 23.4.0: arm64 arm64 ProductName: macOS ProductVersion: 14.5这就说明 Runner 已经在 Apple 硬件上成功执行了 Gitea Actions 任务。
4.2 在 Workflow 中使用 Xcode 构建
接下来看一个更贴近实际需求的例子:在 Apple 硬件上执行 Xcode 构建。
name: iOS Build on: push: tags: - 'v*' jobs: build: runs-on: macos-latest steps: - name: Checkout uses: actions/checkout@v4 - name: List available SDKs run: xcodebuild -showsdks - name: Show Xcode version run: xcodebuild -version - name: Build project run: | xcodebuild \ -project YourProject.xcodeproj \ -scheme YourScheme \ -configuration Release \ -sdk iphoneos \ -derivedDataPath build \ CODE_SIGNING_ALLOWED=NO \ build这个示例有两个关键点:
-derivedDataPath build:把构建产物输出到当前目录下的build文件夹,方便后续上传或查看。CODE_SIGNING_ALLOWED=NO:在没有配置签名证书的环境下,先关闭代码签名,只验证编译是否通过。
如果你需要完整签名和导出 IPA,可以在 Runner 上安装好证书和描述文件,然后在 Workflow 中使用环境变量或密钥传入签名信息,这里不再展开,但一定要避免把签名文件直接提交到仓库。
4.3 使用仓库 Secrets 传入敏感信息
如果你的构建脚本需要 API Key、证书密码等敏感信息,不要写在 YAML 文件里。建议在 Gitea 仓库的“设置”→“Actions”→“Secrets”中添加密钥。
然后在 Workflow 中通过环境变量引用:
- name: Build with secret run: | echo "$MY_SECRET" > secret.txt # 这里继续执行构建命令 env: MY_SECRET: ${{ secrets.MY_SECRET }}这样的好处是:
- 敏感信息不会出现在 Git 历史中。
- 不同仓库可以使用不同的密钥。
- 可以在不修改 Workflow 的情况下轮换密钥。
4.4 在 Workflow 中选择 amd64 或 arm64
如果你有多台 Runner,或者希望同一台 Mac 上区分架构,可以注册多个标签。例如在注册时使用:
./act_runner register \ --instance http://127.0.0.1:3000 \ --token <你的Token> \ --name mac-arm64-runner \ --labels macos-arm64:host,macos-latest:host这样 Workflow 可以这样写:
jobs: test-arm64: runs-on: macos-arm64 steps: - name: Show arch run: uname -m注意:--labels多个标签之间用逗号分隔,标签名不能重复,否则会造成 Runner 匹配混乱。
5. 进阶:常见构建场景与 Runner 维护
5.1 场景一:macOS 应用编译
macOS 应用和 iOS 应用类似,都需要 Xcode 工具链。在 Workflow 中可以直接执行xcodebuild,不过要注意:
- 需要提前打开一次 Xcode,或者在终端执行
sudo xcodebuild -license accept接受许可协议。 - 如果使用 Command Line Tools,部分 GUI 功能可能缺失,建议安装完整 Xcode。
5.2 场景二:多架构验证
很多跨平台项目需要同时产出 amd64 和 arm64 的构建产物。在 Apple Silicon 上,macOS 的 CGO 编译可能涉及架构问题。
例如 Go 项目:
- name: Build amd64 run: | GOOS=darwin GOARCH=amd64 go build -o bin/app-amd64 . - name: Build arm64 run: | GOOS=darwin GOARCH=arm64 go build -o bin/app-arm64 .如果还要交叉编译 Linux 版本,要注意 CGO 依赖可能导致失败,需要关闭 CGO 或使用对应的交叉编译工具链。
5.3 场景三:Runner 更新
act_runner 更新比较频繁。建议定期关注官方 Release,更新时先停止旧 Runner,替换二进制文件,再启动新 Runner。
更新步骤:
cd /opt/act_runner # 停止当前 Runner 进程 kill $(pgrep act_runner) # 备份旧配置 cp .runner .runner.bak # 下载新版本二进制 curl -L -o act_runner <新的下载地址> chmod +x act_runner # 启动新版本 nohup ./act_runner daemon > act_runner.log 2>&1 &.runner.bak在确认新版本运行正常后可以删除。
5.4 使用 launchd 开机自启
如果你希望 Mac 重启后 Runner 自动运行,可以配置 launchd。
创建 plist 文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.example.actrunner</string> <key>ProgramArguments</key> <array> <string>/opt/act_runner/act_runner</string> <string>daemon</string> </array> <key>WorkingDirectory</key> <string>/opt/act_runner</string> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/opt/act_runner/act_runner.log</string> <key>StandardErrorPath</key> <string>/opt/act_runner/act_runner.err.log</string> </dict> </plist>保存到/Library/LaunchDaemons/com.example.actrunner.plist,然后加载:
sudo chown root:wheel /Library/LaunchDaemons/com.example.actrunner.plist sudo launchctl load /Library/LaunchDaemons/com.example.actrunner.plist这里用/Library/LaunchDaemons而不是~/Library/LaunchAgents,是因为 Runner 通常需要以系统级服务运行,不受用户登录状态影响。注意,如果 Runner 需要访问钥匙串中的证书,建议单独配置登录钥匙串,避免权限问题。
6. 常见问题与排查思路
在 Apple 硬件上跑 Gitea Actions,最容易踩到的是下面几个坑。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| Runner 显示离线 | Runner 未启动、网络不通、Token 失效 | 查看 Runner 日志,确认 Gitea 地址可达,重新注册 |
| 任务一直卡在 queued | 标签不匹配、Runner 正忙 | 检查runs-on标签,确认 Runner 在线且空闲 |
| 执行命令提示无法找到 | PATH 环境不一致 | 在 Workflow 中使用绝对路径,或先执行which排查 |
xcodebuild无法使用 | 未安装 Xcode 或未接受许可 | 执行xcode-select --install,sudo xcodebuild -license accept |
docker相关步骤失败 | macOS 上没有 Docker | 改用host模式,或安装 Docker Desktop / colima |
| 签名失败 | 证书未导入、钥匙串权限不足 | 将证书导入 Runner 的钥匙串,并设置访问权限 |
| 网络下载慢 | 国内网络到 GitHub 资源受限 | 使用代理或镜像站,但要注意合规性 |
6.1 Runner 显示离线
首先确认进程是否还在:
ps aux | grep act_runner如果进程存在,再查看日志:
tail -f /opt/act_runner/act_runner.log常见错误是 Gitea 地址被写成了localhost,但 Runner 在远端机器上。此时要把--instance改成 Gitea 所在机器的局域网 IP 或域名。
6.2 任务一直处于 queued 状态
打开 Gitea 仓库的 Actions 页面,查看任务详情。如果显示waiting for a runner,说明没有找到匹配的 Runner。
检查点:
- 注册 Runner 时的
--labels是否包含 Workflow 中使用的标签。 - 该 Runner 是否已经离线。
- Gitea 版本是否支持该标签格式。
6.3 macOS 安全策略阻止执行
如果是下载的二进制,macOS 可能提示“无法打开,因为无法验证开发者”。这时需要手动允许:
- 打开“系统设置”→“隐私与安全性”。
- 在“安全性”部分找到被阻止的 App。
- 点击“仍要打开”。
这个操作只在图形界面下可用,如果通过 SSH 远程管理 Mac,可以先在本地设置一次,之后就不会再拦截。
6.4 Actions 日志看不到输出
如果任务显示成功,但日志没有内容,可能是 Runner 使用了host模式且输出缓冲问题。可以尝试在 Workflow 中加timeout-minutes,或者在命令后加; echo "step done"验证步骤是否真正执行。
7. 最佳实践与工程建议
7.1 Runner 安全边界
Gitea Actions 可以执行仓库内定义的任意命令,因此它的风险等价于“让仓库维护者在你的 Mac 上执行代码”。一定要明确一件事:如果 Runner 注册到了不受信任的仓库,等于给了对方代码执行权。
建议从以下几个方面控制风险:
- 只把 Runner 注册给私人仓库或可信团队仓库。
- 使用独立 macOS 用户账号运行 Runner,不要用管理员账号日常登录。
- 尽量在虚拟机或者单独的 Mac 上运行 Runner,不要使用主开发机。
- 对 Runner 能访问的网络、文件系统做最小授权。
- 多仓库共用 Runner 时,考虑容器隔离,但在 macOS 上容器隔离会牺牲 Xcode 访问能力。
7.2 签名与密钥管理
iOS/macOS 构建最常见的敏感信息是证书和描述文件。不要把.p12、.mobileprovision提交到仓库。
推荐做法:
- 将证书和描述文件保存到 Runner 本机,路径固定,例如
~/signing/。 - 在 Gitea Secrets 中保存证书密码,Workflow 运行时动态读取。
- 使用 fastlane 的
match或自定义脚本来管理描述文件。 - 定期轮换证书,并注意 Apple Developer 后台的吊销规则。
7.3 标签命名规范
Runner 的标签决定了 Workflow 如何选择执行机器。建议用清晰的命名:
| 标签示例 | 含义 |
|---|---|
macos-latest | 通用 macOS 任务 |
macos-arm64 | Apple Silicon 专用任务 |
macos-amd64 | Intel Mac 专用任务 |
macos-ios | iOS 构建专用任务 |
如果标签设置得太粗糙,会出现“任务被分到不支持的机器上”的问题;如果太细,又会导致 Runner 匹配效率低。按项目规模,控制在 2 到 4 个标签比较合适。
7.4 日志与监控
Runner 本机的日志默认输出到终端或指定文件。建议:
- 为
act_runner配置独立的日志文件,并设置日志轮转。 - 定期检查 Gitea 管理后台的 Runner 在线状态。
- 如果 Runner 长时间无任务,可以考虑增加一个定时健康检查任务,每隔一段时间向它的管理接口请求一次。
7.5 性能与温度控制
Mac mini 长期跑 CI 构建任务,散热和性能会是一个实际问题。建议:
- 在 Workflow 中设置合理的
timeout-minutes,避免异常任务一直占用资源。 - 高负载任务尽量错开执行。
- 如果使用 MacBook 作为 Runner,屏幕可以关闭,但要注意电源设置,避免合盖后进入休眠。
8. 总结与下一步学习方向
这篇文章从概念到实践,带你完成了一条完整的链路:
- 理解了 Gitea Actions 的组成架构和 Runner 在其中的作用。
- 在 Apple 硬件上安装并注册了 act_runner。
- 编写并运行了第一个 macOS Workflow。
- 了解了签名、密钥、多架构等进阶使用方式。
- 整理了常见问题排查思路和安全注意事项。
如果你只是想在个人 Mac 上跑通 CI,按照第 3 步和第 4 步操作即可。如果你要用于生产环境,我建议先从小项目验证 Runner 稳定性,再逐步接入正式仓库,不要第一天就把所有项目都挂到同一个 Runner 上。
接下来你可以继续研究这几个方向:
- Gitea Actions 的
actions/checkout和actions/cache在 macOS 上的行为差异。 - fastlane 在 Gitea Actions 中的完整 iOS 发布流程。
- 如何在同一台 Mac 上用多个用户配多套 Runner,实现任务隔离。
- 如何使用 colima 或 Docker 实现 macOS 下的容器化 Runner。
如果这篇文章对你有帮助,可以收藏备用。等你在自己的 Apple 硬件上跑通第一个 Gitea Actions 任务后,再回来对照排查清单做一次体检,后续踩坑会少很多。