3年半ぶりにHugoブログを復旧して、Hugo更新と独自ドメイン化までした記録
2023年3月にHugoでブログを作ったまま放置していたが、約3年半ぶりに作業を再開した。やったことは次の4つ。自分用の備忘録としてまとめておく。
- 止まっていた自動デプロイの復旧
- Hugoのバージョンアップ(v0.110.0 → v0.166.0)
- NetlifyのNode.js 16警告への対応
- 独自ドメイン化と、その途中で見つかった2つの不具合の修正
作業はすべて「作業ブランチ → プルリクエスト → Deploy Preview → マージ → 本番確認」の流れで行った。
1.デプロイの復旧
最初に、2023年当時の状態を調べた。
| 項目 | 内容 |
|---|---|
| GitHubリポジトリ | private、デフォルトブランチ main。最終コミットは2023/3/1 |
| テーマ | Anankeをsubmoduleで管理 |
| Netlify | サイトもGitHub連携も生きていた。環境変数は未設定 |
| ローカルのHugo | v0.110.0 extended |
Netlifyには HUGO_VERSION の指定がなかったので、当時のNetlifyのデフォルトでビルドされていたはず。一気に最新へ上げると3年分の差でビルドが壊れるおそれがあるため、まずローカルと同じ 0.110.0 に固定して復旧を優先した。Netlifyの Environment variables に次を追加した。
HUGO_VERSION = 0.110.0
次に、ローカルに残っていた未コミットの変更を git status で確認した。2023年の作業が途中だったらしく、次のようなものが見つかった。
config.tomlのbaseURLが仮値のhttps://sample.comに書き換え途中だったresources/_gen/(Hugoのビルドキャッシュ)が.gitignoreがなかったせいでGit管理下に入っていた- 記事の
draft: trueと、front matterの誤記keywords: [_target] layouts/、assets/、static/images/のカスタマイズ
整理してコミットした内容は次のとおり。
baseURLをhttps://gleaming-figolla-eac13d.netlify.appに修正.gitignoreを新規作成し、resources/_gen/と.hugo_build.lockを除外git rm -r --cached resources/_genでGit管理から外す(ファイルはローカルに残り、ビルド時に再生成される)- 記事を
draft: falseにして公開
git add .
git commit -m "baseURLを設定し、テーマカスタマイズとブログ記事を公開"
git push origin main
pushするとNetlifyの自動ビルドが動き、11秒でPublishedになった。main へのpush → 自動ビルド → 本番公開、という流れが復旧できた。
2.Hugoのバージョンアップ(v0.110.0 → v0.166.0)
方針
- HugoとAnanke(テーマ)は別々にバージョンが動く。 テーマはsubmoduleで2023年のコミットに固定されているので、今回はテーマを据え置いてHugoだけ上げる。
- テーマの
min_versionは下限でしかない。新しいHugoで動くかは、実際にビルドしてみるまで分からない。 - バージョンは
netlify.tomlで指定する。Netlify画面の環境変数は本番にも効くので、マージ前に書き換えると本番ビルドまで新バージョンになる。netlify.tomlの値はブランチ限定で効き、画面の設定より優先される。 - Deploy Previewはプルリクエストで作られる。 ブランチをpushしただけでは作られない。
準備
upgrade-hugo ブランチを作り、.gitignore に public/ を追加した。public/ が2023年のコミットでGit管理下に入っていたので、git rm -r --cached public で管理から外した。.gitignore に書くだけでは、すでに追跡されているファイルは無視されない。
そのうえで、旧バージョンで基準ビルドを取って public を public_old に退避した(Pages 25、Static files 7、Aliases 1)。
ローカルHugoの入れ替え
Get-Command hugo | Format-List Source で場所を調べると Chocolatey のパスだった。導入方法は、このパスで判別できる。管理者権限のPowerShellで実行した。
choco search hugo-extended --exact --all-versions
choco upgrade hugo-extended --version 0.166.0 -y
PowerShellを開き直して hugo version を確認し、v0.166.0 ... +extended になった。
ビルドで出たエラーと対処
2023年当時の書き方が原因のエラーが、順番に出た。
| # | エラー | 対処 |
|---|---|---|
| 1 | cascade.target.language はv0.150.0で廃止 |
my-first-post.md の cascade ブロックを削除(もともと何にも効いていなかった) |
| 2 | resources.ToCSS が使えない |
テーマの GetMainCSS.html をサイト側の layouts/partials/func/style/ にコピーし、resources.ToCSS を css.Sass に置換 |
| 3 | site.Social が廃止 |
テーマの social-share.html を layouts/partials/ にコピーし、site.Params.social 経由に修正 |
| 4 | .Site.DisqusShortname が廃止 |
サイト側の single.html の該当行を site.Config.Services.Disqus.Shortname に置換 |
themes/ananke 本体は一切変更していない。サイト側の layouts/ に同じパスでファイルを置くと、テーマ側より優先される仕組みを使った。
ビルドは成功し、Pagesは26になった(25 → 26の差は、新しいHugoがSitemapsの行をなくしてPagesに含めて数えるため)。生成ファイルの一覧を新旧で Compare-Object して差がないことも確認した。
netlify.toml
リポジトリ直下に作成した。
[build.environment]
HUGO_VERSION = "0.166.0"
# プレビューでは自分のプレビューURLを基準にビルドする
[context.deploy-preview]
command = "hugo -b $DEPLOY_PRIME_URL"
プルリクエストのDeploy Previewのログで、v0.166.0、Pages 26、エラーなしを確認してからマージした。本番も問題なく表示された。最後に、Netlify画面の旧 HUGO_VERSION = 0.110.0 を削除して netlify.toml に一本化した。
3.Node.js 16の警告への対応
Netlifyのデプロイ画面にNode.js 16の非推奨警告が出ていたので、netlify.toml の [build.environment] に追記した。
NODE_VERSION = "24"
Deploy Previewのログには Now using node v24.21.0 と出たが、警告バナーは残った。バナーは netlify.toml ではなく、Netlify画面の Dependency management にあるプロジェクト単位の設定を見ているようだった。Project configuration → Build & deploy → Continuous deployment → Dependency management で Node.js version を24に変更すると、マージ後の本番でバナーが消えた。
4.独自ドメイン化
ドメインとDNSの選択
- 当初は
.siteを考えたが、お名前.comの更新料金(サービス維持調整費込み)を確認して、tassili-najjer.comに変更した。 - ブログはルートドメインではなく、サブドメイン
logs.tassili-najjer.comに割り当てる。今後サブドメインを増やす可能性があるので、DNSは Netlify DNS に委任した。サブドメインを追加するとDNSレコードが自動で作られ、HTTPS証明書(ワイルドカード)も自動でカバーされる。
手順
- お名前.comでドメインを取得(ドメインのみ 二段階認証を設定 自動更新はデフォルト設定)。
- NetlifyのDomain managementでドメインを追加し、Options → Set up Netlify DNS を選ぶ。表示された4つのネームサーバー(
dns1.p06.nsone.netなど)を、お名前.com Naviのネームサーバー設定に入力。 - 反映は想定より早く、Netlify DNSの状態(緑チェック)になった。
- Add domain alias で
logs.tassili-najjer.comを追加(DNSレコードは自動作成)。Options → Set as primary domain で、こちらをPrimaryにした。 - Let’s Encryptのワイルドカード証明書(
*.tassili-najjer.com)が自動発行された。 custom-domainブランチでconfig.tomlのbaseURLをhttps://logs.tassili-najjer.com/に変更してマージ。sitemap.xmlとRSSのURLがすべて新ドメインになっていることを確認した。
ルートドメインが転送されなかった
logs をPrimary domainにすれば、tassili-najjer.com は自動で logs に転送されると思っていたが、実際は転送されず、同じ内容がそのまま表示された。baseURL によってcanonicalは正規化されるので実害は小さいと判断し、今回はそのままにした。転送が必要になれば netlify.toml に [[redirects]] を書く。
5.本番ページのソースで見つかった2つの不具合
baseURL 更新後に本番ページのソースを見て、次の2つに気づいた。どちらも今回のドメイン変更が原因ではなく、前から潜んでいた問題だった。
問題1:本番でも noindex が出ていた
Anankeの baseof.html には、次の分岐がある。
{{ $production := eq (getenv "HUGO_ENV") "production" | or (eq site.Params.env "production") }}
{{ $public := not .Params.private }}
{{ if and $production $public }}
<meta name="robots" content="index, follow">
{{ else }}
<meta name="robots" content="noindex, nofollow">
{{ end }}
HUGO_ENV も site.Params.env も設定していなかったので、本番でも常に noindex, nofollow が出力されていた。検索エンジンにインデックスされない状態が、ずっと続いていたことになる。netlify.toml に、本番contextだけ環境変数を設定した。
[context.production.environment]
HUGO_ENV = "production"
Deploy Previewでは HUGO_ENV が効かないので noindex のままになる。これは意図どおりの動作。
問題2:<html lang="ja"ZgotmplZ>
baseof.html の <html> タグが、次のように dir 属性を条件分岐で出し入れする書き方になっていた。
<html lang="{{ site.LanguageCode | default site.Language.Lang }}" {{- with partialCached "func/GetLanguageDirection" "GetLanguageDirection" }} dir="{{ . }}" {{- end }}>
Goの html/template が、この書き方だと属性の安全性を静的に判定できず、該当部分が ZgotmplZ に置き換わっていた。Hugoアップグレード時の新旧比較で「差なし」だったのは、旧バージョンでも同じ出力だったためで、見落としていた。
GetLanguageDirection.html の .Language.LanguageDirection(非推奨)を .Language.Direction にしても直らなかった。原因は値ではなく、タグ内で属性をまるごと条件分岐させる構造そのものだった。baseof.html をサイト側にコピーして、値だけを変数で組み立て、属性は常に出力する形に直した。
{{ $langDir := partialCached "func/GetLanguageDirection" "GetLanguageDirection" }}
{{ if not $langDir }}{{ $langDir = "ltr" }}{{ end }}
<html lang="{{ site.LanguageCode | default site.Language.Lang }}" dir="{{ $langDir }}">
hugo server -D で確認してから、プルリクエスト経由で本番に反映した。本番のソースで、<html lang="ja" dir="ltr">(ZgotmplZ なし)と <meta name="robots" content="index, follow"> の両方を確認できた。
6.変更ファイルと最終状態
| ファイル | 内容 |
|---|---|
config.toml |
baseURL を https://logs.tassili-najjer.com/ に変更 |
netlify.toml(新規) |
HUGO_VERSION、NODE_VERSION、プレビュー用ビルドコマンド、本番の HUGO_ENV |
.gitignore(新規) |
resources/_gen/、.hugo_build.lock、public/、public_old/ |
layouts/_default/baseof.html(新規) |
テーマからコピー。<html> タグの dir 属性の出し方を変更 |
layouts/partials/func/GetLanguageDirection.html(新規) |
テーマからコピー。LanguageDirection → Direction |
layouts/partials/func/style/GetMainCSS.html(新規) |
テーマからコピー。resources.ToCSS → css.Sass |
layouts/partials/social-share.html(新規) |
テーマからコピー。site.Social → site.Params.social |
layouts/_default/single.html |
Disqus設定の参照を新しい書き方に変更 |
content/posts/my-first-post.md |
不要な cascade ブロックと誤記を削除、draft: false に変更 |
最終状態は次のとおり。
- サイト:
https://logs.tassili-najjer.com(Primary domain)。tassili-najjer.comは転送されず同じ内容を表示 - Hugo v0.166.0 extended(ローカルとNetlifyで一致)、Node.js 24
- HTTPS:Let’s Encryptのワイルドカード証明書、自動更新
- テーマ(Ananke)は2023-02-03時点のまま変更なし
7.今後のための運用メモ
Hugo更新の手順
choco search hugo-extended --exact --all-versionsで入れられる版を確認。- 作業ブランチを切り、管理者権限のPowerShellで
choco upgrade hugo-extended --version <版> -y。PowerShellを開き直してhugo versionで確認。 hugo --logLevel infoでERRORと非推奨警告を確認。hugo server -Dで見た目を確認。netlify.tomlのHUGO_VERSIONを更新してpushし、プルリクエストを作る(マージはしない)。Deploy Previewのログでバージョンと結果を確認。- 問題なければマージして、本番のログとサイトの表示を確認。
ロールバック
- 即時:Netlifyの Deploys から直前の成功デプロイを開いて Publish deploy(自動公開が止まるので、直したら Start auto publishing で再開)。
- 恒久:
netlify.tomlのHUGO_VERSIONを戻してpush、またはマージコミットをgit revert。 - ローカルのHugoを戻す場合:
choco install hugo-extended --version <版> --allow-downgrade -y(管理者権限)。
注意点
layouts/に置いたテーマのコピー4ファイル(baseof.html、GetLanguageDirection.html、GetMainCSS.html、social-share.html)は、テーマが更新されても追随しない。テーマを更新するときは必ず見直す。- LibSassはHugo v0.153.0で非推奨になっている。将来のHugo更新でSass関連のエラーが出ないか注意する。
git add .の前にgit statusで、public/など意図しないファイルが入っていないか確認する。
今回の学び
- Netlify画面の環境変数は本番にも効く。ブランチ限定で試すなら
netlify.toml。 - Deploy Previewはプルリクエスト用。
- Node.jsの警告バナーは、Netlify画面の Dependency management の設定を見ている。
- 追跡済みのファイルは
.gitignoreに書いても無視されない。git rm --cachedが必要。 - HTMLタグの属性を
{{ with }}でまるごと出し入れするとZgotmplZになることがある。属性は常に出力し、値だけを変数で分岐させる。 - Anankeの
index/noindexの切り替えはHUGO_ENV=productionに依存していて、Netlifyでは自動では設定されない。本番のソースは一度見ておく。 - ドメインの更新料金は時期で変わる。契約前に最新の実額を確認する。
- サブドメインをPrimary domainにしても、ルートドメインが自動で転送されるとは限らない。
8.残っている宿題
- 非推奨警告の解消:
config.tomlのlanguageCodeをlocaleに置き換える(v0.158.0で非推奨)。.Site.LanguageCodeの警告も、あわせて対応を検討する。 - Ananke本体の更新:最新はv2.19.1。v2.16.0以降はHugo v0.161以上が必須で、CSS処理が
css.Buildになり、custom_cssが[params.ananke]配下に移るなど破壊的変更がある。.gitmodulesのURL更新も必要。別ブランチで実施する。 www.tassili-najjer.comの扱い:Primary domainを変えたらwwwのエイリアスが表示から消えた。アクセスしたときの挙動は未確認。- ルートドメインの転送(任意):
netlify.tomlに[[redirects]]を追加する。 - 記事まわり(任意):
my-first-post.mdのRaw HTML omitted警告(コマンド名がHTMLタグ風に書かれているため。バッククォートで囲めば直る)、本文が「4.Netlifyでデプロイ」の直後で終わっていること、content/_index.mdの日本語化、custom.cssの誤記backgraund-color。