Webサイト管理・公開をhugo+GitHub+S3で

Webサイト管理・公開をhugo+GitHub+S3で

やりたいこと

Webページを

  • 静的サイトジェネレータで作成
  • GitHubで管理
  • S3でホスティング

静的サイトジェネレータ:Hugo

リクエストに対してページを動的に生成する動的サイトに対して,サーバに設置したhtmlファイルなどをそのまま返すサイトを静的サイト(static site)という. 静的サイトジェネレータは,静的サイトの生成をテンプレートとMarkdownなどの軽量マークアップ言語からおこなうフレームワークのこと. データベースが必要ない,基本的にテキストデータなのでバージョン管理システムとの相性が良いという点がCMSなどと比べたときのメリット.

以前は,PythonベースのPelicanを使っていたが, 今回はその中でもビルド速度に定評があるHugoを使うことにした.

その他の人気静的サイトジェネレータについてはStaticGenが参考になる.

ホスティング:S3

AWSのS3でホスティングする.

次の状況を想定する.

  • S3 Bucket「www.test.com」でホスティングする
  • CloudFrontを経由して配信する

IAMユーザの作成とポリシー設定

S3へのデプロイ用IAMユーザを作成し,ポリシーを設定する. 例えば,IAMユーザ「s3-deploy-web」を作成し, ポリシー「s3-deploy」を以下のように作成・アタッチする.

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Allow",
        "Action": [
            "s3:GetObject",
            "s3:PutObject",
            "s3:DeleteObject",
            "s3:ListObject",
            "s3:ListBucket"
        ],
        "Resource": [
            "arn:aws:s3:::www.test.com",
            "arn:aws:s3:::www.test.com/*"
        ]
    }
]
}

Bucketの作成とポリシー設定

新規にBucket「www.test.com」を作成する. プロパティ → 静的ウェブサイトホスティング から静的サイトのホスティングを有効にする.

  • インデックスドキュメント:index.html
  • エラードキュメント:404.html

をそれぞれ設定する.

CloudFront

いわゆるCDNサービス.世界中のエッジサーバから配信することで高速な配信が可能になる.

サブディレクトリでindex.htmlへの補完を利用する場合は注意!

以下の設定をおこなう. その他はデフォルト.

  • Origin Settings # サブディレクトリでindex.htmlへの補完を利用しない場合
    • Origin Domain Name: www.test.com.s3.amazonaws.com
    • Restrict Bucket Access: yes
      • Origin Access Identity: Create a New Identity
      • Grant Read Permissions on Bucket:
  • Origin Settings # サブディレクトリでindex.htmlへの補完を利用する場合,この場合はS3への直接アクセスが可能になる.
    • Origin Domain Name: S3の静的サイトホスティングのエンドポイント
  • Default Cache Behavior Settings
    • Viewer Protocol Policy: Redirect HTTP to HTTPS
    • もし投稿フォームがあればPOSTを許可
  • Distribution Settings
    • Price Class: 適切な範囲を指定
    • Alternate Domain Name: www.test.com
    • SSL Certificate: Custom SSL Certificate
      • Request or Import a Certificate with ACMで新規のSSL証明書を発行してもらう
    • Supported HTTP Versions: HTTP/2, HTTP/1.1, HTTP/1.0
    • Default Root Object: index.html

404エラー

サブディレクトリでindex.htmlへの補完を利用しない設定の場合は, 404エラーが期待される場面でAccessDenied(403エラー)が出現する.

詳細は理解していないが,Restrict Bucket Accessの設定が効いているような…?

今回はCloudfrontのError Pagesで対応することにした. 以下の様に設定する.

  • HTTP Error Code: 403
  • Response Page Path: /404.html
  • HTTP Response Code: 404

403エラーを受けて404エラーを返す. 大丈夫?今後の課題.

ビルド:GitHub + CircleCI

今回はGitHubリポジトリへpushしたら,自動でビルドしてS3にホスティングする仕組みを作る.

CircleCIはビルド・テスト・デプロイ特化型の継続的インテグレーション(Continuous Integration)サービス.

  • GitHubのプライベートリポジトリで使いたい
  • 無料

という条件で選んだ.

Git(Hub)の設定

  • GitHub用にWebサイトの編集用リポジトリを作成.今回はprivateにする.
  • .gitignoreはHugo docs.gitignoreファイルを参考にした.
  • とりあえず一度pushしておく.

CircleCIの設定

  • CircleCIにGitHubアカウントでログインする.
  • 対象にしたいレポジトリのBuild Projectボタンを押す

もし,circle.ymlがルートにあれば一度目のBuildが走る.

なければcircle.ymlを追加してpushすると,Buildが実行される. 今回は以下のようなファイルにした.

checkout:
  post:
    - git submodule sync
    - git submodule update --init --recursive

machine:
  timezone:
    Asia/Tokyo

dependencies:
  override:
    - sudo pip install awscli
    - sudo pip install Pygments
  pre:
    - go get -v github.com/spf13/hugo
    - git config --global user.name "noshita"
    - git config --global user.email "noshita@morphometrics.jp"
  post:
    - aws configure set region us-west-2
    - aws configure set preview.cloudfront true

test:
  override:
    - echo "Nothing to do here"

deployment:
  production:
    branch: master
    commands:
      - hugo --cleanDestinationDir 
      - aws s3 sync ~/www.test.com/public/ s3://www.test.com/ --delete
      - aws cloudfront create-invalidation --distribution-id <CloudFront ID> --paths '/*'

DNSの設定:お名前.com

今回はお名前.comで取得したドメインを利用することにする.

DNS関連機能の設定 → DNSレコード設定を利用する,からCNAMEレコードを設定する.

  • ホスト名: www.test.com
  • TYPE: CNAME
  • TTL: 300
  • VALUE: CloudFrontのドメイン名

確認

CDNの配信やDNSの設定の反映を待って,アクセスできるかを確認する. アクセスできれば設定終了.

ちなみに,当サイトの管理は上記の方法でおこなっている.

今後の課題

  • サブディレクトリでindex.htmlへの補完を利用しない設定の場合に,404エラーが期待される場面でAccessDenied(403エラー)が出現する.
    • 何故起こるのかの理解
    • どう対応するのが適切かの把握