Gitlab Pagesの独自ドメイン用Let's Encrypt証明書を自動更新する


2019/08/17 追記

Gitlab 12.1 から、Gitlab の Web UI のみで「カスタムドメイン用Let's Encrypt証明書発行」ができるようになったみたいです。
https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.html

以下の情報は古いものとして扱ってください(multidomain 環境ならまだ役に立つのかも?そこまでは調べてないです。)

環境

  • gitlab.com
    • GitLab Enterprise Edition 11.11.1-ee (2019/06/02 現在)
  • APIでレコード情報を更新できるDNSサービス

前提

さくらのクラウド DNS

  • Gitlab Pages を公開したいドメイン用のゾーンが作成されていること
  • API key/Api secret が発行済であること
    • 必要なアクセスレベルは、「設定編集」以上です

gitlab.com

手順

Gitlab CI の環境変数を設定

  • 設定する内容は「さくらのクラウド API key/API secret」と「Gitlab.comアクセストークン」
  • 今回は名前をそれぞれ SAKURA_SECRETS GITLAB_API_TOKEN としました
  • SAKURA_SECRETS は Type を File にしておくと後々便利です

証明書発行&Gitlab Pagesに証明書をアップロードするためのスクリプトを作成

  • DNS 認証でのSSL証明書発行となるため、ワイルドカード証明書も発行できます
    • ワイルドカード証明書の場合、証明書/秘密鍵の格納先ディレクトリが変わります
      • www.epaew.net を発行すると /etc/letsencrypt/live/www.epaew.net/
      • *.epaew.net を発行すると /etc/letsencrypt/live/epaew.net/
    • 複数ドメインに使える証明書だとどこに格納されるんだろうね
  • certbot renew を使いたいのは使いたいんですが、発行済証明書をどこで保持するか悩んだ結果毎回新規で発行しています。
    キャッシュだといつ消えるかわからないですし、リポジトリにコミットするものでもないと思うので。。
#!/bin/sh -eu
certbot certonly --dns-sakuracloud --dns-sakuracloud-credentials $SAKURA_SECRETS \
  -d <設定したいドメイン> -m <メールアドレス> \
  --manual-public-ip-logging-ok --agree-tos

curl -X PUT -H "Private-Token: $GITLAB_API_TOKEN" \
    -F "key=@/etc/letsencrypt/live/<証明書のドメイン>/privkey.pem" \
    -F "certificate=@/etc/letsencrypt/live/<証明書のドメイン>/fullchain.pem" \
    https://gitlab.com/api/v4/projects/<GitlabプロジェクトのID>/pages/domains/<Gitlab Pagesに設定したドメイン>

.gitlab-ci.yml にジョブを作成

  • ハマったポイント
    • Docker の certbot イメージは、entrypoint に [ "certbot" ] が設定してあります
    • このあと Gitlab の設定画面からスケジュールを設定しますが、現状「ジョブごとのスケジュール」は設定できません。
      • 環境変数で頑張れば分岐できそうだけど今回は対象外
      • 各ジョブに only/except: schedules を設定するようにしてください
 pages:
   image: node:lts
   script:
     - yarn run generate
   artifacts:
     paths:
     - public
   only:
     - master
+  except:
+    - schedules
+
+renew_certs:
+  image:
+    name: certbot/dns-sakuracloud
+    entrypoint: [""]
+  before_script:
+    - apk --no-cache add curl
+  script:
+    - scripts/create-and-set-new-cert.sh
+  only:
+    - schedules

Gitlab CI にスケジュールを設定

  • 2ヶ月に1回発火するように設定しました

動作確認

Gitlab CI の Scheduling Pipelines の画面で「▶」を押せば、スケジュールジョブを手動実行することができます

Gitlab Pagesのページに移動し、証明書が差し替わっていれば無事完了です。
お疲れ様でした。

参考

https://docs.gitlab.com/ee/user/project/pipelines/schedules.html
https://docs.gitlab.com/ee/api/pages_domains.html#update-pages-domain
https://qiita.com/chamaharun/items/c87dbfe865d8126433bf