※本記事は2026年1月時点の情報に基づいて更新しています。Let’s Encrypt は現状「90日証明書(classic)」が基本ですが、将来的に有効期間短縮が段階的に進む予定です。運用では「手動更新」や「更新間隔の固定」ではなく、自動更新(定期実行)+期限監視を前提に設計してください。

Webサイトの常時SSL化は、もはや必須の要件となっています。Let’s Encrypt を活用すれば、無料でSSL/TLS証明書を取得・運用できます。ただし Let’s Encrypt の証明書は短い有効期間で運用されるため、証明書の自動更新ができていないと、期限切れでサービス停止につながります。特にゲームサーバーの管理パネル、API、管理画面など「止められない」サービスでは、更新の自動化と監視は必須です。
参考として、日本語の解説動画(YouTube)も埋め込んでいます。必要に応じて併せて確認してください。

SSL証明書とLet’s Encryptの基礎
SSL/TLS証明書の役割
SSL/TLS証明書は、Webサイトとユーザー間の通信を暗号化し、さらに「そのサイトが本物である」こと(ドメインの管理者であること)を証明するための仕組みです。HTTPS 化により、以下の効果が得られます。
- 盗聴・改ざんの防止:通信内容(ログイン情報、APIキー、Cookieなど)を保護
- なりすまし防止:偽サイトへの誘導リスクを低減
- ブラウザ警告の回避:非HTTPSは「保護されていない通信」と表示されやすい

Let’s Encryptの特徴
- 完全無料:費用負担なしで証明書取得
- 自動化対応:ACMEプロトコルにより自動取得・自動更新が可能
- 主要ブラウザで信頼済み:一般的なWeb利用で警告が出にくい
- 短い有効期間:90日(今後短縮予定)なので自動化が前提
acme.shによる証明書管理
acme.sh は、シンプルで扱いやすい ACME クライアントです。Let’s Encrypt の証明書取得・更新を自動化でき、DNS-01(ワイルドカード対応)にも強いのが特徴です。以降は「取得 → 配置 → 自動更新」の流れで、運用に耐える形を作ります。
acme.shの基本セットアップ
インストール方法は複数ありますが、まずは公式の導入手順に近い形で入れるのが安全です。サーバーに合わせて、git か curl のどちらかを選んでください。
# acme.sh のインストール(git)
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
sudo ./acme.sh --install --accountemail your-email@example.com
# または curl(1行)
curl https://get.acme.sh | sh -s email=your-email@example.com
環境変数の設定
acme.sh を PATH に通しておくと、cron や systemd で呼び出すときに事故が減ります。利用ユーザー(root運用 or 専用ユーザー運用)に合わせて PATH を設定してください。
# 例:.bashrc または .profile に追加
export PATH="$HOME/.acme.sh:$PATH"
source ~/.bashrc
# 動作確認
acme.sh --version
基本的な証明書取得
主な認証方式は3つです。運用上のおすすめは、停止不要でワイルドカードにも対応できる DNS-01 です。
- Webroot(http-01):Web公開ディレクトリに検証ファイルを書き込む。既存Webが動いている環境向け。
- Standalone:acme.sh が一時的に 80/TCP を使う。Webサーバー停止が必要になりやすい。
- DNS-01(推奨):DNS に TXT を自動追加。ワイルドカード対応、停止不要。
# Webroot認証(http-01)
acme.sh --issue -d example.com -w /var/www/html
# Standalone認証(Webサーバー停止が必要になることが多い)
acme.sh --issue -d example.com --standalone
# DNS認証(推奨:ワイルドカードも可能)
# ※例として Cloudflare の dns_cf を使用
acme.sh --issue -d example.com --dns dns_cf
DNS認証による自動化
DNS-01 は「DNS に TXT レコードを追加できる権限」が必要です。acme.sh は多くの DNS プロバイダーに対応しており、APIキーを環境変数で渡すと自動で TXT を更新します。重要なのは、APIキーは最小権限にし、漏えい対策(権限分離、秘匿、ローテーション)を前提にすることです。
Cloudflare DNS の設定
Cloudflare は利用者が多く、DNS-01 自動化の代表例です。Cloudflare 側の API トークン/キーを用意し、acme.sh が参照できる形で設定します。
# Cloudflare API設定(例:従来形式)
export CF_Key="your-cloudflare-api-key"
export CF_Email="your-email@example.com"
# ワイルドカード込みで発行(DNS-01)
acme.sh --issue -d example.com -d "*.example.com" --dns dns_cf
# 設定の永続化(証明書配置+リロード)
acme.sh --install-cert -d example.com \
--key-file /etc/ssl/private/example.com.key \
--fullchain-file /etc/ssl/certs/example.com.pem \
--reloadcmd "systemctl reload nginx"
Route53 DNS の設定
AWS Route53 を使う場合は、IAM のアクセスキーを用意します。ここでも最小権限(対象 Hosted Zone の変更権限のみ)を推奨します。
# AWS認証情報設定
export AWS_ACCESS_KEY_ID="AKIAxxxxxxxxxxxxxxxx"
export AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Route53でワイルドカード証明書取得
acme.sh --issue -d example.com -d "*.example.com" --dns dns_aws
その他DNSプロバイダーの対応
acme.sh は多数の DNS API に対応しています。以下は例です(実運用では公式の dnsapi スクリプト名と必要な環境変数を必ず確認してください)。
# Google Cloud DNS(例)
export GCE_Project="your-project-id"
export GCE_Domain="example.com"
acme.sh --issue -d example.com --dns dns_gce
# さくらインターネット(例)
export SAKURA_ACCESS_TOKEN="your-token"
acme.sh --issue -d example.com --dns dns_sakura
# お名前.com(例)
export Onamae_User="your-username"
export Onamae_Pass="your-password"
acme.sh --issue -d example.com --dns dns_onamae
ワイルドカード証明書の取得
ワイルドカード(*.example.com)証明書は、サブドメインが増える運用で非常に便利です。注意点として、Let’s Encrypt でワイルドカードを取るにはDNS-01 が必須です(http-01/standaloneでは取得できません)。
ワイルドカード証明書の発行
# ワイルドカード証明書の取得(DNS-01必須)
acme.sh --issue -d example.com -d "*.example.com" --dns dns_cf
# ネストしたサブドメインを追加したい場合の例
acme.sh --issue \
-d example.com \
-d "*.example.com" \
-d "*.app.example.com" \
-d "*.api.example.com" \
--dns dns_cf
証明書のインストール
証明書は「発行しただけ」では使えません。Webサーバーが参照する場所に配置し、更新時に reload されるようにします。–install-cert により、更新後に自動で配置・reload まで実行できます。
# Nginx用の証明書インストール
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/example.com.key \
--fullchain-file /etc/nginx/ssl/example.com.pem \
--reloadcmd "nginx -t && systemctl reload nginx"
# Apache用の証明書インストール
acme.sh --install-cert -d example.com \
--cert-file /etc/apache2/ssl/example.com.crt \
--key-file /etc/apache2/ssl/example.com.key \
--fullchain-file /etc/apache2/ssl/example.com.pem \
--reloadcmd "apachectl configtest && systemctl reload apache2"
複数ドメインの一括管理
複数の独立ドメインを運用している場合は、スクリプト化して発行・配置・リロードまで自動化すると安全です。以下は例です(環境変数・権限・パスは必ず実環境に合わせてください)。
#!/bin/bash
# bulk_ssl_issue.sh
set -eu
DOMAINS=(
"example1.com"
"example2.com"
"example3.com"
)
for domain in "${DOMAINS[@]}"; do
echo "Processing SSL certificate for ${domain} ..."
# 証明書発行(DNS-01)
acme.sh --issue -d "${domain}" -d "*.${domain}" --dns dns_cf
# 証明書インストール
acme.sh --install-cert -d "${domain}" \
--key-file "/etc/ssl/private/${domain}.key" \
--fullchain-file "/etc/ssl/certs/${domain}.pem" \
--reloadcmd "nginx -t && systemctl reload nginx"
if [ $? -eq 0 ]; then
echo "Success: ${domain}"
else
echo "Failed: ${domain}"
fi
# APIレート制限対策
sleep 5
done
自動更新の設定
Let’s Encrypt の証明書は短い有効期間のため、更新は自動化が前提です。acme.sh は –cron を定期実行するのが基本で、期限が近い証明書だけを更新します。短い周期(毎日など)で実行しても、更新不要なら何もしないため安全です。
cron設定による自動更新
cron は簡単ですが、ユーザー・パス・権限を間違えると更新に失敗しやすいので、acme.sh の home を明示し、ログも残す設計が安全です。
# crontab の編集
crontab -e
# 毎日 02:17 に更新チェック(例:分を固定にせず、環境により分は分散推奨)
17 2 * * * "/home/user/.acme.sh/acme.sh" --cron --home "/home/user/.acme.sh" >> /var/log/acme_renew.log 2>&1
systemd タイマーによる自動更新
systemd の方がログ管理や実行状態の把握がしやすく、サーバー運用ではおすすめです。以下は最小構成例です(パスは環境に合わせてください)。
# /etc/systemd/system/acme-renewal.service
[Unit]
Description=Renew Let's Encrypt certificates (acme.sh)
After=network-online.target
[Service]
Type=oneshot
ExecStart=/home/user/.acme.sh/acme.sh --cron --home /home/user/.acme.sh
User=root
# /etc/systemd/system/acme-renewal.timer
[Unit]
Description=Daily renewal check for acme.sh
Requires=acme-renewal.service
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
# 有効化
sudo systemctl daemon-reload
sudo systemctl enable acme-renewal.timer
sudo systemctl start acme-renewal.timer
sudo systemctl status acme-renewal.timer
更新状況の監視
更新が失敗しても「すぐには気づけない」ことが一番危険です。以下は openssl を使って残日数を確認し、一定日数以下なら通知する例です(通知先は必要に応じて差し替えてください)。
#!/bin/bash
# ssl_monitor.sh
set -eu
DOMAINS=(
"example.com"
"api.example.com"
"www.example.com"
)
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
WARNING_DAYS=14
send_alert() {
local domain="$1"
local message="$2"
curl -sS -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"${message}\"}" \
"${WEBHOOK_URL}" >/dev/null
}
check_ssl_expiry() {
local domain="$1"
local expiry_date
local expiry_ts
local now_ts
local days_left
expiry_date=$(echo | openssl s_client -servername "${domain}" -connect "${domain}:443" 2>/dev/null \
| openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2 || true)
if [ -z "${expiry_date}" ]; then
send_alert "${domain}" "SSL証明書の確認に失敗しました: ${domain}"
return
fi
expiry_ts=$(date -d "${expiry_date}" +%s)
now_ts=$(date +%s)
days_left=$(( (expiry_ts - now_ts) / 86400 ))
if [ "${days_left}" -le "${WARNING_DAYS}" ]; then
send_alert "${domain}" "SSL証明書の期限が近づいています: ${domain}(残り ${days_left} 日)"
fi
}
for domain in "${DOMAINS[@]}"; do
check_ssl_expiry "${domain}"
done
WebサーバーでのSSL設定
証明書を取得しても、Webサーバー側で正しく参照していないと HTTPS になりません。以下は Nginx / Apache の代表的な設定例です。ファイルパス(key / fullchain)は、先ほどの –install-cert で指定したパスと一致させてください。
Nginx設定例
# /etc/nginx/sites-available/example.com
server {
listen 80;
server_name example.com *.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com *.example.com;
ssl_certificate /etc/nginx/ssl/example.com.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
location / {
root /var/www/html;
index index.html index.htm;
}
}
Apache設定例
# /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias *.example.com
Redirect permanent / https://example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
ServerAlias *.example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/example.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/example.com.key
SSLCertificateChainFile /etc/apache2/ssl/example.com.pem
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header set X-Frame-Options DENY
Header set X-Content-Type-Options nosniff
</VirtualHost>
トラブルシューティング
よくあるエラーと対処法
acme.sh / Let’s Encrypt 周りで多いのは、DNS 伝播、API権限、ポート競合、そして更新タスクの実行ユーザー・パス不一致です。まずは「どの方式で検証しているか」を確認し、方式ごとのチェックを行います。
# DNS-01 の TXT レコード確認
dig TXT _acme-challenge.example.com
# http-01 の場合:.well-known が到達できるか
curl -I http://example.com/.well-known/acme-challenge/test
# 更新の手動実行(強制更新)
acme.sh --renew -d example.com --force
# 削除と再発行(慎重に)
acme.sh --remove -d example.com
acme.sh --issue -d example.com --dns dns_cf
ログ確認とデバッグ
「なぜ失敗しているか」はログに出ます。cron/systemd 実行時は PATH が違うことも多いので、実行したユーザーとacme.sh の homeも含めて確認してください。
# acme.sh のログ確認(例)
tail -f ~/.acme.sh/acme.sh.log
# デバッグ(出力を増やす)
acme.sh --issue -d example.com --dns dns_cf --debug 2
# 証明書ファイルの中身確認
openssl x509 -in ~/.acme.sh/example.com/example.com.cer -text -noout
# SSL接続テスト
openssl s_client -connect example.com:443 -servername example.com
証明書の復旧手順
更新が失敗して期限が切れそうな場合、最優先は「現行証明書のバックアップ」→「再発行」→「配置」→「Webサーバーの設定テストとリロード」です。以下は一連の流れをまとめた例です。
#!/bin/bash
# ssl_recovery.sh
set -eu
DOMAIN="example.com"
BACKUP_DIR="/backup/ssl"
LOG_FILE="/var/log/ssl_recovery.log"
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" | tee -a "$LOG_FILE"
}
backup_current_cert() {
local ts
ts=$(date +%Y%m%d_%H%M%S)
log_message "現在の証明書をバックアップ中: ${ts}"
mkdir -p "${BACKUP_DIR}/${ts}"
cp -r ~/.acme.sh/"${DOMAIN}"/ "${BACKUP_DIR}/${ts}/" || true
}
reissue_certificate() {
log_message "証明書の再取得を開始"
acme.sh --remove -d "${DOMAIN}" || true
if acme.sh --issue -d "${DOMAIN}" -d "*.${DOMAIN}" --dns dns_cf; then
log_message "証明書取得成功"
return 0
fi
log_message "証明書取得失敗"
return 1
}
install_certificate() {
log_message "証明書のインストール中"
acme.sh --install-cert -d "${DOMAIN}" \
--key-file /etc/nginx/ssl/"${DOMAIN}".key \
--fullchain-file /etc/nginx/ssl/"${DOMAIN}".pem \
--reloadcmd "nginx -t && systemctl reload nginx"
}
notify() {
local message="$1"
curl -sS -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"${message}\"}" \
"${WEBHOOK_URL}" >/dev/null || true
}
main() {
log_message "SSL証明書復旧処理を開始: ${DOMAIN}"
backup_current_cert
if reissue_certificate && install_certificate; then
log_message "SSL証明書復旧完了"
notify "SSL証明書の復旧が完了しました: ${DOMAIN}"
exit 0
else
log_message "SSL証明書復旧失敗"
notify "SSL証明書の復旧に失敗しました: ${DOMAIN}"
exit 1
fi
}
main "$@"
セキュリティ強化
OCSP Staplingの設定
OCSP Stapling を有効化すると、証明書失効情報の確認をサーバー側で補助でき、クライアントの負荷や接続遅延を減らせることがあります。環境により効果は異なるため、まずは設定→検証の順で導入してください。
# Nginx でのOCSP Stapling(例)
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/example.com.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
}
Certificate Transparency監視
CT(Certificate Transparency)ログを監視すると、自ドメイン名で「見覚えのない証明書」が発行されていないかを早期検知できます。以下は簡易スクリプト例です(jq が必要です)。
#!/bin/bash
# ct_monitor.sh
set -eu
DOMAIN="example.com"
CT_API="https://crt.sh/?q=%25.${DOMAIN}&output=json"
KNOWN_CERTS_FILE="/tmp/known_certs_${DOMAIN//./_}.txt"
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
send_alert() {
local message="$1"
curl -sS -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"${message}\"}" \
"${WEBHOOK_URL}" >/dev/null
}
new_certs=$(curl -s "${CT_API}" | jq -r '.[].id' | sort -n | uniq)
if [ ! -f "${KNOWN_CERTS_FILE}" ]; then
echo "${new_certs}" > "${KNOWN_CERTS_FILE}"
exit 0
fi
unknown=$(comm -13 "${KNOWN_CERTS_FILE}" <(echo "${new_certs}") || true)
if [ -n "${unknown}" ]; then
count=$(echo "${unknown}" | wc -l | tr -d ' ')
send_alert "新しいSSL証明書が検出されました: ${DOMAIN}(${count} 件)"
echo "${new_certs}" > "${KNOWN_CERTS_FILE}"
fi
SSL設定の品質チェック
設定変更のたびに、TLSバージョンやチェーンが壊れていないかを機械的にチェックできると安全です。外部サービスのAPIを使う場合は、API制限・利用規約・情報送信(対象ドメイン)に注意してください。
パフォーマンス最適化
SSL設定の最適化
TLS の最適化は「速さ」だけでなく「互換性」も絡みます。まずは TLSv1.2/1.3 を有効にし、HTTP/2 を併用し、問題が出ない範囲でチューニングしてください。以下は設定例です(環境により調整が必要です)。
# 例:Nginx の TLS まわり(環境により要調整)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_buffer_size 4k;
証明書チェーンの最適化
「中間証明書が足りない」「fullchain ではなく cert だけを設定している」などは、環境によって接続エラーや警告の原因になります。基本は fullchain を参照する設定にして、openssl で実際のチェーンを確認してください。
# サーバーが返す証明書の確認
openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer
よくある質問(FAQ)
Q. ワイルドカード証明書の更新でエラーが発生します
A. DNS-01 の API 権限、環境変数が cron/systemd 実行時に読めているか、TXT の伝播待ち時間を確認してください。Cloudflare の場合は API トークン方式(最小権限)に切り替えると管理が楽になることがあります。
Q. 複数のサブドメインで別々の証明書が必要ですか?
A. ワイルドカード証明書(*.example.com)を使えば、多くの場合は1枚で複数サブドメインをカバーできます。ただし、別ドメイン(example.net など)は別証明書が必要です。
Q. 証明書の更新に失敗した場合の対処法は?
A. まずログ(~/.acme.sh/acme.sh.log や systemd journal)を確認し、DNS設定・API認証・レート制限・Webサーバーの reload 失敗(nginx -t など)を切り分けます。緊急時は「復旧手順」スクリプトの流れ(バックアップ→再発行→配置→テスト→reload)で復旧します。
おすすめサーバー環境
SSL証明書の運用は「自動更新が動くこと」と「DNS設定やリロードが安全にできること」が重要です。安定稼働、バックアップ、監視などを含めて、運用しやすい環境を選んでください:
高可用性VPS
- ConoHa VPS:自動バックアップでSSL設定も安全
- mixhost:Let’s Encrypt標準対応
専用サーバー
- KAGOYA マネージド専用サーバー:24時間365日監視でSSL管理も安心
これらのサービスは、SSL証明書の自動更新に必要な安定稼働、DNS設定の柔軟性、セキュリティ対策を提供し、信頼性の高いWebサービス運営を支援します。

