Linuxサーバー

パネル不要の無料 SSL 証明書:Nginx で Certbot・acme.sh、Cloudflare DNS でワイルドカード証明書と自動更新

7 ステップ 12 分で読めます 25 回閲覧 0
目次

HTTPS の運用にコントロールパネルは必要ありません。Certbot や acme.sh を使えば、Nginx 上のどのサイトにも Let's Encrypt の無料証明書を取得でき、Cloudflare DNS API を使って *.example.com のようなワイルドカード証明書を発行し、自動で更新することもできます。この記事では、Debian/Ubuntu と Rocky Linux/AlmaLinux での両ツールの使い方、Nginx の HTTPS 設定、Cloudflare プロキシ配下のサイト、そして更新が本当に機能しているかの確認方法を解説します。

Let's Encrypt の証明書の有効期間は 90 日で、Let's Encrypt は 2025 年に有効期限切れの通知メールの送信を終了しました。設定後は必ずドライランで自動更新を確認してください。確認しておかないと、証明書の期限切れで気付かないうちにサイトが表示できなくなります。

始める前に

  • ドメインの A レコード(IPv6 を使う場合は AAAA レコードも)がサーバーの IP を指していること。dig +short example.com で確認できます。
  • サーバーのファイアウォールでポート 80 と 443 が開いていること(firewalld と ufw でのポート開放を参照)。
  • Nginx がインストール済みで、サイトがすでに HTTP で表示されていること。

方法A:Certbot の Nginx プラグインを使う(最も簡単)

Certbot は証明書を取得したうえで、HTTP から HTTPS へのリダイレクトも含めて Nginx の server ブロックを自動で編集してくれます。

# Debian / Ubuntu
apt update
apt install -y certbot python3-certbot-nginx

# Rocky Linux / AlmaLinux (EPEL)
dnf install -y epel-release
dnf install -y certbot python3-certbot-nginx

# Request and install a certificate for the domain and www
certbot --nginx -d example.com -d www.example.com \
  --agree-tos -m [email protected] --redirect

# Renewal is scheduled automatically; confirm the timer and run a test renewal
systemctl list-timers | grep -i certbot
certbot renew --dry-run

証明書は /etc/letsencrypt/live/example.com/ に保存されます。Nginx の設定ファイルを書き換えられたくない場合は certbot certonly --nginx -d example.com を使い、後述の「Nginx の HTTPS 設定」のように証明書のパスを自分で追加してください。

方法B:acme.sh を使う(軽量、Python 不要)

acme.sh は cron ジョブとして動作する単一のシェルスクリプトです。既定の認証局(CA)は ZeroSSL なので、必要に応じて Let's Encrypt に切り替えてください。

# Install (creates ~/.acme.sh and a daily cron job)
curl https://get.acme.sh | sh -s [email protected]
source ~/.bashrc

# Use Let's Encrypt as the default CA
acme.sh --set-default-ca --server letsencrypt

# Issue using your site's web root (HTTP-01 validation)
acme.sh --issue -d example.com -d www.example.com -w /var/www/example

# Install the certificate where Nginx expects it and reload Nginx on every renewal
mkdir -p /etc/nginx/ssl
acme.sh --install-cert -d example.com \
  --key-file       /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.crt \
  --reloadcmd      "systemctl reload nginx"

Nginx から ~/.acme.sh 内のファイルを直接参照してはいけません。必ず --install-cert を使ってください。このオプションはファイルをコピーし、更新のたびにリロードコマンドを実行します。

Cloudflare DNS API でワイルドカード証明書を取得

ワイルドカード証明書(*.example.com)の取得には DNS 認証が必要です。ドメインで Cloudflare DNS を使っている場合は、Cloudflare ダッシュボードの My Profile → API Tokens で「Edit zone DNS」テンプレートを使って API トークンを作成し、対象を必要なゾーンだけに限定します。

# acme.sh: dns_cf reads the token from the environment and saves it for renewals
export CF_Token="your-cloudflare-api-token"
export CF_Zone_ID="your-zone-id"        # shown on the domain's Overview page in Cloudflare
acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'

# Certbot alternative
apt install -y python3-certbot-dns-cloudflare
mkdir -p ~/.secrets && chmod 700 ~/.secrets
echo 'dns_cloudflare_api_token = your-cloudflare-api-token' > ~/.secrets/cloudflare.ini
chmod 600 ~/.secrets/cloudflare.ini
certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
  -d example.com -d '*.example.com'

DNS 認証はポート 80 が閉じている場合や、サイトにまだアクセスできない場合でも使えるため、内部サービスや構築直後のサーバーにも便利です。

Nginx の HTTPS 設定

certonly や acme.sh で証明書を発行した場合は、HTTPS 用の server ブロックを自分で追加します。証明書のパスは使用したツールに合わせて変更してください。

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;                      # Nginx 1.25.1+; older versions: "listen 443 ssl http2;"
    server_name example.com www.example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;   # acme.sh: /etc/nginx/ssl/example.com.crt
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;     # acme.sh: /etc/nginx/ssl/example.com.key
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:SSL:10m;

    root /var/www/example;
    index index.html index.php;
}
nginx -t && systemctl reload nginx

Cloudflare プロキシ配下のサイト

オレンジ色の雲(プロキシ)を有効にしていても、Cloudflare が /.well-known/acme-challenge/ へのリクエストをサーバーに転送するため、通常は HTTP 認証もそのまま使えます。オリジンに有効な証明書を設定したら、Cloudflare の SSL/TLS 暗号化モードを Full (strict) にしてください。「Flexible」ではサーバーまでの通信が暗号化されず、リダイレクトループの原因にもなりがちです。DNS 認証を使う方法もあり、サイトを常に Cloudflare 経由でのみ配信するなら無料の Cloudflare Origin Certificate も利用できます。訪問者が Cloudflare を経由せずにアクセスするのを防ぐには、オリジン IP を隠す方法を参照してください。

有効期限と更新の確認

# Expiry date of the certificate your site actually serves
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

# Certbot: all certificates and their expiry
certbot certificates

# acme.sh: list certificates and force a test renewal
acme.sh --list
acme.sh --renew -d example.com --force

よくある質問

「Timeout during connect」や 404 エラーで認証に失敗する

ポート 80 がブロックされている、DNS レコードが別の場所を指している、または別の server ブロックがそのドメインに応答している可能性があります。ファイアウォールを確認し、dig +short example.com を実行したうえで、Nginx の設定で /.well-known/acme-challenge/ がリダイレクトや拒否の対象になっていないことを確認してください。それでも解決しない場合は DNS 認証に切り替えます。

テスト中にレート制限に達してしまった

Let's Encrypt では、同じドメイン名に対して 1 週間に発行できる証明書の数に上限があります。試行錯誤している間は --dry-run(Certbot)や --staging(acme.sh)を使い、設定が正しく動作してから本番の証明書を取得してください。

1 枚の証明書で複数のドメインに対応できますか?

はい。各ドメイン名をそれぞれ -d オプションで追加します。ワイルドカードが対象とするのは 1 階層だけなので、*.example.com は shop.example.com には一致しますが、a.shop.example.com や example.com 自体には一致しません。ルートドメインは別途追加してください。

上記の手順で解決しない場合は、サポートチケットを送信して IMIDC の 24 時間 365 日対応テクニカルサポートへご連絡ください。サーバー IP、OS バージョン、ドメイン名、実行したコマンド、エラー全文を添えていただくと、より迅速に調査できます。

この回答はお役に立ちましたか?

関連チュートリアル