Hugo+S3+CloudFrontで個人ブログを作る

目次

本稿では、Hugoで静的ブログサイトを作り、CloudFrontで配信する方法を紹介しています。
前半は、ブログコンテンツを作成するために使用しているHugoについて紹介しています。
後半は、Hugoで作成したブログコンテンツをS3にアップロードし、CloudFrontで配信する手順を紹介します。

全体像

architecture.png
上の図のようなアーキテクチャになります。
記事を執筆する際は、ローカルPCのHugoディレクトリで作業します。
Markdownで記事を執筆できます。
HugoにはローカルWebサーバ機能があるので、検証サイトを確認しながら記事を執筆できます。
記事が書けたら、コンパイルしてブログコンテンツを生成します。
生成されたブログコンテンツをS3にアップロードし、CloudFrontで配信します。

Hugoの設定方法

Hugoとは

hugo-website.png 公式ページ
Hugoは静的サイトジェネレータです。
Markdownで記事を書き、Hugoを実行すると、記事のページやTopページ、プロフィールページなどブログに必要なファイルを生成します。
これらのファイルをS3などに置けば簡単にブログを公開できます。

Hugoのインストール

Homebrewでインストールしました。
Mac以外の環境の場合は公式インストール手順ページに書いてあります。

$ brew install hugo

Hugoサイトを作成する

下記コマンドを叩くことでHugoサイトの雛形が生成されます。

$ hugo new site test-blog

下記のようなディレクトリと設定ファイルの一式が作成されます。

$ ls test-blog
.
├── archetypes          # 記事のテンプレートを置くためのディレクトリ
│   └── default.md
├── content             # 記事を置くためのディレクトリ
├── data                # 記事で使用したいパラメータを置くためのディレクトリ(toml、yaml、json)
├── hugo.toml           # 設定ファイル
├── layouts             # themeの上書きや独自レイアウトを追加するためのディレクトリ
├── static              # 静的ファイルを置くためのディレクトリ
└── themes              # テーマを入れるためのディレクトリ

Hugoサイトの雛形へ移動して、

$ cd test-blog

Gitで管理します。

$ git init 
$ git add .
$ git commit -m "first commit"

使用するテーマを設定する

hugo-themes.png https://themes.gohugo.io/themes/
Hugo公式ページでは、さまざまなテーマが紹介されているので、このページから使用したいテーマを選ぶことができます。

今回はhugo-blog-awesomeを使用します。
git submodule addコマンドを叩くことで、themesの配下にhugo-blog-awesomeテーマを追加します。

$ git submodule add https://github.com/hugo-sid/hugo-blog-awesome.git themes/hugo-blog-awesome

設定ファイルは、test-blog/hugo.tomlを開いて

$ vim hugo.toml

下記のように更新します。

baseURL = 'http://example.com/'
languageCode = 'ja-jp'
title = 'My New Hugo Site'

theme = 'hugo-blog-awesome'

defaultContentLanguage = 'ja'
[Languages]
    [Languages.ja]
      languageName = "Japanese" 
      languageCode = "ja"
      contentDir = "content"
      weight = 1

      [Languages.ja.menu]
      [[Languages.ja.menu.main]]
        pageRef="/"
        name = 'ホーム'
        url = '/'
        weight = 10

      [[Languages.ja.menu.main]]
        pageRef="posts"
        name = '投稿'
        url = '/posts/'
        weight = 20

      [Languages.ja.params.author]
        intro = "サイト名"
        name = "author"
        description = "これはテストブログです"
設定項目設定する内容
baseURL公開するときのURL
languageCode言語設定
titleブログタイトル
theme使いたいテーマ名
defaultContentLanguageデフォルトで表示する言語ページ
Languages各言語ページ毎の設定
Languages.ja.menu日本語ページで表示するメニューの設定
Languages.ja.prams日本語ページで使用するパラメータの設定
Languages.ja.params.authorのintroサイト名※
Languages.ja.params.authorのname執筆者名※
Languages.ja.params.authorのdescriptionサイト説明※

hugo-blog-awesomeでは言語毎のページを作成できますが、今回は日本語ページのみの設定を行っています。
※ hugo-blog-awesomeのデモを見るとLanguages.ja.params.authorで執筆者情報を表示していますが、私はこれをサイト名表示に使用しています。

コンパイルする

下記コマンドを実行することで、Markdownで記載した記事をブログコンテンツにコンパイルします。

$ hugo --minify

–minifyオプションを使うことで、出力される HTML / CSS / JS ファイルを圧縮できます。

このコマンド実行後、publicディレクトリが作成され、この中にブログコンテンツが置かれます。

.
├── archetypes          
│   └── default.md
├── content             
├── data                
├── hugo.toml           
├── layouts             
├── static              
├── public              # new
└── themes              

ローカルサーバーで確認する

HugoはローカルWebサーバ機能を内蔵しているので、下記コマンドで立ち上げます。
このコマンドを実行すると、記事がコンパイルされてから、ローカルWebサーバが立ち上がります。

$ hugo serve -D --minify

-Dオプションは下書き(draft=true)ページを表示するオプションです。

立ち上げたローカルサーバ(http://localhost:1313/ )にアクセスすると、ブログトップページにアクセスできます。

hugo-local-test.jpg

以上がHugoのインストール方法と設定方法でした。
次はこれをS3に上げてCloudFrontで配信するために、AWSコンソールでの設定を行います。

S3バケットの作成

まずはブログコンテンツを配置するS3バケットを作成します。
デフォルトの設定で大丈夫です。
ブログurlをhttps://blog.<ドメイン名>にしたいので、わかりやすいようにバケット名もこのように設定しました。
make-s3-bucket.png

下記コマンドでs3バケットにブログコンテンツをアップロードします。  

$ aws s3 sync --delete public/ s3://<バケット名>

–deleteオプションは、publicフォルダに存在せずs3バケットに存在するファイルを削除するオプションです。

CloudFrontの作成、設定

次にCloudFrontディストリビューションを作成します。

make-cloudfront-step1.png 名前と説明のところはわかりやすくブログFQDNにしています。
custom domainの設定はスキップします。

make-cloudfront-step2.png オリジンドメインは先ほど作成したS3バケットを選択します。
Settingはデフォルトで大丈夫です。

make-cloudfront-step3.png WAFの設定はOFFで作ります。

その後確認画面がでるので、確認してCloudFrontディストリビューションを作成します。

デフォルトルートオブジェクトの設定

次に、https://blog.<個人ドメイン名>にアクセスしたら、https://blog.<個人ドメイン名>/index.htmlにアクセスする設定をします。
cloudfront-config.png CloudFrontディストリビューションの設定を編集して、

default-root-object.png index.htmlをデフォルトルートオブジェクトに設定します。

パスの設定

次に、URLの末尾が"/“のURL(https://blog.<個人ドメイン名>/posts/article1/)にアクセスしたとき、末尾がindex.htmlのURL(https://blog.<個人ドメイン名>/posts/article1/index.html)に変更する設定をします。
下記のようなコードでCloudFront Functionを作成します。
ランタイムはcloudfront-js-2.0で作成します。

function handler(event) {
    var request = event.request;
    var uri = request.uri;
    if (uri.endsWith('/')) {
        request.uri += 'index.html';
    }
    else if (!uri.includes('.')) {
        request.uri += '/index.html';
    }
    return request;
}

その後、“関数を発行"ボタンを押して関数を発行します。
発行できたら、“関連付けを追加"ボタンを押して、先ほど作成したCloudFrontディストリビューションのDefaultビヘイビアのView Requestと関連づけます。 cloudfront-functions.png

アクセス確認

最後に、CloudFrontディストリビューションのページから、ディストリビューションドメイン名をコピーして、ブラウザからアクセスできるかチェックします。 cloudfront.png

hugo-local-test.jpg

ブログにアクセスできれば成功です。

ドメインの設定

ドメインの購入

ブログサイトへのアクセスをHTTPSで行うために、個人ドメインが必要です。
Route53で購入します。 route53.png マネジメントコンソールでRoute53を開いたら、登録済みドメインから、“ドメインを登録ボタン"でドメイン購入ページへアクセスできます。

ブログサイト用サブドメインの設定

購入したドメインを使用して、ブログサイト用のドメインを作成します。
Route53の左ペインのホストゾーンをクリックして、先ほど登録したドメイン名が存在することを確認します。 route53-hostzone.png

ブログ用に新しいホストゾーンを作成します。
ブログ用サブドメイン : blog.<購入したドメイン>
blog-ns.png

作成したレコードを開くと下の画像のようにレコードが2つできています。 sub-domain.png 上の図の赤い四角の中に4つアドレスがあるので、これをコピーします。

次に購入したドメイン名と同じホストゾーンを開き、NSレコードを作成します
このレコードの値に先ほどコピーした4つのアドレスをペーストします。
ns-record.png

  • レコード名: blog
  • レコードタイプ: NS - ホストゾーンのネームサーバ
  • 値: 先ほどコピーした4つのアドレス

証明書の作成

サーバ証明書をACMで作成します。
証明書タイプはパブリックで作成します。
syomeisyo.png

下記2つのURLでブログサイトにアクセスするように設定するので、下記のように2つドメインを登録します。

  • https://blog.<購入したドメイン
  • https://www.blog.<購入したドメイン>

リクエストボタンを押すと、検証ページに遷移するので、“Route53でレコードを作成"ボタンを押します。 syomeisyo2.png

検証ページの証明書ステータスが"保留中の検証"から"発行済み"に変われば成功です。

CloudFrontの代替ドメイン設定

次にCloudFrontディストリビューションの設定を編集して、代替ドメイン名にブログサイト用ドメインを追加します。
cloudfront-config.png CloudFrontの設定の代替ドメイン名のところにある"Add domain"ボタンをクリックします。 cloudfront-alter-domain.png 下記2つのドメインを追加します。

  • https://blog.<購入したドメイン
  • https://www.blog.<購入したドメイン>

次のGet TLS certificateページでは、先ほど作成した証明書が表示されているので、そのまま何もせず次に進みます。

ブログサイト用レコードの設定

次にブログサイト用のAレコードを作成します。
ブログサイト用サブドメインに下記2つのAレコードを登録します。
a-record.png

  • https://blog.<購入したドメイン
    • レコード名: 空白
    • レコードタイプ: A - IPv4アドレスと一部のAWSリソースに…
    • エイリアス: True
    • トラフィックのルーティング先
      • CloudFrontディストリビューションへのエイリアス
      • CloudFrontディストリビューションID
  • https://www.blog.<購入したドメイン>
    • レコード名: www
    • レコードタイプ: A - IPv4アドレスと一部のAWSリソースに…
    • エイリアス: True
    • トラフィックのルーティング先
      • CloudFrontディストリビューションへのエイリアス
      • CloudFrontディストリビューションID

アクセス確認

最後に、下記2つのURLをブラウザに入力し、ブログサイトへアクセスできるかチェックします。

  • https://blog.<購入したドメイン
  • https://www.blog.<購入したドメイン> hugo-local-test.jpg

運用方法

記事を執筆する

hugoディレクトリに行き、下記コマンドを叩くことで記事を書くためのmarkdownファイルが生成されます。

$ hugo new posts/my-first-post/index.md
$ tree .
.
├── ...
├── content
│   └── posts
│       └── my-first-posts  
│           └── index.md    # 追加されていることを確認

contentディレクトリの中に記事を書くためのMarkdownを追加していきます。
postsディレクトリをブログ記事のディレクトリとしています。
my-first-postsディレクトリを"はじめてのHugo"という記事のディレクトリとしています。
index.mdが記事を書くためのMarkdownファイルです。   “はじめてのHugo"という記事で画像を使用したい場合、my-first-postsディレクトリに画像ファイルを追加することで、Markdownの書式で画像を使用できます。

追加されたMarkdownファイルに執筆していきます。

$ vim content/posts/my-first-post/index.md

設定項目が付いているので、まずはこれを編集します。

+++
title= "はじめてのHugo"
date= 2023-06-17T14:06:00+09:00
draft= true
toc= true
+++
設定項目設定する内容
titleページのタイトル
date日付
draft下書きページかどうか
toc目次を表示するかどうか

設定項目の下は記事の本文を書く部分になります。

+++
title= "はじめてのHugo"
date= 2023-06-17T14:06:00+09:00
draft= true
toc= true
+++

# はじめてのHugo
## Hugoとは
Golangで書かれたSSG

## Hugoを使ってみた感想
良き

記事を確認する

HugoはローカルWebサーバを内蔵しているので、下記コマンドで立ち上げます。

$ hugo serve -D --minify

立ち上げたローカルサーバ(http://localhost:1313/ )にアクセスすると、ブログトップページにアクセスできます。
記事が追加されたことを確認します。 blog-top.png 記事タイトルをクリックすると、記事を閲覧できることを確認します。 blog-article.png

記事を公開する

下記コマンドで、記事をコンパイルします。

$ hugo --minify

下記コマンドで、s3バケットにブログコンテンツをアップロードします。  

$ aws s3 sync --delete public/ s3://<バケット名>

下記コマンドで、CloudFrontのキャッシュを削除します。  

$ aws cloudfront create-invalidation --distribution-id <CloudFrontディストリビューションID> --paths "/*"