惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
Vercel News
Vercel News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Y
Y Combinator Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
博客园 - 司徒正美
B
Blog RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
L
LangChain Blog

CodeSky 代码之空

如何让 AI 成为 24 小时牛马:我的个人项目实践 - CodeSky 代码之空 AI 浪潮下真实诉求的想象空间—同志仍需努力 - CodeSky 代码之空 AI 浪潮下的新时代开发模式—AI Coding 的快速成长 - CodeSky 代码之空 体验豆包手机的 24 小时 - CodeSky 代码之空 Agent Platform Self-Host 开源项目对比 - Coze Studio - CodeSky 代码之空 Chrome 端到端网络排查战记 - CodeSky 代码之空 瞎逼逼:2025 年还没有升级研发工具的你落伍了吗 - CodeSky 代码之空 Project. 博客重建计划 - CodeSky 代码之空 Python 音频去广告+字幕提取 - CodeSky 代码之空 群晖通过 Active Backup for Business 实现服务器快照 - CodeSky 代码之空 Windows WSL 启用 NVIDIA CUDA 配置教程 - CodeSky 代码之空 HTTP Auth From BasicAuth to WebAuthn - CodeSky 代码之空 Redis 分布式锁的实现 - CodeSky 代码之空 限流与常见实现 - CodeSky 代码之空 Redis 大 key、热 key 判别和解决方案 - CodeSky 代码之空 缓存:高并发读的救世主 - CodeSky 代码之空 如何解决服务中的事务问题 - CodeSky 代码之空 聊聊 MySQL 索引与索引设计 - CodeSky 代码之空 Redis 中使用键空间监听 key 过期消息 - CodeSky 代码之空 AI:Make 死宅 Great Again - CodeSky 代码之空
群晖 Gitea + Gitea Actions 安装与部署服务教程 - CodeSky ...
敖天羽 · 2025-01-29 · via CodeSky 代码之空

每当公有云类服务出现问题的时候,我都会庆幸还好我一个 NAS 走天下:

说(传销)了这么多,让我们回到本文的主题,关于怎么部署 Gitea 以及 Gitea Action,CI CD 到自己的服务器。

读前指南:请不要问「为什么不用 GitHub 这种问题,前面的 Case 已经说明。

Gitea 部署

Gitea 部署起来其实比较容易,你可以直接选择 Docker 安装,参考:使用 Docker 安装

如果你不需要使用 Gitea Action,那么完全可以用界面化的创建容器来进行:

此时你可能最低程度的需要填写下面的信息:

  • 环境变量
    • USER_UID
    • USER_GID
  • 目录映射:
    • /data

默认启在 3000 端口,SSH 为 22 端口,你可以进行自定义或者针对性的进行映射。

当然,实践发现如果你不用 SSH 的话其实 USER_UID 和 USER_GID 也用不到。

USER_UID 和 USER_GID 的获取方式是,先进入群晖的 ssh,然后执行以下命令:

1synouser --add git "passwd" "" 0 "" 0
2id git
3
4# output
5# uid=1030(git) gid=100(users) groups=100(users)
6

然后根据输出填上 uid 和 gid。也可以通过系统的用户创建,但此时 git 用户名是被保留的,只能选择创建别的名字后改名或者使用创建的名字,依然要到 SSH 里才能看到 uid 和 gid。

当然,我还自定义了端口号啥的,可参考配置。(之所以用 yaml 是因为之后 Gitea Action Runner 要保证运行的网络环境,所以用同一个 docker compose 串联)

1version: "3"
2networks:
3  mynet:
4    external: false
5
6services:
7  gitea:
8    image: gitea/gitea:latest
9    container_name: gitea
10    environment:
11      - PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
12      - USER=git
13      - GITEA_CUSTOM=/data/gitea
14      - USER_UID=1030
15      - USER_GID=100
16      - HTTP_PORT=6688
17      - DISABLE_SSH=false
18    restart: always
19    networks:
20      - mynet
21    volumes:
22      - /volume1/homes/git/.ssh:/data/git/.ssh
23      - /etc/localtime:/etc/localtime:ro
24      - /volume1/docker/gitea:/data
25    ports:
26      - "6688:6688"
27      - "2234:22"
28

运行后访问你映射的 HTTP 端口(默认为 3000),会有安装界面,如果你没有选择任何 DB,那么默认使用 SQL Lite 初始化就可以了,它会把配置存在 /data/conf/app.ini中,之后如果你需要修改配置是没有后台界面的,需要改 app.ini(比如显示的端口号,DB 设置,log 设置,邮箱设置等等)。

注意:app.ini 如果发现无权编辑,可以走 SSH sudo -u git vim /volume1/docker/gitea/gitea/conf/app.ini 来编辑。

坑点

有一个坑点是我使用群晖界面提供的镜像升级按钮把镜像从 1.22.6 升级到 1.23.1,然后直接再起不能了,因为 1.23 启动命令路径改了,建议不要随便升级,或者升级时做好一定的准备(指留出 debug 时间),毕竟存储来说稳定性最重要。

还好主要内容都是存在了挂载的目录下的,所以你重启一下就能恢复了。

Gitea Action Runner 部署

目前你有了一个能使用 HTTP / SSH 的 Git 托管服务,接下来我们介绍如何部署 Gitea Action。

首先,你可以阅读官方对于 Gitea Action 的介绍:https://docs.gitea.com/zh-cn/usage/actions/overview

如果你用过 GitHub Action,相信对于它已经不陌生了,基本上可以看做是兼容的,就连包都是兼容的(否则生态都建立不起来)。

要使用 Gitea Action,我们需要先部署 Runner:https://docs.gitea.com/zh-cn/usage/actions/act-runner

刚开始的时候我也很普通的常识根据教程启容器,但我发现启完了虽然 Gitea 中虽然成功显示了 Runner,但触发任务并不会调度到 Runner 上,问了 DeepSeek 老师半天,最终还是 Google 解决了:action container that gets triggered by act_runner can't communicate with gitea (docker in NAS),场景和问题是一模一样,得亏我们现在用的是 7 了,在 6 中 docker compose 是不外露的,你甚至要 SSH 上机器手动挡,现在你只要负责写文件就可以了。

这就是为什么我前面准备了一个 Docker Compose Yaml 的原因。在底部加上一个:

1  runner:
2    image: gitea/act_runner:nightly # nightly 版本比 latest 新很多
3    container_name: localrunner
4    restart: always
5    environment:
6      CONFIG_FILE: /config.yaml
7      GITEA_INSTANCE_URL: http://[gitea_site]/
8      GITEA_RUNNER_REGISTRATION_TOKEN: "your token"
9      GITEA_RUNNER_NAME: "localrunner"
10    networks:
11      - mynet
12    volumes:
13      - /volume1/docker/gitea-act-runner/config.yaml:/config.yaml
14      - /volume1/docker/gitea-act-runner:/data
15      - /var/run/docker.sock:/var/run/docker.sock
16    depends_on:
17      - gitea
18    ports:
19      - "9432:9432"
20

这里需要注意:

  1. INSTANCE_URL:填写你的 gitea URL
  2. REGISTRATION_TOKEN:http://[gitea_site]/-/admin/actions/runners,创建 Runner 中你会得到一个 Token,填入
  3. RUNNER_NAME:标识名
  4. networks:和 Gitea 同网络,我这里叫 mynet
  5. volumes 配置:
    1. 自定义的 config.yaml 用于配置,默认有配置,但建议还是搞一个,毕竟有了配置更灵活。
    2. Gitea Runner 配置映射到 /data
    3. docker.sock 用于调度,非常重要
  6. 端口号映射之后在介绍缓存时说明

自定义的 config.yaml 初始化时可能没有,可以关联后进容器执行命令:./act_runner generate-config

然后启动,我们就能看到 Runner 注册成功了。

此外,在配置文件里,我们会看到有个属性叫做 label,他决定了 runner 的 label 和关联的镜像,推荐先把涉及到的镜像都准备好,这里我准备了下面几种:

1  labels:
2    - "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest"
3    - "ubuntu-20.04:docker://gitea/runner-images:ubuntu-20.04"
4    - "ubuntu-raw-latest:docker://ubuntu:latest"
5

修改后重启容器就可以了。

缓存配置

使用 actions/cache这个 action 包可以让我们在诸如 npm install 阶段进行一些缓存处理,可以有效提升 Action 的效率,但如果你需要使用,得先进行配置,在官方文档中已有说明,可以修改 config.yaml

1cache:  
2enabled: true  
3dir: ""  # 这里 cache 存放目录,我已经提前映射了 /data,所以可以直接放在比如 /data/cache 下
4# 使用步骤 1. 获取的 LAN IP  
5host: "192.168.8.17"  
6# 使用步骤 2. 获取的端口号  
7port: 9432
8

因此在上面我暴露了 9432 端口,就是用来给 cache 用的。

Action 配置

有了 Action 后接下来我们就可以对 Action 进行测试并且正式投入使用,首先先试用一个测试的 Action,在某个仓库中新建一个文件 .gitea/workflows/test.yml

1name: Test Gitea Actions
2on: [push]
3
4jobs:
5  test:
6    name: Test Actions
7    runs-on: ubuntu-20.04
8    steps:
9      - name: Check out repository
10        uses: actions/checkout@v3
11      
12      - name: Setup Node
13        uses: actions/setup-node@v3
14        with:
15          node-version: '18'
16      
17      - name: Echo Test
18        run: |
19          echo "Hello from Gitea Actions!"
20          echo "Current directory: $PWD"
21          echo "Node version: $(node -v)"
22          echo "NPM version: $(npm -v)"
23      
24      - name: List Files
25        run: ls -la
26
27

runs-on就是你设置的 label,这里我选了其中一个。

如果在后台(/admin/actions/runners)开始了任务调度并显示「激活」,那就说明任务在跑了,如果 Runner 看上去再跑,但实际管理后台显示的是空闲,可能就存在问题。(理论上跟着这个教程走不会出现)。

测试成功后让我们开始准备 CI/CD,相关的教程其实可以直接参考 GitHub Action,这里我贴一个自用款,因为我的部署流程都是从 SFTP 发文件、重启 pm2,而前端项目的复杂度最高,还用到了前面配置的 action/cache,其他项目部署比较简单,因此贴个我的前端的配置:

1name: Deploy to Production
2on:
3  push:
4    branches:
5      - master  # 或者你的主分支名称
6
7jobs:
8  deploy:
9    name: Build and Deploy
10    runs-on: ubuntu-20.04
11    steps:
12      - name: Check out repository
13        uses: actions/checkout@v3
14      
15      - name: Setup Node
16        uses: actions/setup-node@v3
17        with:
18          node-version: '18'
19      
20      - name: Setup PNPM
21        uses: pnpm/action-setup@v2
22        with:
23          version: 9.15.1
24          
25      - name: Get pnpm store directory
26        id: pnpm-cache
27        run: |
28          echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
29
30      - name: Setup pnpm cache
31        uses: actions/cache@v3
32        with:
33          path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
34          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
35          restore-keys: |
36            ${{ runner.os }}-pnpm-store-
37
38      - name: Cache node_modules
39        uses: actions/cache@v3
40        with:
41          path: node_modules
42          key: ${{ runner.os }}-node-modules-${{ hashFiles('**/pnpm-lock.yaml') }}
43          restore-keys: |
44            ${{ runner.os }}-node-modules-
45      
46      - name: Setup PNPM Registry
47        run: pnpm config set registry https://registry.npmmirror.com
48      
49      - name: Install Dependencies
50        run: pnpm install
51      
52      - name: Build Application
53        run: pnpm build
54      
55      - name: Deploy to Server
56        uses: appleboy/[email protected]
57        with:
58          host: ${{ secrets.SSH_IP }}
59          username: ${{ secrets.SSH_USERNAME }}
60          password: ${{ secrets.SSH_PASSWORD }}
61          port: ${{ secrets.SSH_PORT }}
62          source: ".output/,.env"
63          target: "/root/target_path"
64          strip_components: 1
65      
66      - name: Execute PM2 reload
67        uses: appleboy/[email protected]
68        with:
69          host: ${{ secrets.SSH_IP }}
70          username: ${{ secrets.SSH_USERNAME }}
71          password: ${{ secrets.SSH_PASSWORD }}
72          port: ${{ secrets.SSH_PORT }}
73          script: |
74            export NVM_DIR="$HOME/.nvm"
75            [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
76            pm2 reload project
77

用了一下还是 appleboy/[email protected]这个库最简单粗暴,非常方便。

总结

又还了一个债,群晖玩家真是幸福啊,什么都能玩(我也有考虑过把监控回报,然后搭个 Grafana 啥的,毕竟服务太小了)。

如果使用遇到了任何问题,可以尝试查看官方文档或者查查 issue,DS 或者 GPT 老师还真不一定好使。

参考资料