Hugoで技術ドキュメント環境を作る
はじめに
本稿の対象
Hugoによるシステムの構築およびかんたんな運用まわりについて述べる。
要件の整理
データサイエンス系に関するアウトプットはローカルのサーバにて保存したい。
そのための環境を構築する。
基本的な要件は以下の通りとした。
- 構築やリカバリが容易である。
- 動作が軽量である。
- CMSやWordPressなどのようなゴテゴテしたものは不要。
- markdownで書ける。
- (できれば)画面の印刷がきれいにできる環境が用意されている。
- カスタマイズ性(UIの変更)は二の次。
- 外部ネットワークからのアクセスは発生しない。
結論
最終的には以下の構成にすることとした。
Hugoを選択した理由はGo言語の強みであるワンバイナリで稼働するところ。
これは家庭内のサーバの移設やクラッシュからのリカバリも容易に行えるというところに強みがある。
Hugoの外装に相当する部分をthemeというが、上記要件を鑑みて、Relearnを採用した。
特にnode.jsが必要となるパッケージのリカバリの知識もなく、自信がもてないことから、そのようなthemeの採用は今回は見送ることとした。
OSをUbuntuにした理由も個人的によく使っているから以外の理由はない。
rpmもdebも配布されているため、好きな方を使えばよいと思う。
構築
Ubuntu Server 22.04 LTS
タイムゾーンの調整
タイムゾーンの設定はファイルの更新に影響を与えることから、一応調整する。
timedatectl で現在の Time zone を確認する。
timedatectl
以下のように、Time zoneがAsia/Tokyo (JST, +0900)
として表示されるかを確認する。
Local time: Sat 2022-12-31 15:36:29 JST
Universal time: Sat 2022-12-31 06:36:29 UTC
RTC time: Sat 2022-12-31 06:36:30
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
もし、タイムゾーンが日本時間(JST)になっていない場合は、下記コマンドで日本時間に変更する。
sudo timedatectl set-timezone Asia/Tokyo
ディレクトリの設定
Hugoのコンテンツは/opt/contents/hugo_contents
に配置する。
なお、作業するユーザはuser01
という一般ユーザが行うものとする。
コンテンツを格納するディレクトリの作成および権限系の付与を行う。
mkdir /opt/contents
sudo chmod 0777 /opt/contents
sudo chown user01:user01 /opt/contents
Hugoのインストール
下記リンク先より、Hugoの最新バイナリを取得することができる。
https://github.com/gohugoio/hugo/releases
ここではSCSSのコンパイルも可能なextendedバージョンをダウンロードする。
Ubuntu等であれば.deb
、CentOS等であれば.rpm
が配布されているので、それを用いてインストールするのが楽である。
それにならい、ここでは.deb
をダウンロードして、apt
を実行する。
export HUGO_VERSION=0.109.0
cd /tmp
curl -LO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb
sudo apt install ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb
Hugoがインストールされたことを確認する。
hugo version
Hugo環境の構築
プロジェクトの作成
以下の通り、サイトのテンプレートを作成する。
cd /opt/contents
hugo new site hugo_contents
gitによる管理もここでスタートさせる。
cd hugo_contents
git init
テーマの設定
relearn
テーマの取得を行う。
cd /opt/contents/hugo_contents/themes
git clone https://github.com/McShelby/hugo-theme-relearn.git hugo-theme-relearn
rm -rf .git
config.toml
を編集する。
vi /opt/contents/hugo_contents/config.toml
現状は以下のものを採用しているが、逐次編集を行っていく。
なお、編集の方針としては、以下サイトを参考にするとよい。
title = "いろんなもの置き場"
languageCode = "en"
defaultContentLanguage = "en"
theme = "hugo-theme-relearn"
baseURL = "https://example.com/"
staticDir = ["static"]
canonifyURLs = true
relativeURLs = true
uglyURLs = false
disableHugoGeneratorInject = true
[outputs]
home = ["HTML", "RSS", "PRINT", "SEARCH", "SEARCHPAGE"]
section = ["HTML", "RSS", "PRINT"]
page = ["HTML", "RSS", "PRINT"]
[markup]
[markup.highlight]
guessSyntax = true
style = "xcode-dark"
[markup.goldmark.renderer]
unsafe = true
[server]
[[server.headers]]
for = "**.html"
[server.headers.values]
X-UA-Compatible = "IE=edge"
[params]
# hugoとテーマの生成者バージョンのmetaタグの生成を無効にしたい場合は
# trueに設定する。
# HugoのdisableHugoGeneratorInject=trueも忘れずに設定すること。
disableGeneratorVersion = false
# サブメニューを展開する(true)か、折りたたむ(false)かを制御する。
# 設定を与えない場合、最初のメニューレベルはfalseに設定され、
# 他のレベルはtrueに設定されます。
# これはページのフロントマターでオーバーライドすることができます。
alwaysopen = true
# 現在のページを編集するためのプレフィックスURLを指定します。
# これにより, 各ページの右上に "Edit"ボタンが表示されるようになります.
# あなたのドキュメントに対してマージリクエストを作成する機会を人々に与えるのに便利です.
# 例として, このドキュメントサイトにあるconfig.tomlファイルをご覧下さい.
editURL = ""
# サイトの作者, メタ情報に使用される
author = ""
# サイトの説明, メタ情報の中で利用されます
description = ""
# 訪問したページのチェックマークをメニューに表示する
showVisitedLinks = false
# 検索機能を無効にする。検索バーが非表示になる
disableSearch = false
# すべてのページが隠されていてもタグの用語は表示されるが、隠されたページがタグページに表示されることを無効にする
disableTagHiddenPages = false
# JavascriptとCSSのキャッシュは、新しいバージョンのサイトが生成されたときに自動的に破棄されます。
# この動作を無効にするには、これをtrueに設定します(一部のプロキシは、この最適化をうまく処理できません)
disableAssetsBusting = false
# インラインコード用の copy-to-clipboard ボタンの無効化
# 無効にするには、これを true に設定する。
disableInlineCopyToClipBoard = true
# メニューのショートカットのタイトルが設定の無効化
# 無効にするには、これを true に設定する。
disableShortcutsTitle = false
#### MathJax ####
# MathJaxの読み込み
# falseに設定すると、MathJaxショートコードが存在するかどうかに関わらず、
# すべてのページでMathJaxモジュールがロードされます。
disableMathJax = false
# MathJax.jsのリモートロケーションの指定
customMathJaxURL = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
# MathJaxの初期化パラメータ
mathJaxInitialize = "{}"
#### Mermaid ####
# Mermaidの読み込み
# falseに設定すると、MermaidショートコードやMermaidコードフェンスが存在するか
# どうかに関わらず、すべてのページでMermaidモジュールをロードします。
disableMermaid = false
# Mermaid.jsのリモートロケーションの指定
customMermaidURL = "https://unpkg.com/mermaid/dist/mermaid.min.js"
# Mermaidの初期化パラメータ
mermaidInitialize = "{ \"theme\": \"default\" }"
#### Swagger ####
# Swaggerの読み込み
# falseに設定すると、Swaggerショートコードがあるなしに関わらず、
# すべてのページでSwaggerモジュールをロードします。
disableSwagger = false
# RapiDoc.jsのリモートロケーションの指定
customSwaggerURL = "https://unpkg.com/rapidoc/dist/rapidoc-min.js"
# Swaggerの初期化パラメータ
swaggerInitialize = "{ \"theme\": \"light\" }"
# メニューの検索バーの下にホームボタンの表示
# falseに設定すると、ホームボタンが表示されます。
# 指定された場合, 現在の言語のランディングページにリダイレクトされます.
# (デフォルトは"/"です)
disableLandingPageButton = true
# 多言語のウェブサイトを利用している場合,
# trueにすると言語切り替えボタンを無効化する。
disableLanguageSwitchingButton = true
# ページのヘッダーにある目次メニュー
# trueに設定すると非表示になる。
disableToc = false
# ヘッダーのパンくずを隠し、現在のページタイトルのみを表示する
disableBreadcrumb = false
# メニューのセクションを "weight"または "title"で並び替えます。
# デフォルトは "weight"
# これはページのフロントマターで上書きすることができる
ordersectionsby = "weight"
# デフォルトの配色を別の配色に変更します.
# 例えば, "red", "blue", "green"または["blue", "green"]のような配列にすることができます.
themeVariant = [ "blue", "relearn-light", "relearn-dark", "learn", "neon", "green", "red" ]
# タイトルのセパレータを変更します。デフォルトは"::"です.
titleSeparator = "::"
# trueに設定すると, サイドバーのメニューが折りたたみ可能なツリービューで表示されます.
# 古いブラウザ(IE11)でも機能は動作しますが、
# エキスパンダーアイコンの表示はモダンブラウザに限定されます
collapsibleMenu = true
# 通常はコンテンツの横に縦長に表示される次ページと前ページのボタンを隠す
disableNextPrev = false
# 1つのページが複数の言語でコンテンツを含むことができる場合、それらをここに追加します。
additionalContentLanguage = [ "en" ]
disableSeoHiddenPages = false
Hugo環境の起動
手動実行
Hugoを実行する。
ここでlocalhost以外からのアクセスを受け付ける--bind 0.0.0.0
と
起動時に再ビルドを行う--disableFastRender
をオプションに付与して起動させる。
hugo server --bind 0.0.0.0 --disableFastRender
あとはコンテンツを作るだけ。
サービス化
基本的にはサービスによる稼働をさせたい。
sudo vi /etc/systemd/system/hugo.service
パラメータの意味は以下の通り。
-
Restart=always
を指定することで異常・正常にかかわらず再起動を試みます。 -
StartLimitBurst
は再起動を実施する回数の上限、StartLimitIntervalSec
は再起動のインターバルの秒数です。
[Unit]
Description=Hugo Contents
[Service]
Type=simple
WorkingDirectory=/opt/contents/hugo_contents
ExecStart=/usr/local/bin/hugo server --bind 0.0.0.0 --disableFastRender
Restart=always
StartLimitBurst=5
StartLimitIntervalSec=10
User=user01
Group=user01
[Install]
WantedBy=multi-user.target
設定ファイル再読み込みをおこない、起動できるか確認する。
sudo systemctl daemon-reload
sudo systemctl start hugo.service
sudo systemctl status hugo.service
OKであれば、有効化を行う。
sudo systemctl enable hugo.service
運用関連
バックアップとリストア
基本的にリストアは以下をどこかに退避しておけば、容易に行うことができる。
- hugoのdebパッケージ(今回だと"hugo_extended_0.109.0_linux-amd64.deb")
- コンテンツデータ
コンテンツデータとは、/opt/contents/hugo_contents
配下のデータのことを指す。
/opt/contents
に移動して、hugo_contents
配下のデータを日時情報を付与したtarファイルにまとめるサンプルを以下に示す。
#!/bin/bash
BACKUP_TIME=`date "+%Y%m%d_%H%M%S"`
cd /opt/contents
tar zcvf hugo_contents_${BACKUP_TIME}.tar.gz hugo_contents/
あとはこれをどこかに転送する仕組みを追加し、crontabなどで定期的に実行すればよい。
Discussion