Caddy

ウェブサーバーとリバースプロキシ。

いくつか特徴がある。

  • 証明書を自動で取得してくれる
  • 一つの実行ファイルで完結しているので、好きな場所に配置できる
  • 設定ファイルをカレントディレクトリから読み込むのでディレクトリによって動作を変えられる
  • ドキュメントがわかりやすい

デメリットとしては。

  • サービスにしたければ手動で登録する必要がある
  • nginxのような大量のアクセスに対してどの程度の性能があるのかよくわからない

今のところ大量のアクセスを処理しなければならない状況にはないので、自分にはCaddyが適していると思う。

今のCaddyfileはこんな感じ。あまり綺麗ではないので後で整理したい。

 1 moli-green.xyz {
 2     root * /home/moli/Public/www
 3     file_server
 4 }
 5 
 6 moli-stream.zapto.org {
 7     reverse_proxy :8080
 8 }
 9 
10 :80 {
11     root * /home/moli/Public/onion
12     file_server browse
13 }

インストール

静的バイナリをインストールすることにする。

1 curl -OL https://github.com/caddyserver/caddy/releases/download/v2.9.1/caddy_2.9.1_linux_arm64.tar.gz
2 tar xzf caddy_2.9.1_linux_arm64.tar.gz

このバイナリ一つで使用するとこができる。

署名の検証方法はよくわからなかった。

Caddyをサービスにする

まあ、あとはドキュメントの通りでうまくいく。

設定ファイルを編集する。

1 sudo vim /etc/caddy/Caddyfile
2 sudo systemctl reload caddy

静的サイトの場所はどこにでも配置できる。(/var/www/html, /srv が例に上がっているが、標準的なディレクトリとして例示しているだけだろう)

API

caddyの管理エンドポイントはCADDY_ADMIN環境変数で設定できる。

 1 # 管理エンドポイントのために使用されてないポートを探す
 2 ss -ant | grep 2222
 3 
 4 # caddyの管理エンドポイントを設定
 5 export CADDY_ADMIN=localhost:2222
 6 
 7 # Caddyを起動(runの方がいいかもしれない)
 8 ./caddy start
 9 
10 # 構成ファイルを作成
11 jq -n '{apps: {http: {servers: {foo: {listen: [":2015"], routes: [{handle: [{handler: "static_response", body: "hello!"}]}]}}}}}' > config.json
12 
13 # 構成ファイルをロード
14 curl localhost:2222/load -H 'Content-Type: application/json' -d @config.json
15 
16 # 構成を表示
17 curl localhost:2222/config/ | jq
18 
19 # 構成を変更
20 curl localhost:2222/config/apps/http/servers/foo/routes/0/handle/0/body -H 'Content-Type: application/json' -d '"second."'
21 
22 # IDを設定
23 curl localhost:2222/config/apps/http/servers/foo/routes/0/handle/0/@id -H 'Content-Type: application/json' -d '"msg"'
24 
25 # IDを使用して構成を変更
26 curl localhost:2222/id/msg/body -H 'Content-Type: application/json' -d '"something..."'
27 
28 # Caddyを停止
29 ./caddy stop
30 
31 # Caddyを前回の構成で起動
32 sudo -E ./caddy run --resume &

GET/config/[path]

1 curl http://localhost:2019/config/ | jq

JSON Config Structure /apps/http/servers

1 curl -s http://localhost:2019/config/apps/http/servers | jq '.'
* * *

構成をエクスポート。

1 curl -s http://localhost:2019/config/apps/http/servers | jq '.'

Caddyfile

グローバルオプション

トップレベルの括弧はグローバルオプションを意味する

1 {
2     ...
3 }
1 email moli_green@runbox.com

HTTP3を設定するにはこうする。

1 servers :443 {
2     protocols h1 h2 h3
3 }

細かく設定すると、こんな感じになる。

1     log hoge {
2         level debug
3         format console
4         output file /home/moli/work/s/log {
5             roll_size 1mb
6             roll_keep 2
7     }
8     }           roll_keep_for 1m
9     

しかし、最低限の設定でも十分だと思われる。

1     log {
2         output file /home/moli/work/s/log
3     }

ディレクティブ

1 encode zstd gzip
1 header foo "bar"

HTST

httpの接続をhttpsにアップグレードする。max-ageはブラウザがそれを記憶する秒数。

preloadはGoogleのサービスを使うので、適切な資格が必要なようだ。

以下は、有効期間が5分の例(最終的に2年に設定するのが目標なようだ)

1 header Strict-Transport-Security "max-age=300; includeSubDomains"
* * *

リクエストの最大サイズを指定する。(POSTリクエストも含まれるようなので、添付できるファイルサイズの上限でもある)

1     request_body {
2         max_size 1MB
3     }
1 reverse_proxy localhost:50000 {
2         header_up Host {http.request.host}
3     }

beader_upはバックエンドに送るヘッダーを操作する。 Header Valueの形になっている。{http.request.host}はリクエストヘッダーに含まれるホスト名を示す。なので、この例の指定はホスト名にホスト名を設定しているだけなので、何も設定しなくても、違いはない。

1 tls {
2     protocols tls1.2 tls1.3
3 }