GitHubで回すWebサイト制作

目次

  1. GitHubで回すWebサイト制作
    1. 検証環境
    2. 検証目標
  2. ミドルウェアのインストール
    1. OS
    2. Apache
    3. InCron
    4. スナップクラフト
    5. Webhook
    6. 後始末
  3. 自作スクリプトの設置
    1. ディレクトリ作成
    2. /root/.webhook/run/activate_id_update-contents
    3. /root/.webhook/bin/fecho
    4. /etc/httpd/libexec/update-contents.sh
    5. 後始末
  4. ミドルウェアの設定
    1. /etc/incron.d/update-contents
    2. /etc/httpd/conf/httpd.conf
    3. /etc/httpd/conf/hooks.yaml
    4. 後始末
    5. デプロイ用SSH鍵の準備
  5. GitHubの設定
    1. まずはSettings
    2. Deploy Keys
    3. Webhooks
  6. コンテンツの展開方法
    1. チェックアウト除外ファイルの追加
  7. よくある質問とその答え
    1. Q.ProxyPass設定したならProxyReverseの設定は必須では?
    2. Q.ウェブフックへのIPアクセス制限を課したいのだが?
    3. Q.trigger-ruleはどの程度書けば良くて?
    4. Q.ライトなWebサイト運用してる割には凝った設定では?
    5. Q.CMS使いたくない割には、GitHub使うって無いのでは?
    6. Q.他のサイトでのやり方見るに、胡乱な手順に見えるけどどうして?
    7. Q.なんでスナップクラフト使ったの?
    8. Q.よくよく見ると/etcはホストのディレクトリが見えてない?
    9. Q.となるとホストから参照できるディレクトリ以下にスクリプト置けば遠回りしなくていいのでは?
  8. 参考文献

検証環境

用途

ソフトウェア名

バージョン番号

備考

OS

CentOS 7

7.7.1908

SELinuxは有効とする

Webサーバー

Apache 2.4

2.4.41

IUSリポジトリ

Webフック

webhook

2.6.10

スナップクラフト

ファイルフック

incron

0.5.12

ワークアラウンドのために泣く泣く使用

検証目標

apache-webhook.svg

ミドルウェアのインストール

OS

基本的な(とは何かは議論しない)セットアップは実施済みであることとする。

ファイアウォール設定

sudo firewall-cmd --add-service=http  --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload

※ここではHTTPは80番ポート、HTTPSは443番ポートを使用するモノとして記述しておく。

firewall-cmd --permanent --service=http  --get-ports
firewall-cmd --permanent --service=https --get-ports

違うポート番号で運用する場合は --get-ports の代わりに --add-port--remove-port を駆使して設定すること。

SELinux設定

特に設定無し。下記コマンドを実行した結果で得られたポート範疇内の設定であれば問題無し。

semanage port -l | grep -w http_port_t

違うポートで運用する場合は下記コマンドを実行する(例では81番ポートを追加してみた)。

sudo semanage port -a -t http_port_t -p tcp 81

Apache

sudo yum -y install https://centos7.iuscommunity.org/ius-release.rpm
sudo yum -y install httpd24u httpd24u-mod_ssl httpd24u-tools

※インストールした直後は自動起動設定を有効にしない、Apacheを立ち上げない。

InCron

sudo yum -y install epel-release
sudo yum -y install incron

sudo systemctl enable incrond
sudo systemctl start  incrond

スナップクラフト

sudo yum -y install snapd
sudo systemctl enable --now snapd.socket
sudo ln -s /var/lib/snapd/snap /snap
sudo systemctl reboot

※スナップクラフトの有効化のために一度再起動しておくこと。

Webhook

sudo snap install webhook

※スナップクラフトが稼働してる状態で上記コマンドを実行すること。

/etc/systemd/system/snap.webhook.webhook.service.d/override.conf

sudo systemctl edit snap.webhook.webhook.service

上記コマンドを実行して以下の設定を行う。

[Service]
EnvironmentFile=-/etc/sysconfig/webhook
ExecStart=
ExecStart=/usr/bin/snap run webhook $OPTIONS

※Webhook起動のための設定オプションの指定ができなかったので、/etc/sysconfig/webhook を参照するように改変してみた。

/etc/sysconfig/webhook

OPTIONS="-hooks /etc/httpd/conf/hooks.yaml -hotreload -ip 127.0.0.1 -port 9000"

※動作確認が取れるまで -verbose オプションを指定しておいた方がいいかもしれない。

後始末

restorecon -RFv /etc/sysconfig /etc/systemd/system

自作スクリプトの設置

ディレクトリ作成

sudo mkdir -p /root/.webhook/bin
sudo mkdir -p /root/.webhook/run
sudo mkdir -p /etc/httpd/libexec

/root/.webhook/run/activate_id_update-contents

以下のコマンドを実行してファイルを作成する。

sudo touch /root/.webhook/run/activate_id_update-contents

/root/.webhook/bin/fecho

#!/bin/sh
: APPEND=no
: OUTFILE=-

while getopts ao: OPT; do
        case $OPT in
        a)  APPEND=yes
                ;;
        o)  OUTFILE=$OPTARG
                ;;
        \?) continue
                ;;
        esac
done
shift $((OPTIND - 1))

if [ x"$OUTFILE" = x"" -o x"$OUTFILE" = x"-" ]; then
        echo $*
else
        if [ x"$APPEND" = x"yes" ]; then
                echo $* >> "$OUTFILE"
        else
                echo $* >  "$OUTFILE"
        fi
fi

/etc/httpd/libexec/update-contents.sh

#!/bin/sh
cd /var/www/html

git pull -q
if [ x"$1" = x"refs/heads/master" ]; then
        git checkout -qf master
fi
restorecon -RF .

後始末

sudo restorecon -RFv /root/.webhook /etc/httpd/libexec
sudo chmod 0755      /root/.webhook/bin/fecho /etc/httpd/libexec/update-contents.sh

ミドルウェアの設定

/etc/incron.d/update-contents

/root/.webhook/run/activate_id_update-contents  IN_CLOSE_WRITE,loopable=false   /etc/httpd/libexec/update-contents.sh $$(cat $@)

/etc/httpd/conf/httpd.conf

ProxyPass /hooks/ http://localhost:9000/hooks/
<Proxy http://localhost:9000/hooks/*>
    Require all granted
</Proxy>
<Files ".git*">
    Require all denied
</Files>
<Directory "/var/www/*/.git">
    Require all denied
</Directory>

/etc/httpd/conf/hooks.yaml

- id: update-contents
  command-working-directory: "/root"
  execute-command: "/root/.webhook/bin/fecho"
  pass-arguments-to-command:
    - source: string
      name: "-o"
    - source: string
      name: "/root/.webhook/run/activate_id_update-contents"
    - source: payload
      name: ref
  response-message: |
    Updated, Done.
  trigger-rule-mismatch-http-response-code: 400
  trigger-rule:
    and:
      - match:
          type: payload-hash-sha1
          secret: "GitHubに設定するシークレット"
          parameter:
            source: header
            name: "X-Hub-Signature"
      - or:
          - match:
              type: value
              value: ping
              parameter:
                source: header
                name: "X-GitHub-Event"
          - match:
              type: value
              value: push
              parameter:
                source: header
                name: "X-GitHub-Event"

後始末

sudo restorecon -RFv /etc/incron.d /etc/httpd/conf

デプロイ用SSH鍵の準備

sudo ssh-keygen -t ssh-ed25519 -C root@$(hostname) -N "" -f /root/.ssh/id_ed25519
sudo restorecon -RFv /root/.ssh

以下の点に注意すること。

GitHubの設定

まずはSettings

リポジトリのトップを見ると、下記のようなメニュー(タブ)が表示されているはず。

settings.png

この時、赤丸で強調した「Settings」タブが表示されない場合は、設定すべき権限が無いので、権限をもらおう。 もちろん他人のリポジトリの権限くれ、と言っても極めて困難と思われるので、その辺りの調整についてはここでは説明しない。

ここでは「Settings」タブが表示されている前提で説明を行う。

Deploy Keys

deploy-keys.png

Webhooks

webhooks.png

設定項目

設定内容(例)

ペイロードURL

https://www.example.jp/hooks/update-contents を入力する

Content-Type

application/json を選ぶ

シークレット

「GitHubに設定するシークレット」を入力する

SSL verification

Enable SSL verification を選ぶ

Which events would you like to trigger this webhook?

Just the push event. にチェックを入れる

Active

チェックを入れる

上記入力して保存します。

コンテンツの展開方法

GitHubの設定まで完了したらコンテンツを展開します。

env - git clone --no-checkout git@github.com:example-jp/www.example.jp.git /var/www/html
cd /var/www/html
git config core.sparseCheckout true
echo "/*\n\!README.md" > .git/info/sparse-checkout
git checkout
restorecon -RFv /var/www/html

チェックアウト除外ファイルの追加

git read-tree -m -u HEAD

よくある質問とその答え

Q.ProxyPass設定したならProxyReverseの設定は必須では?

A.よくセットで設定されるので必須扱いなのはわかります。が、webhookには高度な応答(リダイレクトやらクッキーやら)機能が無いので必要ないです。

Q.ウェブフックへのIPアクセス制限を課したいのだが?

A.https://api.github.com/meta の応答(JSON)見ると接続元IPアドレスがリストアップしてますねー(棒)。

詳細はREST API v3 - Meta を参考に設定してみてください。時々変更してるようなので頑張ってメンテナンスしてください。

Q.trigger-ruleはどの程度書けば良くて?

A.例えば、マスターブランチへプッシュ以外は無視という設定は可能です。その場合、マスター以外のブランチへのプッシュはエラー応答するため、GitHub的にはどうかと(障害と区別がつかない)。 GitHubのWebhooks設定では、「PUSHイベントのみ」、「全てのイベント」、「個別に指定したイベント」と設定できるので、それを受けられるだけの設定を行うようにしましょう。

Q.ライトなWebサイト運用してる割には凝った設定では?

A.二度と編集しないようなページを作ってるなら必要ない作業ですね。年に一回くらいしか更新しならペイしないかも。

やれ誤字だ脱字だ、一行追加したい、すぐにやれとかワガママに対応したいならここまでこだわらなくていいでしょう。自分にはとてもても。

Q.CMS使いたくない割には、GitHub使うって無いのでは?

A.Webコンソールでの作業は抵抗無いのですが、HTMLを直接書きたい向けですね。

要はWikiのような軽量マークアップ言語は使いたくない(制御できない、表現力が低い)、覚えたくない(アレするのにコレ、が思い出せない)人向けというのが。 システムサイドとしては、オマケでイシュー管理(めんどくさい修正の丸投げ)やバージョン管理(勝手に変更の追跡)してくれるお手軽さが重要。 知名度も高いので提案しやすいというのもメリット。

Q.他のサイトでのやり方見るに、胡乱な手順に見えるけどどうして?

A.おっしゃる通り、あまりに胡乱なので今回、フロー図作りました。あまり合理的で無いことは認めます。

ひとえにスナップクラフトによるコンテナ効果(?)が大きく、webhookが動く環境の外に対してアクション起こせないことが原因です。 唯一ホームディレクトリ(rootで動いてるので /root ディレクトリ)のみ、下界(コンテナの外)につながってるので、 そこを通してアクション起こしています。

またアクションを即応させるために、incronを使用して最小限の遅延でコンテンツの同期を行えるようにしています。 普通にcron回してると「更新まだ~?」というF5攻撃が…。

Q.なんでスナップクラフト使ったの?

A.その辺のメジャーなYUMリポジトリで取り扱ってなかったから。またwehookの開発者公認のリポジトリがスナップクラフトだったので使用。 ソースからコンパイル?もっと楽に生きようぜ。

Q.よくよく見ると/etcはホストのディレクトリが見えてない?

A.見えてますね。設定ファイル(/etc/httpd/conf/hooks.yaml)はコンテナ内でなく、コンテナ外のファイル参照してます。 参照可能なコンテナ外ディレクトリは /etc/usr/share//var/lib のようです。

Q.となるとホストから参照できるディレクトリ以下にスクリプト置けば遠回りしなくていいのでは?

A.良い点に気がつきました。だが断る。じゃなくて、コンテナ内にgitコマンドが無いので、そこの部分でどうしようもないです。 あと展開したいディレクトリ(通常 /var/www ディレクトリ以下)をどうするか…。 もちろんループバックで逃げる手も無くも無いですが、そこまで頑張るならこのやり方の方が…。

参考文献

apache+webhook/GitHubで回すWebサイト制作 (最終更新日時 2019-11-13 01:46:10 更新者 NorikatsuShigemura)