ペパボテックフライデーでWordPressプラグイン開発について動画発表した

毎月第2金曜はペパボテックフライデー。今回は最近取り組んでいるカラーミーショップWPプラグインについて、開発環境周りの話をした。動画はこちら。

カラーミーショップWordPressプラグイン開発における最近の改善 - ペパボテックフライデー2020-05-08 - YouTube

ここ数日お仕事が立て込んでいたので、ゆっくり発表する余裕がないかもしれないと思い、事前に動画を撮っておいた。なんとか顔を出すくらいはできそうだったのでmeetを繋いだのだけど、「自分のPCから自分のYouTube動画を画面共有する」という今まで体験したこと無い発表体験ができたのでよかった。

撮影の環境などについては、こなれて来たらまとめようと思う。

GitHub ActionsでRailsアプリをロリポップマネージドクラウドにデプロイする

ロリポップ!マネージドクラウド(以下マネクラ)へのRails(Ruby)アプリケーションのデプロイは、Herokuと同じようにgit pushをすることでbundle installやDBのマイグレーションなどが自動で行われるようになっている。このウェブ日記もRailsで作っていて、そのデプロイをGitHub Actionsで自動化したのでそのやり方や試行錯誤の過程を記録しておく。

2020-05-02時点で利用している完全なYAML

「結論ははじめに」ということで、以下ようなYAMLと2つのsecrets(SSH_PRIVATE_KEYとLOLIPOP_REPOSITORY_URL)を用意すれば、masterへのpushをトリガーにしてマネクラにRailsアプリケーションがデプロイされる。

name: deploy

on: 
  push:
    branches:
      - master

jobs:
  deploy_to_lolipop_mc:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
      with:
        fetch-depth: 0

    - uses: webfactory/ssh-agent@v0.2.0
      with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
    
    - name: add known_hosts
      run: cat .github/workflows/known_hosts >> ~/.ssh/known_hosts
    
    - name: git remote add
      run: git remote add lolipop ${{ secrets.LOLIPOP_REPOSITORY_URL}}

    - name: git remote update
      run: git remote update

    - name: deploy
      run: git push lolipop HEAD:master

各stepを簡単に解説する。

  • checkout@v2にfetch-depth: 0を設定する。デフォルトでは1となっていてgitの履歴をとってこない設定になっているため、マネクラ側にpushする際にnon-fast-forwardと判定されてしまう。デフォルトのままにしてgit push -fとする手もあると思う。
  • webfactory/ssh-agentを使ってsshの秘密鍵を使えるようにする。(後述)
  • webfactory/ssh-agentはknown_hostsの管理はやってくれないので、リポジトリ上にknown_hostsをコミットしておいてそれを書き込む。(後述)
  • マネクラのgitリポジトリをremoteに追加する。
  • git pushのためには一度fetchしてくる必要があるのでremote updateする。
  • マネクラのgitリポジトリにpushする。

今回は、テストの実行などはステップに含めていない。デプロイだけであればこれくらいのステップ簡単にできる。

webfactory/ssh-agent でsshの秘密鍵をメモリ上で管理する

SSHの鍵認証しか許していないサーバにGitHub Actionsの中からアクセスするためには、GitHub Actionsが動作している環境に秘密鍵を置く必要がある。 GitHub Marketplace · Actions to improve your workflowをsshで検索するといくつかsshができるようにするActionsがあることがわかるが今回はwebfactory/ssh-agentを利用した。

sshとその秘密鍵を利用可能にするActionsは大別すると以下の2種類がある。

  • ssh-agentを実行する(webfactory/ssh-agent)
  • ~/.ssh に秘密鍵を書き込む

GitHub Actionsの実行モデルはよく理解できていないが、実行環境のローカルファイルシステム上に秘密鍵を書き込むよりはメモリ内に留められる方法のほうがよかろうと思い、このActionsを使うことにした。なお、公式のactions/checkoutでも秘密鍵を扱う仕組みはあって、ファイル名をランダムにして書き込むということをしている。

https://github.com/actions/checkout/blob/94c2de77cccf605d74201a8aec6dd8fc0717ad66/src/git-auth-helper.ts#L186-L197

Secretsに登録する秘密鍵とURLを準備する

デプロイに使う秘密鍵は、GitHub Actions専用のものを用意したほうが安全だろう。マネクラではキーペアを簡単に作成・登録できる仕組みがあるので、この機能を使ってデプロイ用のキーペアを作っておく。Ed25519の鍵ができるので強度も安心。

マネクラのコンパネでSSHのキーペアを作成する

ここで作成してダウンロードされた秘密鍵の中身をそのまま、GitHub側に SSH_PRIVATE_KEYというsecretsに登録すればOK。

GitHub側でのsecretsの登録

また、LOLIPOP_REPOSITORY_URLという名前で、マネクラのコンパネに書かれているリポジトリ「ssh://xxxxxx@yyyy.lolipop.jp:port/」を追加しておく。

マネクラでの接続先情報

Actionsの実行に必要な秘匿情報の追加はこれでおわり。

known_hostsをリポジトリに入れる

sshで初めて接続しようとしたときにプロンプトが出てくるアレのこと。何らかの方法でマネクラサーバのホストキーをknown_hostsにいれないとgit pushができないのだ。webfactory/ssh-agentのREADMEでは、actionsの中でssh-keyscanを使って書き込むか、この内容は秘匿情報ではないのでリポジトリにコミットするとよいと書かれている。このファイルの目的は、READMEにもあるとおり接続先のサーバが正しいものか、MITM攻撃にあっていないか、を検証するためのものなので、Actionsの中で毎回取得するよりは同じものを使ったほうが良いだろうと思い、コミットすることにした。

マネクラのコンパネからリモートリポジトリの情報を元に、以下のコマンドで実行することでホストキーを取得することができる。しかし、マネクラ側のSSHコンテナが起動していないと鍵がうまく取れないことがあるので、事前に別のターミナルなどでSSHをつないでおいたほうがいい。

ssh-keyscan -p <your port> -H <your ssh host>

上のコマンドを実行したときに、stderrに以下のような文字列が出てきたら、一度SSHしてから試してみるとうまくいく。

xxxx.mc.lolipop.jp: Connection closed by remote host

この問題のせいで、Actionsの中でssh-keyscanするのはひと手間掛かりそう。

おわりに

GitHub Actionsを使ったマネクラへのデプロイは、sshの秘密鍵をどう管理したらいいかわからずに二の足を踏んでいたのだけど、改めて学習し直して自分なりに安全な方法を考えてみた。マネクラでもこれで継続的なデプロイをGitHubだけで完結させることができるので、かなり便利ではないかと思う。

この方法でも危険な部分などあったら、是非コメントやツイッターなどで教えてください。

おまけ

テックブログでのロリポ関連の記事を読んだことで、この記事を書くモチベーションがあがりました。@antipopと@linyowsに感謝!

snapがうまく動かないのはmake 4.3とAppArmorの組み合わせのせいだった話

久しぶりにsnapで入れたmicrok8sを動かそうとしたら全然動かなくて、調べていくとAppArmorが動かなくなっていることに気付いた。

AppArmorの起動ログには、以下のようにcapabilityがおかしいというエラーがたくさんでていたのだけど、さすがに sys_admin がないというのはおかしい。

AppArmor parser error for /etc/apparmor.d/sbin.klogd in /etc/apparmor.d/sbin.klogd at line 17: Invalid capability sys_admin.

インターネットの海をさまようと、AppArmorのissue Make.rules fails to generate cap_names.h and af_names.h (#74) · Issues · AppArmor / apparmor · GitLab と、Gentoo側のissue 714158 – sys-apps/apparmor-2.13.4 -> ? fails at runtime if built with sys-devel/make-4.3をみつけて、なるほどとなった。

Gentoo側のissueの通り、make 4.3をmaskして4.2に落として、再度コンパイルしたら動くようになったのでよかったですね。

laymanからeselect-repositoryに移行した

数日前のGURUの記事に対してursmがmentionをくれたので早速移行した。

移行といっても、実際はemerge eselect-repositoryをするだけでよいので楽ちん。layman -leselect repository list -iを見比べて、有効になっているoverlayが同じだったらOK。

[11:20:33] in ~ via 💎 v2.7.1
❯ layman -l

 * dotnet                    [Git       ] (https://github.com/gentoo/dotnet.git                                              )
 * go-overlay                [Git       ] (https://github.com/Dr-Terrible/go-overlay.git                                     )
 * guru                      [Git       ] (https://anongit.gentoo.org/git/repo/proj/guru.git                                 )
 * jorgicio                  [Git       ] (https://github.com/jorgicio/jorgicio-gentoo.git                                   )
 * snapd                     [Git       ] (https://github.com/zigford/snapd.git                                              )


[11:23:36] in ~ via 💎 v2.7.1
❯ sudo eselect repository list -i
Available repositories:
  [99]  dotnet # (https://github.com/gentoo/dotnet)
  [148] gentoo * (https://gentoo.org/)
  [163] go-overlay # (https://github.com/Dr-Terrible/go-overlay)
  [168] guru # (https://wiki.gentoo.org/wiki/Project:GURU)
  [197] jorgicio # (https://github.com/jorgicio/jorgicio-gentoo)
  [276] pepabo @
  [349] snapd # (https://github.com/zigford/snapd)

eselect-repositoryの方は、privateなリポジトリもでて便利。よかったよかった。

see also: eselect/repository - Gentoo Wiki

procsのebuildをGURUにコミットした

Rustで書かれたモダンpsことdalance/procsのebuildファイルをGURUにコミットした。

Rustのツールをebuildにするのはcardoe/cargo-ebuildというコマンドを使うと一撃でできるのだけど、出来上がったebuildファイルにコメントがあるとおり、このツールではライセンスのリストがうまく出せないことがある。

cargo-ebuildが出力するebuildファイルのLICENSEの部分は、リンクする全てのライブラリのライセンスを集めてきて出してくれるのだけど、

  • 2つのライセンスが設定されている場合は両方でてくるが、実際にはどちらか一方となっているものも多い
  • portageのLICENSE名と必ずしも一致していない

という問題がある。

最終的にどういうライセンスにすればよいかは、onur/cargo-licenseというものを使えと書いてあって、これがメチャクチャ便利…すごい。これの出力をみながら、最小限のANDをとっていくとよさそう。

portageのライセンス名とのマッチングは License groups - Gentoo Wiki このあたりを見ながらマッチングしていけば良さそう。procsのebuildを作るにあたり困ったのは、BSD-3-Clauseというライセンスで、これはportage的にはBSDというライセンスだったので直したりした。