「Let's Encryptの証明書をCertbotで手動取得・更新するのが面倒だ」
そんな悩みを抱えるLinuxエンジニアは多い。CaddyはNginxと同じくWebサーバー・リバースプロキシとして機能しながら、Let's EncryptのSSL証明書を自動で取得・更新する機能を内蔵している。Caddyfileの設定はわずか数行で済む。この記事では、Ubuntu Server上でCaddyを使ってOllamaのAPIをHTTPS対応リバースプロキシ経由で安全に公開する手順を解説する。インストールからBasic認証の追加・よくあるトラブルの対処まで一通りカバーする。
この記事のポイント
・Caddyfileにドメイン名とreverse_proxyを書くだけでHTTPS証明書が自動取得される
・certbotやcronの手動設定が不要で、証明書の更新もCaddyが自動で行う
・caddy hash-passwordとbasicauthディレクティブでAPIをパスワード保護できる
・OLLAMA_HOSTを127.0.0.1に限定してCaddy経由のみアクセスさせる構成が基本
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
NginxではなくCaddyを選ぶ理由
OllamaのリバースプロキシにはNginxが使われることが多い。しかしCaddyには明確なメリットがある。最大の特徴は自動HTTPSだ。NginxでHTTPS対応するには、Certbotをインストールし、certbot --nginxコマンドを実行し、cronで証明書を自動更新する設定も必要になる。CaddyはLet's EncryptへのACMEリクエスト・証明書の保存・定期更新を自前でやる。追加インストールも手動cron設定も不要だ。
もう一つの特徴は設定ファイルの簡潔さだ。Nginxのnginx.confはserver・location・ssl_certificate等のブロックを複数書く必要があるが、CaddyのCaddyfileは1ドメインあたりわずか3~5行で済む。設定変更後の反映も
sudo systemctl reload caddyの1コマンドで完結する。NginxにはないCaddy固有の特徴として、リロード時に既存の接続を切断せずに設定を切り替えるグレースフルリロードが標準で動作する点も実運用で助かる。
事前準備:ドメインとファイアウォールの設定手順
CaddyでHTTPS証明書を自動取得するには2つの前提条件がある。1. 公開ドメイン名を用意する
Let's EncryptのHTTP-01チャレンジはドメイン名を必要とする。IPアドレス直接では証明書を取得できない。VPSを使っている場合は、取得済みのドメインをサーバーのIPに向けるAレコードをDNSに設定する。チームのLAN内のみで使う閉じた環境には、mkcertでローカルCA証明書を作成する方法もある。本記事はパブリックVPS+公開ドメインを前提とする。
OllamaのUbuntu Serverへの初期構築については「Ubuntu ServerでローカルLLMを構築する方法」を参照してほしい。本記事はOllama導入済みの前提で進める。
2. UFWでCaddyに必要なポートを開放する
# Caddy用ポートを開放(HTTP challengeに80、HTTPS通信に443が必要) $ sudo ufw allow 80/tcp comment 'Caddy HTTP challenge' $ sudo ufw allow 443/tcp comment 'Caddy HTTPS' $ sudo ufw reload # 設定を確認 $ sudo ufw status Status: active To Action From -- ------ ---- 22/tcp ALLOW Anywhere 80/tcp ALLOW Anywhere 443/tcp ALLOW Anywhere
CaddyをUbuntu Serverにインストールする手順
Caddyはデフォルトのaptリポジトリには含まれていない。Caddy公式が提供するAPTリポジトリを登録してインストールする。1. CaddyのAPTリポジトリを追加する
# 必要なパッケージをインストール $ sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl # Caddy公式GPGキーを取得してキーリングに追加 $ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \ | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg # APTリポジトリを追加 $ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \ | sudo tee /etc/apt/sources.list.d/caddy-stable.list # パッケージリストを更新してCaddyをインストール $ sudo apt update && sudo apt install -y caddy
2. インストールとsystemdサービスの自動起動を確認する
# バージョンを確認 $ caddy version v2.9.1 h1:OTkEHPxOm7SUJR9bDWF6RZNJ/Kno+k4oy0XCW/EVZ9M= # systemdサービスの状態を確認 $ sudo systemctl status caddy * caddy.service - Caddy Loaded: loaded (/usr/lib/systemd/system/caddy.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2026-09-03 10:00:00 JST; 10s ago
OllamaのリバースプロキシをCaddyfileで設定する手順
Caddyの設定ファイルは/etc/caddy/Caddyfile だ。デフォルトではサンプル設定が入っている。Ollamaのリバースプロキシ用に書き換える。1. Ollamaをlocalhostのみにバインドする
CaddyがリバースプロキシとしてOllamaのAPIを受け取るため、Ollama自体は127.0.0.1にのみバインドして外部から直接アクセスさせない設定にする。# override.confを編集してOLLAMA_HOSTをlocalhostに限定する $ sudo systemctl edit ollama # エディタが開いたら以下の内容を追記する [Service] Environment="OLLAMA_HOST=127.0.0.1:11434" # 保存後に設定を反映 $ sudo systemctl daemon-reload && sudo systemctl restart ollama # OllamaがlocalhostのみでListenしていることを確認 $ ss -tlnp | grep 11434 LISTEN 0 128 127.0.0.1:11434 0.0.0.0:* users:(("ollama",pid=12345,fd=3))
2. Caddyfileにリバースプロキシ設定を書く
# /etc/caddy/Caddyfileを編集(your.domain.comは実際のドメイン名に置換すること) $ sudo nano /etc/caddy/Caddyfile # 以下の内容に書き換える your.domain.com { reverse_proxy localhost:11434 encode gzip header { X-Content-Type-Options nosniff X-Frame-Options DENY Strict-Transport-Security "max-age=31536000; includeSubDomains" } }
reverse_proxy localhost:11434 の1行がOllamaへのプロキシ設定だ。encode gzip でレスポンスを圧縮し転送量を削減する。header ブロックはセキュリティヘッダーを付与する設定だ。3. 設定を検証してCaddyに反映する
# 設定ファイルの構文チェック $ sudo caddy validate --config /etc/caddy/Caddyfile Valid configuration # 設定を反映(グレースフルリロード・既存接続を維持したまま切り替わる) $ sudo systemctl reload caddy # 動作確認(HTTPS経由でOllamaバージョンを取得) $ curl https://your.domain.com/api/version {"version":"0.6.5"}
caddy validate が Valid configuration を返せば構文エラーはない。curl でOllamaのAPIがHTTPS越しに返ってくれば設定完了だ。Let's Encryptによる自動HTTPS証明書取得を確認する手順
Caddyfileにドメインを書いてリロードすると、Caddyが自動でACMEチャレンジを実施してLet's Encryptの証明書を取得する。状況を確認する。1. Caddyのログで証明書取得を確認する
# journalctlでCaddyのログを確認 $ sudo journalctl -u caddy -n 30 --no-pager | grep -i 'certificate\|tls\|acme' Sep 03 10:01:05 server caddy[12345]: {"level":"info","msg":"certificate obtained successfully","identifier":"your.domain.com"} Sep 03 10:01:05 server caddy[12345]: {"level":"info","msg":"served key authentication","identifier":"your.domain.com"}
2. 証明書の有効期限を確認する
# opensslで証明書の発行元と有効期限を確認 $ echo | openssl s_client -connect your.domain.com:443 -servername your.domain.com \ | openssl x509 -noout -issuer -dates issuer=C=US, O=Let's Encrypt, CN=R11 notBefore=Sep 3 01:00:00 2026 GMT notAfter=Dec 2 01:00:00 2026 GMT
issuer に Let's Encrypt が表示され、notAfter が90日後の日付になっていれば証明書取得は成功だ。Caddyは証明書の有効期限を自動で監視し、期限の30日前に更新する。Certbotのような手動設定やcronジョブは不要だ。
Basic認証でOllamaのAPIアクセスを保護する手順
社内チームにOllamaのAPIを提供する場合、パスワードなしで公開するのは避けたい。Caddyのbasicauth ディレクティブを使ってパスワード保護を追加する。機密データを扱うローカルLLMをチームで使うときのセキュリティの考え方については「社内でChatGPTが使えないときの代替手段」でも整理している。
1. パスワードをbcryptハッシュ化する
Caddyのbasicauthはパスワードをbcryptハッシュ形式で設定ファイルに書く。平文のまま書かない。# caddy hash-passwordでbcryptハッシュを生成 $ caddy hash-password --plaintext "my-secure-password" $2a$14$xvABs6.g3jPzXV5jIcPgXeGCPZkj9M/AYrHl3Xjn4oOMZ1KPmBQ2y
2. CaddyfileにBasic認証を追加する
# /etc/caddy/Caddyfileを更新 your.domain.com { basicauth { # ユーザー名とbcryptハッシュパスワードを半角スペースで区切る teamuser $2a$14$xvABs6.g3jPzXV5jIcPgXeGCPZkj9M/AYrHl3Xjn4oOMZ1KPmBQ2y } reverse_proxy localhost:11434 encode gzip header { X-Content-Type-Options nosniff X-Frame-Options DENY Strict-Transport-Security "max-age=31536000; includeSubDomains" } } # 設定を検証して反映 $ sudo caddy validate --config /etc/caddy/Caddyfile && sudo systemctl reload caddy
3. Basic認証の動作を確認する
# 認証なしでアクセス(401 Unauthorizedが返るはず) $ curl -s -o /dev/null -w "%{http_code}" https://your.domain.com/api/version 401 # 正しい認証情報でアクセス $ curl -u "teamuser:my-secure-password" https://your.domain.com/api/version {"version":"0.6.5"}
401 が返れば認証が機能している。-u オプションで認証情報を渡すとAPIが正常に返る。接続後にどのモデルを活用するかは「ローカルLLMのモデルを比較する方法」で詳しく解説している。
よくあるトラブルと対処法
ACMEチャレンジが失敗して証明書を取得できない場合
Let's Encryptの証明書取得失敗の原因の大半は「ポート80が外部から到達できない」か「DNSが正しく設定されていない」だ。# Caddyのログで詳細なエラーを確認する $ sudo journalctl -u caddy -n 50 --no-pager | grep -i 'error\|failed\|acme' # UFWのポート80開放を確認 $ sudo ufw status | grep 80 80/tcp ALLOW Anywhere # DNSが正しく向いているか確認 $ dig +short your.domain.com 203.0.113.10
502 Bad Gatewayが返る場合
CaddyはOllamaに接続できているがOllamaが正常に動作していないか、バインドアドレスが不一致のときに502が返る。# Ollamaサービスの状態確認 $ sudo systemctl status ollama # → Activeでなければ再起動する $ sudo systemctl restart ollama # localhostから直接APIを叩いて動作確認 $ curl http://localhost:11434/api/version {"version":"0.6.5"}
localhost:11434 から直接レスポンスが返ればOllama側は正常だ。502が続くならCaddyfileの reverse_proxy の向き先アドレスを確認する。ブラウザからCORSエラーが出る場合
JavaScriptからfetch() でCaddy経由のOllama APIを呼ぶとCORSエラーが出ることがある。CaddyfileにCORSヘッダーを追加する。# CaddyfileのheaderブロックにCORSヘッダーを追加 your.domain.com { basicauth { ... } reverse_proxy localhost:11434 header { Access-Control-Allow-Origin "https://your-frontend.example.com" Access-Control-Allow-Methods "GET, POST, OPTIONS" Access-Control-Allow-Headers "Content-Type, Authorization" X-Content-Type-Options nosniff } } $ sudo caddy validate --config /etc/caddy/Caddyfile && sudo systemctl reload caddy
Access-Control-Allow-Origin には許可するオリジンを明示する。チーム内のみで使う内部ツールであれば *(全オリジン許可)も選択肢だが、注意が必要だ。* にするとインターネット上の任意のオリジンからリクエストが通るため、Basic認証と組み合わせていても公開用途では避けること。まとめ
CaddyでOllamaをHTTPS対応リバースプロキシで公開する手順をまとめた。Nginxと比べてCertbotの手動設定が不要になるのが最大のメリットだ。設定手順と確認コマンドを整理する。| 手順 | コマンド | ポイント |
|---|---|---|
| Ollamaをlocalhost限定にする | OLLAMA_HOST=127.0.0.1:11434 | Caddy経由のみアクセスさせる |
| Caddyをインストール | sudo apt install -y caddy | systemdサービスが自動登録される |
| 設定ファイルを検証 | sudo caddy validate --config /etc/caddy/Caddyfile | Valid configurationが返れば構文OK |
| 設定を反映 | sudo systemctl reload caddy | 既存接続を維持したままリロード |
| パスワードをハッシュ化 | caddy hash-password --plaintext "パスワード" | Caddyfileにbcryptハッシュを書く |
| 認証動作確認 | curl -u "user:pass" https://domain/api/version | バージョンJSONが返れば完了 |
ローカルLLMの構築・セキュア運用を2日間のハンズオンで体験する
OllamaのインストールからCaddyによるHTTPS化・Basic認証の設定まで、実機Linux環境で手を動かしながら習得したい方向けに、「ローカルAIマスターセミナー」を開催しています。
少人数(最大8名)ZOOMハンズオン形式で実施しています。
・Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
・社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
・ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:OllamaでローカルLLMをfine-tuningする方法|UnslothとLoRAでGGUF変換して業務特化モデルをOllamaに取り込む手順
- この記事の属するカテゴリ:ローカルLLMへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます