Hugoの動的プレビューをNginxリバプロ越しに行う設定

約1年越しの悩み
当サイト (RemoteRoom) は、Hugoという静的サイトジェネレータ (Static Site Generator) で構築している。Hugoのserver機能を併用すると、markdown記法で書き進めるコンテンツを、テンプレートが適用されたウェブサイトhttp://localhost:1313/上ですぐに動的にプレビューできるのでとても助かっている。
このプレビューを、私の環境では次のような仕掛けの上で行ってきた。
- Hugoのドラフトデータはどこでも編集できるようにDropboxに保存して同期。そのデータを、Dropboxデーモンが常駐しているクラウド上のLinuxサーバで常時hugo serverして動的なプレビューサイトを生成
- プレビューサイトの確認はTailscale越しにhttp://100.NNN.NNN.NNN:1313/で行う (つまり、Tailscale導入端末での閲覧がメイン。クローズドで安全ではあるが)
しかし、これまで2の部分が理想とは違っていた。2の理想は次の通り。
- プレビューサイトの確認はBASIC認証をかけたhttps://hugo.example.com/でどの端末からでも行えること。かつ変更ページのlive reloadingも効くこと
2に関しては約1年前に「Nginxで行うReverse Proxyの部分で、live reloadingに用いられているwebsocket通信を通す設定がわからない」と悩んで、以降諦めていた問題であったが、今改めて調べてみると一気に解決したのでメモします。
問題がクリアできた設定
1. Hugoの起動オプション
Hugoの起動オプションは次のように設定する。通信に関する4つの appendPort, baseURL, liveReloadPort, port オプションのうち1つでも欠けるとおそらく不具合が発生する (不具合の例としては、websocket通信が1313番ポートを使用してリバプロ越しに通信できない状態になったり、プレビューサイト内のリンク先URLに:1313が含まれたり)。
hugo server \ --appendPort=false \ --baseURL=https://hugo.example.com/ \ --liveReloadPort=443 \ --navigateToChanged \ --port=1313
なお、私の場合はプレビューという目的上、非公開中のページもレンダリングする次のオプションも追加している。
--buildDrafts=true \ --buildExpired=true \ --buildFuture=true
2. Nginx (Reverse Proxy)
Reverse Proxyとして動作させるNginxのサイト設定に関しては、Websocket for LiveReload using wrong port if Hugo binds to port 80 · Issue #2205 · gohugoio/hugoのコメントを参考にした。主要な内容を抜き出すと次の通り。locationで/livereloadを別扱いにしているのがポイントなのかもしれない。
server {
	listen 80;
	listen [::]:80;
	server_name hugo.example.com;
		location / {
			return 301 https://$host$request_uri;
		}
}
server {
	listen 443;
	listen [::]:443;
	server_name hugo.example.com;
		auth_basic "Restricted";
		auth_basic_user_file /etc/nginx/htpasswd.txt;
		location / {
			proxy_pass http://localhost:1313/;
			proxy_set_header Host $http_host;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;
		}
		location /livereload {
			proxy_pass http://localhost:1313;
			proxy_set_header Host $http_host;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;
			proxy_http_version 1.1;
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection "Upgrade";
		}
}参考) Twitter
hugo server の livereload を、nginx の proxy server 越しにやるにはどういう設定が要るのか?
— Masahiko OHKUBO (@mah_jp) June 29, 2021
ということにハマってる。。。かなしい。
たぶん websocket やらが関係しているがわからんとです。
hugo serve の liveReload を reverse proxy 経由でまともに動かす設定がやっとわかった。
— Masahiko OHKUBO (@mah_jp) June 12, 2022
まずは風呂♨入る。
