CI/CD с Gitea для HomeLab
опубликовано: ⏰ 8Очень редко встречал Gitea в качестве DVCS + CI/CD решения, обычно все используют GitLab. Собственно, и сам первым делом попытался использовать GitLab, но практически сразу появились проблемы. Основная его проблема – это аппетиты к ресурсам, которые были ограничены. Поэтому пришлось искать альтернативы, и Gitea оказалась одной из них.
Введение
Зачем это всё нужно?
Во-первых, так или иначе, но для нормальной работы (SDLC) требуется хоть какой-то выстроенный процесс автоматизации сборки, тестирования и поставки приложений. Заниматься этим вручную, мягко говоря, не эффективно и не масштабируемо.
Во-вторых, не всегда есть возможность использовать публичные сервера, например, GitHub или GitLab. Там хотя и есть приватные репозитории, но всегда есть риск, что код утечёт. Либо сам сервис будет заблокирован, и придётся всё восстанавливать из резервных копий, повезёт, если делались достаточно часто.
В-третьих, иногда хочется иметь полный контроль над своими данными и процессами.
Поэтому и начал искать DVCS-сервер + CI/CD к нему, когда возникла потребность развернуть базовое окружение для разработки.
Варианты
В большинстве проектов обычно требовался довольно ограниченный функционал:
- Хранение кода.
- CI/CD.
- MR/PR.
- Иногда трекер задач.
По этой причине к DVCS-серверу каких-то особых требований не было. Из известных бесплатных решений, которые можно развернуть локально, было несколько вариантов:
| Решение | CI/CD | Сложность настройки | Язык разработки | Лицензия |
|---|---|---|---|---|
| GitLab | встроенный | Высокая | Ruby | Apache 2 |
| Gitea | встроенный, Drone, Woodpecker, Tekton | Низкая | Go | MIT |
| Forgejo (форк Gitea) | Woodpecker | Низкая | Go | GPLv3 |
| GitBucket + Jenkins | Jenkins | Средняя | Scala | Apache 2 / MIT |
Скажу честно, дальше Gitea я не пробовал, так как он полностью подошёл. Да и судя по скриншотам, у них примерно похожее всё.
GitLab и Gitea
В чём собственно была проблема с GitLab? По функционалу всё понятно, много где используется, много всего умеет и поддерживает. Но вот скорость старта и потребляемые ресурсы неприятно удивили. Ниже, как пример, пустые сервера с несколькими проектами и парой пользователей.
Процессы и потребление памяти у GitLab – ~7.5 GiB, время старта 2-3 минуты:

Время старта пара минут (до доступа к UI) и довольно сильно нагружает при этом CPU при запуске всех сервисов. Вроде бы можно отключить (Puma) кластеризацию у GitLab, что снизит потребление памяти, но ценой потери параллелизма.
Процессы и потребление памяти у Gitea – ~200-300 MiB, время старта 2-5 секунд:

Настройка раннеров для CI/CD у Gitea и Git примерно одинаковая и простая. Раннеры у обоих могут разворачиваться в Docker или на хосте. Запускаем, регистрируем и можно собирать проекты:
Дальше начинаются отличия: пайплайны у них разные:
- В GitLab используется собственный формат описания CI/CD pipelines.
- В Gitea используется форк nektos/act, это реализация GitHub Actions для локального запуска.
Сложно сказать, что лучше или хуже. По ощущениям, из коробки GitLab более функционален, а Gitea более понятный. При этом в Gitea есть возможность делать свои действия, которые потом можно использовать в пайплайнах. Ну, и получаем возможность использовать существующие GitHub Actions, все нужные были в наличии.
Пример пайплайна в Gitea, на котором тестировалось:
name: Build
on:
pull_request:
branches:
- main
- develop
push:
branches:
- main
- develop
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Maven
uses: stCarolas/setup-maven@v5
with:
maven-version: '3.9.9'
- name: Cache local Maven repository
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Cache Node.js modules
uses: actions/cache@v4
with:
path: ~/.npm # Or ./node_modules if you prefer caching locally
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Set up JDK (21)
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
- name: Set up Node.js (24)
uses: actions/setup-node@v4
with:
node-version: 24
- name: Setup settings.xml
uses: s4u/maven-settings-action@v3.1.0
with:
mirrors: |
[{
"id": "nexus.public",
"name": "public",
"mirrorOf": "*",
"url": "http://${{ vars.NEXUS_HOST }}/repository/maven-public/"
}]
servers: |
[{
"id": "nexus.private",
"username": "${{ secrets.NEXUS_USER }}",
"password": "${{ secrets.NEXUS_PASS }}"
}]
- name: Build and test
run: mvn --batch-mode clean deploy -Dnexus.host=${{ vars.NEXUS_HOST }}
- name: Generate JaCoCo coverage and Sonar reports
run: mvn --batch-mode jacoco:report sonar:sonar -Dsonar.token=${{ secrets.SONAR_TOKEN }} -Dsonar.host.url=${{ vars.SONAR_HOST }} -P sonarВ этом скрипте выполняются следующие шаги:
- Получение кода.
- Настройка кеширования Maven/NPM.
- Установка Maven.
- Установка NPM.
- Установка JDK.
- Сборка проекта и деплой артефактов в репозиторий.
- Генерация отчётов по тестам.
- Запуск Sonar.
По скорости получается довольно быстро, учитывая, что средний по размеру проект (65 модулей, ~41к строк) с:
- Генераторы protobuf, antlr4.
- Backend (Spring Boot).
- Frontend (NodeJS).
- SAST, тесты, отчёты и прочее.

И пару скриншотов интерфейса, очень похож на GitHub.


Возможность доработок
Учитывая, что после смены GitLab на Gitea получилось сэкономить почти 8 GiB оперативной памяти, то решил в качестве эксперимента попробовал добавить сборку в RAM (tmpfs). Как бонус, ещё снизить IOPS и износ SSD дисков. По умолчанию, в раннере (Docker) нельзя смонтировать рабочую директорию как tmpfs. Все тома монтируются на локальную файловую систему внутри временного контейнера задачи. Единственный вариант – это запуск на хосте, без докера. Либо поднять VM и сделать там всё, но не очень всё это нравилось.
В целом ничего сложного, но для этого пришлось форкнуть два проекта:
- https://github.com/devmix/fork-gitea-act – это модифицированный форк
nektos/act, в котором нужно было добавить поддержку параметров монтирования tmpfs для контейнеров. - https://github.com/devmix/fork_gitea_act_runner – это сам раннер, который используется в Gitea Actions.
Проблема только была с зависимостями и обновлением модуля Docker до версии с поддержкой опций для tmpfs. По
умолчанию, выставляется флаг noexec и перестаёт работать protobuf-компилятор при сборке проекта. По итогу всё
заработало
и настраивается парой параметров через конфигурацию раннера.
container:
workdir_mount_as_tempfs: true
workdir_tempfs_options: [ [ exec ] ]Сервер
Почему пытаюсь сэкономить ресурсы? Всё окружение пока решил развернуть на отдельной железке без виртуалок. Т.е. это минимально необходимый набор из:
- DVCS (GitLab -> Gitea).
- CI/CD (GitLab -> Gitea)
- Репозитории артефактов Maven, NPM, Docker Registry (Nexus).
- Общая RDBMS (PostgreSQL).
- SAST (SonarQube).
- NFS (Samba).
- Трекер задач (YoutTrack -> Gitea).
- Почтовый сервер (poste.io).
- Агенты LLM и сами проекты.
Всё на Docker Compose, но возможно стоило Proxmox/ESXi использовать для развертывания отдельных VM. Но опять же вопрос, как их потом нарезать с минимальными накладными издержками.
Ещё вылезла проблема с низкой скоростью WiFi. Возможно, роутер не справляется, которому уже лет 11 или эфир забит (смена каналов не помогает). Больше 8 MiB/s не получалось увидеть при передаче файлов. В итоге, купил коммутатор с 2.5G портами и завёл всё на него. Пришлось вспомнить старые времена с обжимкой патч-кордов, но к счастью без прокладки коробов. Руки ещё помнят :).
Вообще думал, что будут проблемы со старым кабелем категории 5e и нужной скорости не получу. Да и и бухта с кабелем, тоже лет 11 пролежала без дела. Но нет, скорость между устройствами на теоретическом максимуме для 2.5G.
Accepted connection from fe80::ccce:ac20:594c:7b73, port 58386
[ 5] local fe80::ecdf:64b9:2ebd:1c port 5201 connected to fe80::ccce:ac20:594c:7b73 port 49018
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 1.00-2.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 2.00-3.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 3.00-4.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 4.00-5.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 5.00-6.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 6.00-7.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 7.00-8.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 8.00-9.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 9.00-10.00 sec 277 MBytes 2.32 Gbits/sec
[ 5] 9.00-10.00 sec 277 MBytes 2.32 Gbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 2.82 GBytes 2.42 Gbits/sec receiverВот такая штука ExeGate EXE-725C-45 тоже оказалась полезной. Стоит недорого и нужна для ноута без RJ45 порта. Скорость как раз через неё в таблице выше.
Порты SFP+ в будущем можно для NAS использовать, если всё-таки соберу.

Заключение
Что сказать, теперь с Gitea. Нужно больше времени на тестирование, пока нравится больше GitLab и интерфейс кажется более удобным.
По потреблению ресурсов точно был смысл переходить. Если смотреть на возможности масштабирования, то на публичном хосте Gitea десятки тысяч проектов и пользователей, похоже масштабируется.