運用最適化のためのNginxからCaddyへの移行

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への移行は、単なる「軽量化」以上の価値があった。

  1. 設定の抽象化: ネットワークと証明書の管理から解放され、サービスそのものの構築に集中できる。
  2. 保守性の向上: 158行が55行になったことで、設定ミスが起こる余地が物理的に減った。
  3. 証明書管理からの解放。