Giteaを使ってみる
Giteaとは
Goで実装されたセルフホスト型のGitHubクローンで、Gitでのコードホスティング、GitHub Actionsと互換性のあるCI/CDシステムのGitea Actions、ラベルやマイルストーン等が設定可能な課題管理、ComposerやNPM等から利用可能なパッケージ機能など、GitHubでよく利用されているであろう機能は一通り実装されている。
くわしくはhttps://about.gitea.com/を参照
利用の経緯
以前からCI/CDに関して自分で設定して使ってみたいと思っていたのだが、他の技術調査優先で後回しになっていたところ、最近、CI/CDの経験やGitHub Actionsについて尋ねられることがあったり、個人的にやってる仕事等でも利用したいと思って本格的に調べ始めたらこれが見つかったというのがきっかけ。
インストール先の環境や方針について
個人で利用している国内のVPSサービス上のdebianでバージョンは12.9。
ほかのWEBベースのプロダクトがあったり、すでにSSLの設定済みということでnginxをリバースプロキシにしてアクセス。
debianのパッケージが公式で用意されていないというものあるが、一つのバイナリで実行可能で、環境変数や設定などの関連ファイルについても知りたいというのもあって公式バイナリからのインストール。
データベースに関しては個人での利用なのでひとまずsqliteで
インストール
実行ユーザーの作成
以下のコマンドで実行ユーザーを作成し、実行ユーザーへスイッチしておく。
実行ユーザーのホームディレクトリを/opt/gitea
にしておいて、基本的に関連ファイルはここにおくようにする。
$ sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /opt/gitea gitea
$ sudo su - gitea
バイナリのダウンロード
以下のコマンドで公式バイナリをダウンロード、この記事を書いている時点ではバージョンは1.23.4
、実行権限を付け、コマンド入力の際にバージョンまで入力しないで済むよう、リンクを作成。
$ curl -O https://dl.gitea.com/gitea/1.23.4/gitea-1.23.4-linux-amd64?_gl=1*x6hm9l*_gcl_au*MjczMTQ3MzY2LjE3Mzg4NDMzMTQ.
$ chmod u+x gitea-1.23.4-linux-amd64
$ ln -s gitea-1.23.4-linux-amd64 gitea
基本となる設定ファイルの作成
以下で設定ファイルを置くディレクトリを作成。giteaは環境変数で作業ディレクトリを指定することができ、そこをベースにした指定箇所にファイルを置いておけばわざわざ細かいパスを指定する必要がなくなるため、デフォルトのcustom/confとする。
$ mkdir -p custom/conf
作ったディレクトリ上にapp.ini
というファイル名で以下の内容のファイルを作成
[server]
PROTOCOL = http
ROOT_URL = https://gitea.example.com/
HTTP_PORT = 3001
項目はそれぞれ
PROTOCOL: giteaへのアクセスに使用するプロトコル。nginx経由のため、httpに
ROOT_URL: giteaのルートURLで外向けのURL。
HTTP_PORT: giteaの監視ポート。nginx経由のため、空いている3001に
実行してWEBから設定を行う
nginxの設定についてはこちらでは割愛
以下のコマンドでgiteaを起動、変数で作業ディレクトリを指定し、前項で作成した設定ファイルを参照させ、関連ファイル等も作業ディレクトリ下に作成させる。
$ GITEA_WORK_DIR=/opt/gitea ./gitea
2025/03/01 00:00:00 cmd/web.go:253:runWeb() [I] Starting Gitea on PID: 1632054
・・・
2025/03/01 00:00:00 ...s/graceful/server.go:50:NewServer() [I] Starting new Web server: tcp:0.0.0.0:3001 on PID: 1632054
ブラウザから前項で指定したROOT_URLにアクセス。以下のようなページが表示されるため、自分の環境に合わせて記入。ほぼ初期値で問題ないと思われる。
systemdに登録
毎度コマンドで起動するわけにもいかないため、systemdに登録し、自動で起動するようにする。
まず、以下のファイルを作成。
前項のシェル上から起動したものはctrl-c
などして終了しておき、giteaの実行ユーザーではなく、普段利用しているユーザーで操作する。
[Unit]
Description=Gitea (Git with a cup of tea)
After=network.target
[Service]
RestartSec=2s
Type=simple
User=gitea
Group=gitea
WorkingDirectory=/opt/gitea
ExecStart=/opt/gitea/gitea
Restart=always
Environment=USER=gitea HOME=/opt/gitea GITEA_WORK_DIR=/opt/gitea
[Install]
WantedBy=multi-user.target
以下のコマンドで有効化し、起動
$ sudo systemctl enable gitea --now
act_runnerのインストール
GitHub Action互換のCI/CDを有効化するため、ワークフローを処理するデーモンプログラムact_runner
をインストールする。
関連パッケージのインストール
以下のコマンドで関連パッケージをインストール。
act_runnerはホスト上、コンテナ上で実行可能なため、dockerを、ワークフローの処理でnodeを使用するためnodejsをインストールしておく
$ sudo apt update
$ sudo apt install -y docker docker.io apparmor nodejs
以下のコマンドでコンテナ上のact_runnerを使用できるようにdockerグループにact_runnerの実行に使用するgiteaユーザーを所属させ、dockerも起動しておく。
$ sudo usermod -aG docker gitea
$ sudo systemctl start docker
act_runnerのダウンロード
以下のコマンドでact_runnerをダウンロードし、実行権限付与とバージョンを省いたリンクを作成。
これはgiteaの実行ユーザーでホームディレクトリ上で行う。
$ curl -O https://dl.gitea.com/act_runner/0.2.11/act_runner-0.2.11-linux-amd64
$ chmod u+x act_runner-0.2.11-linux-amd64
$ ln -s act_runner-0.2.11-linux-amd64 act_runner
ランナーをgiteaに登録するため登録トークンをメモ
ブラウザからgiteaインスタンスへ管理アカウントでログインし、右上に表示されるアバター画像をクリック、表示されるメニューからサイト管理
を選択。
表示されるページ左のメニューからActions
を選択してサブメニューを展開、サブメニューのランナー
を選択。
以下のイメージのようなページが表示されるため、ページ右上の新しいランナーを作成
ボタンをクリックするとRegistration Token
と書かれている枠にトークンが表示されるため、これをメモしておく。
また、以下のコマンドを実行することでもトークンを得られる。
$ ./gitea --config /opt/gitea/custom/conf/app.ini actions generate-runner-token
0XX0XXx0XXX0XXx000X0x0xX00xxXxXXxxXX0Xx0
ランナーをgiteaへ登録
以下のコマンドでランナーをgiteaへ登録、途中、登録先giteaインスタンスのURL、登録トークン、ランナー名、ワークフローからこのランナーを指定する際に使用するラベルの入力が求められ、設定が.runner
ファイルに保存されます。
$ ./act_runner register
INFO Registering runner, arch=amd64, os=linux, version=v0.2.11.
WARN Runner in user-mode.
INFO Enter the Gitea instance URL (for example, https://gitea.com/):
http://localhost:3001/ # giteaインスタンスのURL。リバースプロキシ内でlistenしてるURLを入力
INFO Enter the runner token:
0XX0XXx0XXX0XXx000X0x0xX00xxXxXXxxXX0Xx0
# 前の項で確認した登録トークンを入力
INFO Enter the runner name (if set empty, use hostname: example.com):
gitea-instance-runner # ランナー名。任意の文字列
INFO Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-latest:docker://gitea/runner-images:ubuntu-latest):
gitea-instance-runner-label # ワークフローで指定するラベル。任意の文字列
INFO Registering runner, name=gitea-instance-runner, instance=http://localhost:3001/, labels=[gitea-instance-runner-label].
DEBU Successfully pinged the Gitea instance server
INFO Runner registered successfully.
systemdに登録
act_runnerもsystemdに登録しておきます。
以下の内容のファイルを作成します。
[Unit]
Description=Gitea Actions runner
Documentation=https://gitea.com/gitea/act_runner
After=docker.service
[Service]
ExecStart=/opt/gitea/act_runner daemon
ExecReload=/bin/kill -s HUP $MAINPID
WorkingDirectory=/opt/gitea
TimeoutSec=0
RestartSec=10
Restart=always
User=gitea
[Install]
WantedBy=multi-user.target
以下のコマンドで設定を反映、有効化、実行
$ sudo systemctl daemon-reload
$ sudo systemctl enable act_runner --now
リモートかつ、カスタムのコンテナ上で動くact_runnerも作成
安めのプランのVPSを使っているので、負荷分散したい、もうすこし自由の効くランナーも使ってみたいといったこともあると思うので、giteaインスタンスのあるサーバーとは別のサーバーで動くカスタムコンテナで動くランナーも用意してみたいと思う。
ベースとなるイメージはDebianのtrixie。
この項のコマンド操作についてはカスタムコンテナ実行可能なサーバー上のユーザーで行う。
作業ディレクトリは任意の場所で。
act_runnerの起動スクリプトを用意
コンテナで動くact_runnerは公式でも用意されていて、同じように使えるようにするため、公式のイメージと同じ起動スクリプトを用意する。
以下がそのスクリプト
#!/usr/bin/env bash
if [[ ! -d /data ]]; then
mkdir -p /data
fi
cd /data
RUNNER_STATE_FILE=${RUNNER_STATE_FILE:-'.runner'}
CONFIG_ARG=""
if [[ ! -z "${CONFIG_FILE}" ]]; then
CONFIG_ARG="--config ${CONFIG_FILE}"
fi
EXTRA_ARGS=""
if [[ ! -z "${GITEA_RUNNER_LABELS}" ]]; then
EXTRA_ARGS="${EXTRA_ARGS} --labels ${GITEA_RUNNER_LABELS}"
fi
# In case no token is set, it's possible to read the token from a file, i.e. a Docker Secret
if [[ -z "${GITEA_RUNNER_REGISTRATION_TOKEN}" ]] && [[ -f "${GITEA_RUNNER_REGISTRATION_TOKEN_FILE}" ]]; then
GITEA_RUNNER_REGISTRATION_TOKEN=$(cat "${GITEA_RUNNER_REGISTRATION_TOKEN_FILE}")
fi
# Use the same ENV variable names as https://github.com/vegardit/docker-gitea-act-runner
test -f "$RUNNER_STATE_FILE" || echo "$RUNNER_STATE_FILE is missing or not a regular file"
if [[ ! -s "$RUNNER_STATE_FILE" ]]; then
try=$((try + 1))
success=0
# The point of this loop is to make it simple, when running both act_runner and gitea in docker,
# for the act_runner to wait a moment for gitea to become available before erroring out. Within
# the context of a single docker-compose, something similar could be done via healthchecks, but
# this is more flexible.
while [[ $success -eq 0 ]] && [[ $try -lt ${GITEA_MAX_REG_ATTEMPTS:-10} ]]; do
act_runner register \
--instance "${GITEA_INSTANCE_URL}" \
--token "${GITEA_RUNNER_REGISTRATION_TOKEN}" \
--name "${GITEA_RUNNER_NAME:-`hostname`}" \
${CONFIG_ARG} ${EXTRA_ARGS} --no-interactive 2>&1 | tee /tmp/reg.log
cat /tmp/reg.log | grep 'Runner registered successfully' > /dev/null
if [[ $? -eq 0 ]]; then
echo "SUCCESS"
success=1
else
echo "Waiting to retry ..."
sleep 5
fi
done
fi
# Prevent reading the token from the act_runner process
unset GITEA_RUNNER_REGISTRATION_TOKEN
unset GITEA_RUNNER_REGISTRATION_TOKEN_FILE
echo ${CONFIG_ARG} > /data/args
exec act_runner daemon ${CONFIG_ARG} 2>&1 > /data/log
Dockerfileを作成してイメージをビルド
以下のDockerfileを作成、中でact_runnerをダウンロードしているが、ファイル外でダウンロードしてCOPYしても問題ない。
FROM debian:trixie
RUN apt update
RUN apt install -y nodejs git curl tini
RUN curl -OL https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64
RUN mv act_runner-0.2.11-linux-amd64 /usr/local/bin/act_runner
RUN chmod +x /usr/local/bin/act_runner
RUN mkdir /opt/act
COPY run.sh /opt/act/run.sh
RUN chmod +x /opt/act/run.sh
ENTRYPOINT ["/usr/bin/tini", "--", "/opt/act/run.sh"]
以下のコマンドでビルド
$ docker image build -f Dockerfile -t "act_runner:debian-trixie" ./
設定ファイルを生成し、修正
giteaインスタンスを動かしているサーバーではSSLにLet's Encryptを使っているためか、リモートからact_runnerを登録しようとすると弾かれてしまう。おそらくルート証明書の問題。イメージビルド中に内部でルート証明書の更新をすることで対応できるかもしれないが、詳しいことがわからず。
設定で証明書のチェックをスルーすることができるので今回はその方法で。
まずは以下のコマンドで基本的な設定をconfig.yaml
ファイルに書き出し。
$ docker run --entrypoint '' act_runner:debian-trixie /usr/local/bin/act_runner generate-config > config.yaml
設定ファイル中の
runner:insecure
をtrue
に
runner:labels
内を空に、もしくはコメントアウト
...
runner:
...
insecure: true
...
labels:
# - "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest"
# - "ubuntu-22.04:docker://gitea/runner-images:ubuntu-22.04"
# - "ubuntu-20.04:docker://gitea/runner-images:ubuntu-20.04"
コンテナを実行
以下のコマンドでコンテナを実行、giteaインスタンスへ登録。
giteaインスタンスのURLやトークン等は環境に合わせて値を設定。
docker run \
-v $PWD/config.yaml:/config.yaml \
-v $PWD/data:/data \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CONFIG_FILE=/config.yaml \
-e GITEA_INSTANCE_URL=https://gitea.example.com \
-e GITEA_RUNNER_REGISTRATION_TOKEN=0XX0XXx0XXX0XXx000X0x0xX00xxXxXXxxXX0Xx0 \
-e GITEA_RUNNER_NAME=debian-trixie \
-e GITEA_RUNNER_LABELS=debian-trixie \
--name debian-trixie \
-d act_runner:debian-trixie
ランナーが登録できているか確認
ブラウザからgiteaインスタンスへ管理アカウントでログインし、右上に表示されるアバター画像をクリック、表示されるメニューからサイト管理
を選択。
表示されるページ左のメニューからActions
を選択してサブメニューを展開、サブメニューのランナー
を選択。
以下のイメージのようなページが表示されるため、ランナーがリストされているか確認。
ワークフローを作成しテストを実行してもらう
準備が整ったので実際にワークフローを作成し、ランナーでテストを実行してもらう。
まずはgiteaでリポジトリを作成し、cloneしておく。
テストを実行する準備
簡単にテストできそうということでひとまずローカルにgoの環境を用意し、cloneしてきたプロジェクトディレクトリ上で以下のコマンドを実行
go mod init local
以下のテスト対象ファイルを作成
package main
func Message() string {
return "Hello world."
}
func main() {
println(Message())
}
以下のテストファイルを作成
package main
import (
"testing"
)
func TestMessage(t *testing.T) {
got := Message()
want := "Hello world."
if got != want {
t.Errorf("Message() == %s, want %s", got, want)
}
}
以下のワークフローファイルを作成。
GitHubのドキュメントにあるものに少し手を加えたもの。
runs-on
の行で実行させたいランナーのラベルを指定、ここではリモートのdebianコンテナのものを指定。
debian-trixieランナーではgoを実行する環境が無いのでapt
でgolang
パッケージもインストール。
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: debian-trixie
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- run: git config --global http.sslVerify false
- run: apt install -y golang
- name: Check out repository code git
uses: actions/checkout@v4
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- name: Run test
run: |
go test -v -cover ./...
- run: echo "🍏 This job's status is ${{ job.status }}."
ワークフローの実行を確認
ワークフローの実行はリモートリポジトリにpush
するだけ。
push後、giteaの対象リポジトリ内のaction
タブに実行されたワークフローがリストされるので、リストタイトル(コミットメッセージの1行目)をクリックし、詳細を見る。
Run test
を開くと以下のようにテスト結果が確認できる。
この記事ではひとまずここで完了
あとは実際運用しながら調整していく。
Discussion