Self-host runnerで色々したい

Hugoで構築したサイトをセルフホストに載せようと思ったときにやり方が書いてなかったので備忘録を兼ねてメモ。

Hugoのバージョンは下記。Extended版とかDart Sassとかは使ってないので割愛。

$ hugo version
hugo v0.154.5-a6f99cca223a29cad1d4cdaa6a1a90508ac1da71+extended linux/amd64 BuildDate=2026-01-11T20:53:23Z VendorInfo=gohugoio

構築手順はドキュメントのビルド手順も参考にしましたが、一旦最小構成です。 セキュリティ面はプライベートリポジトリなのである程度担保されているでしょう、ということにしておきます。

構築手順

GitHub上での作業

  1. GitHub上でビルドしたいリポジトリを作成する

  2. Settings -> Actions -> Runners を開く

  3. 「New self-hosted runner」をクリック

    • 動作させたいOSアーキテクチャにあわせて選択

    • 今回は Runner Image: Linux 、 Architecture: x64 とした

  4. 「Download」のダウンロードURL・ハッシュ値を控えておく

  5. 「Configure」の --url--token を控えておく

マシン上での作業

事前にHugoおよびDockerが利用できることを前提とします。

  1. 事前準備

    # ユーザの追加
    sudo useradd actions-runner -m
    
    # Dockerグループへ追加
    sudo gpasswd -a actions-runner docker
    
  2. Runnerの構築

    # ディレクトリの作成
    sudo mkdir /opt/actions-runner && cd /opt/actions-runner
    
    # ダウンロード
    sudo curl -o actions-runner-linux-x64-2.331.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.331.0/actions-runner-linux-x64-2.331.0.tar.gz
    
    # ハッシュ値の検証
    sudo echo "5fcc01bd546ba5c3f1291c2803658ebd3cedb3836489eda3be357d41bfcf28a7  actions-runner-linux-x64-2.331.0.tar.gz" | shasum -a 256 -c
    
    # 展開
    sudo tar zxvf ./actions-runner-linux-x64-2.331.0.tar.gz
    
    # パーミッションの変更
    sudo chown actions-runner:actions-runner . -R
    
    # 設定
    sudo -u actions-runner ./config.sh --url https://github.com/<foo/bar> --token <token>
    
    # インストール
    sudo ./svc.sh install actions-runner
    
    # 起動
    sudo ./svc.sh start
    
    # 確認
    sudo ./svc.sh status
    # もしくは、下記でもよい
    sudo systemctl status actions.runner.<リポジトリ名>.<マシン名>.service
    
  3. この状態でGitHubのリポジトリの Actions -> Runners -> Self-hosted runnes にRunnerがいて、「Stutus」が Idle になっていることを確認する

Dockerfileの作成

Dockerイメージを作成するため、 Dockerfile を作成する。

このファイルはリポジトリの直下に配置しました。

FROM nginx:latest
COPY public/ /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

compose.yamlの作成

作成したDockerイメージの運用簡略化のため、 compose.yaml を作成する。
これもリポジトリの直下に配置しました。

ポート周りなどは適宜変更してください

services:
  <リポジトリ名>:
    build: .
    container_name: <リポジトリ名>
  # Nginx Proxy Managerを利用しているので、ポートフォワードはせず内部ネットワークを指定
    networks:
      - nginx-proxy
networks:
  nginx-proxy:
    external: true
    name: nginx-proxy

ワークフローの作成

リポジトリ内の .github/workflows/ 配下に実行したい内容を記したファイルを作成する。 GitHub Actionsのyamlについては色々なところで詳細に解説しているページがあると思うので、詳細は割愛します。

.github/workflows/build-site.yml

name: Build Hugo site and build Docker Image CI

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

jobs:

  build:

  # Self-hosted runnerで実行
    runs-on: self-hosted

    steps:

  # GitHubからサブモジュールを含めてPull
    - name: Checkout code
      uses: actions/checkout@v4
      with:
          submodules: recursive

  # 生成物が格納される /public ディレクトリ、および中間ファイルが格納される /resources/_gen ディレクトリを
  # 永続化されたディレクトリ(Self-hosted runnerの既定のディレクトリ以外)に作成し、
  # シンボリックリンクを張ることにより hugo build コマンド実行時のビルド時間を短縮する
    - name: Create symbolic links for build directory
      run: |
        PERSISTENT_DIR="/var/actions-runner/${{ github.repository }}"
        mkdir -p "$PERSISTENT_DIR/public"
        mkdir -p "$PERSISTENT_DIR/resources"
        ln -s "$PERSISTENT_DIR/public" ./public
        ln -s "$PERSISTENT_DIR/resources" ./resources

  # ビルドの実行
  # 永続化されないディレクトリでの実行であれば --minify のみで問題ない
  # --minify: HTML、CSS、Javascriptの軽量化
  # --cleanDestinationDir: 使用されなくなったファイルの削除
  # --gc: クリーンアップタスクの実行
    - name: Build the Hugo site
      run: hugo --minify --cleanDestinationDir --gc --logLevel=info

  # docker build コマンドを実行時にシンボリックリンクはエラーとなる
  # かつカレントディレクトリより上の階層にはアクセスができないため、
  # 一度シンボリックリンクを削除し、生成物を改めてコピーする
    - name: Delete public directory symbolic link and copy public directory
      run: |
        PERSISTENT_DIR="/var/actions-runner/${{ github.repository }}"
        rm ./public
        mkdir -p ./public
        cp -rL $PERSISTENT_DIR/public/* ./public/

  # Dockerfile からDockerイメージをビルド
  - name: Build the Docker image
      run: docker build . --file Dockerfile

  # Docker Compose イメージをビルドし、既に起動している場合はビルド完了後に再起動
    - name: Build the Docker Compose services
      run: docker compose -f compose.yaml up -d --build

動作確認

Actionsを含むファイルをコミットすると自動的に実行されます。

問題なくビルドできているかを確認します。

compose.yaml でポートフォワードしない設定にしているため、Nginx Proxy Manager側で設定 問題なくサイトが表示されたらOK。

リポジトリの master ブランチが変更になった際にもビルドが走り、変更内容が反映されていることを確認。
たぶん大丈夫そうなので、一旦これで様子見してみます。

Dockerコンテナ内でビルドも試してみたんですが、キャッシュ回りの操作が冗長になる&パフォーマンスが出ないので一旦保留・・・
GitHub Actionsにはキャッシュ機能があるので、このあたり使えば改善するような気がしてます。