運用最適化のためのNginxからCaddyへの移行
NginxからCaddyへの移行ログ
概要
自宅サーバ上で稼働しているサービスを公開するためのリバースプロキシを、長年愛用したNginxからCaddyへと完全移行した。
Caddy - The Ultimate Server with Automatic HTTPS
Caddy is a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go

移行の動機は、サブドメインが増えるたびにSSL証明書の管理と冗長な設定記述に限界を感じたことだ。本記事では、設定ファイルがどれほどスリム化したか、そしてDocker Composeを用いた「proxy-nw」による運用構成について取り上げる。
結論
移行の結果、設定ファイルの行数は158行から55行へと激減(約65%削減)。
さらに、証明書管理の自動化により、運用コストはほぼゼロになった。
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name grafana.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name grafana.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_set_header Host $http_host;
proxy_pass http://grafana:3000;
}
# WebSocket用の特別な設定
location /api/live/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_pass http://grafana:3000;
}
# 特定パスのハンドリング
location = /robots.txt {
add_header Content-Type text/plain;
return 200 "User-Agent:*\nDisallow: /";
}
}nginx.conf (Before)
↓
grafana.example.com {
# WebSocket対応は自動(reverse_proxyが標準で処理)
reverse_proxy grafana:3000
# 特定パスのハンドリングも直感的
handle /robots.txt {
header Content-Type text/plain
respond "User-Agent:*\nDisallow: /"
}
}Caddyfile (After)
System Architecture
- Hardware: Raspberry Pi 4 Model B (8GB)
- Reverse Proxy: Caddy on Docker Compose
- Network Strategy: 共通の外部ネットワーク
proxy-nwを介したコンテナ間通信
Nginx vs Caddy
今回移行した全設定をもとに、記述量と機能性を比較した。
| 項目 | Nginx (Before) | Caddy (After) | 改善点 |
|---|---|---|---|
| 総行数 | 158行 | 55行 | 約65%の削減 |
| SSL設定 | 手動指定・更新が必要 | 完全自動(ACME) | 設定漏れ・更新忘れの消失 |
| WebSocket | 複数のHeader定義が必要 | 標準で対応 | 記述ミスによるエラーを防止 |
| 可読性 | server, location の入れ子 |
ドメインベースのフラットな記述 | ひと目で構成が把握可能 |
詳細
1. ネットワーク設計:external NWによる一元管理
プロジェクト(サービス)ごとに独立したDocker Composeを運用しつつ、Caddyと各サービスを接続するため、事前に外部ネットワーク proxy-nw を作成して運用する。これにより、Caddyを停止させずに他プロジェクトの抜き差しが可能になる。
# プロジェクト間で共有するネットワークを事前作成
docker network create proxy-nw
2. docker-compose.yaml
Caddy本体の設定。network_mode: host を避け、必要なポートのみを開放しつつ proxy-nw に所属させることでセキュリティを確保している。
services:
caddy:
image: caddy
container_name: caddy
restart: always
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3 (QUIC) 用
volumes:
- $PWD/caddy/conf:/etc/caddy
- $PWD/caddy/data:/data
- $PWD/caddy/config:/config
- $PWD/caddy/mypublic:/mypublic
- $PWD/caddy/var:/var/log/caddy
environment:
TZ: Asia/Tokyo
cap_add:
- NET_ADMIN
networks:
- proxy-nw
- default
networks:
proxy-nw:
external: true # 事前に作成した外部NWを使用
3. Caddyfile
Nginxでは158行を要した多岐にわたるサービス公開が、これだけの記述で完結する。
{
email your-email@example.com
servers {
metrics
}
}
# Grafanaのプロキシ。WebSocket設定は自動
hoge.doariva.net {
reverse_proxy hoge:3000
}
...
...
DNSは通常どおりCaddyをホストしているサーバのIPアドレスを指定する。
4. Monitoring with Grafana and Prometheus
メトリクス出力機能はCaddyに組み込まれている.設定ファイルで数行記載することでメトリクス公開可能.
- job_name: 'caddy'
metrics_path: '/metrics'
scheme: http
static_configs:
- targets:
- 'caddy:2019'prometheus.yaml
Grafana Dashboard

Caddy | Grafana Labs
The Caddy dashboard uses the prometheus data source to create a Grafana dashboard with the heatmap, piechart, stat and timeseries panels.

まとめ
NginxからCaddyへの移行は、単なる「軽量化」以上の価値があった。
- 設定の抽象化: ネットワークと証明書の管理から解放され、サービスそのものの構築に集中できる。
- 保守性の向上: 158行が55行になったことで、設定ミスが起こる余地が物理的に減った。
- 証明書管理からの解放。

