Golang Hugoで高速なブログを作る -- Travis CI, S3, CloudFront Route53

この記事では、3つのトピックを組み合わせて、AWSを利用したブログの作り方を説明しています。

* hugoでブログを作る
* Travis CIで自動ビルド、サイトをS3にアップロードしてCloudFrontを介して公開する
* Route53とCredential Managerを使って独自ドメインかつHTTPSで公開する



コストはアクセス量によりますが、最小で月額100円程度です。
結果として、こんな感じのサイトが出来上がります。→  https://juntaki.com/
ソースコードは[こちら](https://github.com/juntaki/juntaki.com)。

## Hugoとは

[Hugo](https://gohugo.io/)はMarkdown形式のコンテンツからStaticなWebサイトを生成するツールです。生成されるサイトをまるごとCDNにおいてしまえば、クライアントからは高速[^1]にロードされます。

[^1]: Wordpressのように動的に生成する場合や、レイテンシが大きい遠くのサーバに置く場合と比較して。単なるブログにはオーバースペック感がありますがAWSをいろいろ使ってみるのにはとっつきやすい題材です。

## Hugoの使い方

まずはHugoのインストール、初期構成の生成を行います。

~~~
go get -v github.com/spf13/hugo
hugo new site ~/new_site
~~~

ディレクトリ内は次のようになります。

~~~
archetypes
config.toml
content
data
layouts
static
themes
~~~


テーマは[ここ](https://themes.gohugo.io/)にあるものから選んでみます。`themes`ディレクトリ以下にサブモジュールとしてcloneすると、テーマの更新が簡単になります。

新しいコンテンツを作って、試しにビルドしてみます。

~~~
hugo new blog/test.md
emacs contents/blog/test.md
hugo server --watch
~~~

ブラウザから`http://localhost:1313/` にアクセスすると、ライブリロードでビルド結果が見えます。あとは、気に入るまでconfig.tomlやstaticディレクトリをカスタマイズします。肝心のコンテンツも追加します。

## Travis CIでビルドしてS3にアップロード

S3にバケットを作成し、Webページが公開できる設定にします。インデックスドキュメントに`index.html`を指定しておきます。

![image](https://qiita-image-store.s3.amazonaws.com/0/69350/865abdc5-eb36-459f-733f-a57dc3de60ee.png)

バケットポリシーを設定しておけば、アップロードするだけでWebページとして公開されます。[バケットポリシーの例 →匿名ユーザーへの読み取り専用アクセス許可の付与](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/example-bucket-policies.html)

CloudFrontでは直接S3のバケットをOriginとして設定できますが、Default Root Object以外のインデックスドキュメントの指定ができません。なので、上記の設定でS3のエンドポイントURLをOriginにするのがおすすめです。[^2]

[^2]: hugoのビルド時に`--ugryURL`を使えば、S3のバケットをOriginにしても問題ないです。ただ、URLが長くなるし、uglyと言われたら使いにくいですよね。

Travis CIの設定は以下のようにします。AWSのCredentialを`AWS_ACCESS_KEY_ID`と`AWS_SECRET_ACCESS_KEY`の環境変数として与えると、awsコマンドが使ってくれます。

~~~
language: go
sudo: false
dist: trusty
before_install:
  - pip install --user awscli
  - export PATH=$PATH:$HOME/.local/bin
install:
  - go get -v github.com/spf13/hugo
script:
  - hugo
  - aws s3 sync public/ s3://juntaki.com --delete
notifications:
  email:
    on_failure: always
~~~

この段階でS3のエンドポイントURLからはサイトが見えるようになっているはずです。

## Certificate ManagerでSSLの証明書を取得する

Certificate ManagerはAWS版Let's encryptです。無料です。
証明書取得の前に独自ドメインに対してRoute53のDNSサーバーを設定しておきます。次にCertificate ManagerでSSL証明書を作るときの認証のため、`admin@ドメイン名`でメールを受け取れるようにしておきます。[^3]

[^3]: [Zoho Mail](https://www.zoho.jp/)がWebからも使えてお手軽です。AWSでもAmazon SESなんてサービスもあるのか・・。

Certificate ManagerでSSL証明書を取得します。
![image](https://qiita-image-store.s3.amazonaws.com/0/69350/bed6b9c4-4ebc-094b-dbb4-28948c5741aa.png)

## CloudFrontの設定

CloudFrontの設定で特に必要なのは以下の4つです。Distribution StatusがDeployedとなるまで30分くらい根気強く待ちます。失敗するとデプロイ待ちが長いので、慎重にやりましょう。

|項目|設定内容|
|---|---|
|Alternate Domain Names |独自ドメイン|
|SSL Certificate |CustomSSL|
|Custom SSL Client Support|SNI|
|Origin Domain Name |S3のエンドポイントURL|

### キャッシュのInvalidate

すぐに変更をCloudfrontまで反映したい場合に、CDN上のキャッシュを捨てるには下記のコマンドを実行します。

~~~
aws cloudfront create-invalidation --distribution-id <distribution-id>--paths '/*'
~~~

## 独自ドメインの設定

CloudFrontのGeneralタブから確認できるDomain Nameに対して、AレコードのAliasを設定します。

## まとめ

Webサービスを作るインフラとして、AWSはなんでも揃っていて強力です。
作成したサイトと、ソースコードはこちらです。参考にしてください。
Blog: https://juntaki.com/
Github:  https://github.com/juntaki/juntaki.com