<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>LEGO  |  takeHo（たけほ）のへなちょこ台帳</title>
	<atom:link href="https://blog.takeho.com/tag/lego/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.takeho.com</link>
	<description>いわゆる自由帳ってところです。</description>
	<lastBuildDate>Tue, 11 Nov 2025 07:01:23 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6</generator>

<image>
	<url>https://blog.takeho.com/wp-content/uploads/2024/08/icon-150x150.png</url>
	<title>LEGO  |  takeHo（たけほ）のへなちょこ台帳</title>
	<link>https://blog.takeho.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>ACMEクライアント「lego」でSSL証明書を自動発行・更新するまでの完全解説</title>
		<link>https://blog.takeho.com/complete-guide-to-automating-ssl-certificate-issuance-and-renewal-with-acme-client-lego/</link>
					<comments>https://blog.takeho.com/complete-guide-to-automating-ssl-certificate-issuance-and-renewal-with-acme-client-lego/#respond</comments>
		
		<dc:creator><![CDATA[たけほ]]></dc:creator>
		<pubDate>Tue, 11 Nov 2025 11:05:00 +0000</pubDate>
				<category><![CDATA[セキュリティ]]></category>
		<category><![CDATA[未分類]]></category>
		<category><![CDATA[ACME]]></category>
		<category><![CDATA[LEGO]]></category>
		<guid isPermaLink="false">https://blog.takeho.com/?p=1416</guid>

					<description><![CDATA[目次 手動更新の限界を超えるACMEとlegoの関係を理解するlegoのインストールアカウント登録と初回設定ドメイン検証（Challenge）の仕組みnginxへの反映設定自動更新の仕組みDNS-01方式の利点と落とし穴 [&#8230;]]]></description>
										<content:encoded><![CDATA[

  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2"><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">手動更新の限界を超える</a></li><li><a href="#toc2" tabindex="0">ACMEとlegoの関係を理解する</a></li><li><a href="#toc3" tabindex="0">legoのインストール</a></li><li><a href="#toc4" tabindex="0">アカウント登録と初回設定</a></li><li><a href="#toc5" tabindex="0">ドメイン検証（Challenge）の仕組み</a></li><li><a href="#toc6" tabindex="0">nginxへの反映設定</a></li><li><a href="#toc7" tabindex="0">自動更新の仕組み</a></li><li><a href="#toc8" tabindex="0">DNS-01方式の利点と落とし穴</a></li><li><a href="#toc9" tabindex="0">複数ドメイン・ワイルドカード対応</a></li><li><a href="#toc10" tabindex="0">docker-composeを使ったlego運用</a></li><li><a href="#toc11" tabindex="0">ACMEの裏側で起きていること</a></li><li><a href="#toc12" tabindex="0">47日時代を見据えたlegoの活用</a></li><li><a href="#toc13" tabindex="0">自動化は「信頼の継続」である</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">手動更新の限界を超える</span></h2>



<p>ウェブサイト運用者にとって、SSL/TLS証明書の更新は「気を抜くと致命的な停止を招く」作業の代表格だ。数年前まで、証明書の有効期限は最長825日だったため、1～2年に一度更新すれば十分だった。しかし2020年以降、証明書の有効期限は398日に短縮され、さらに2026年以降は200日、2027年には100日、2029年には47日と、わずか数週間単位での更新が求められる時代がやってくる。そんな環境で人手の運用を続けるのはもはや現実的ではなく、<strong>自動化</strong>が生き残る唯一の道となる。</p>



<p>自動化の中心にあるのが「ACME（Automatic Certificate Management Environment）」という仕組みだ。ACMEはIETFのRFC 8555で標準化されたプロトコルであり、認証局（CA）とウェブサーバの間で自動的に証明書を要求・発行・更新するための通信規約である。このACMEのクライアント実装は多数存在するが、その中でも特に軽量で柔軟、そして運用スクリプトに組み込みやすいのが「<strong>lego</strong>」である。</p>



<p>legoはGolangで書かれたコマンドラインACMEクライアントであり、Let’s EncryptやSectigo、ZeroSSL、さらにはFujiSSL ACMEにも対応できる。小規模サイトでも、複数ドメインを抱える企業環境でも使いやすく、Dockerやsystemd環境での運用にも向いている。本稿では、このlegoを使い、example.comという仮想ドメインを題材に、SSL証明書の自動発行から反映、自動更新までを構築していく。</p>



<h2 class="wp-block-heading"><span id="toc2">ACMEとlegoの関係を理解する</span></h2>



<p>ACMEは、証明書発行に必要なやり取りをHTTP APIとして自動化するためのプロトコルである。証明書を発行するには、認証局が申請者が本当にそのドメインを所有しているかを確認する必要がある。従来はCSR（証明書署名要求）を作り、メールやファイルアップロードなどで手動認証をしていたが、ACMEではクライアントが自動的に認証局へ接続し、ドメイン検証（Challenge）を完了させ、署名済み証明書を受け取るまでを一貫して実施する。legoはこのACMEクライアントの一種で、Goで書かれた実装として高い評価を受けている。Goで書かれているため、バイナリひとつで動作し、依存関係をほとんど持たない。つまり、コンテナ環境、軽量Linux、クラウドVMなどあらゆる環境で導入できる。</p>



<p>legoが対応しているCAはLet’s Encryptが有名だが、<code>--server</code>オプションで任意のACMEエンドポイントを指定できるため、SectigoやFujiSSLのACMEエンドポイントを使うことも可能である。これにより、特定の商用証明書（有料DV/OV/EV）でも同じ仕組みで自動更新を実現できる。</p>



<h2 class="wp-block-heading"><span id="toc3">legoのインストール</span></h2>



<p>ここではUbuntu 22.04環境を例にする。Go言語の環境がなくても、legoは単一バイナリで提供されているため、wgetまたはcurlで入手できる。以下はバイナリ直接インストールの例である。</p>



<pre class="wp-block-code"><code>sudo mkdir -p /usr/local/bin
sudo curl -s https://api.github.com/repos/go-acme/lego/releases/latest | grep browser_download_url | grep linux_amd64 | cut -d '"' -f 4 | wget -i -
sudo tar -xzf lego_v*.tar.gz
sudo mv lego /usr/local/bin/
lego --version</code></pre>



<p>これでlegoコマンドが使用可能になる。バージョンが表示されれば成功だ。もしコンテナ環境やCI/CDで運用する場合は、Docker Hubにも<code>goacme/lego</code>という公式イメージが用意されているため、<code>docker run --rm goacme/lego --version</code>で確認できる。</p>



<h2 class="wp-block-heading"><span id="toc4">アカウント登録と初回設定</span></h2>



<p>ACMEサーバと通信するには、まずlegoが使用するアカウントを作成する必要がある。ACMEサーバはEメールアドレスをアカウント識別子として使用し、秘密鍵で署名することでそのアカウントを認証する。初回登録時にはACMEの規約（Terms of Service）への同意が求められる。以下が最初の登録コマンド例である。</p>



<pre class="wp-block-code"><code>sudo lego --email "admin@example.com" --domains "example.com" --server "https://acme-v02.api.letsencrypt.org/directory" register</code></pre>



<p>上記コマンドにより、legoは<code>~/.lego/accounts</code>ディレクトリに秘密鍵とアカウントデータを保存する。登録後、このアカウントを使って証明書の要求や更新が行われる。もしFujiSSL ACMEを使う場合は、<code>--server</code>にそのエンドポイントを指定すれば同じ手順で登録可能である。</p>



<h2 class="wp-block-heading"><span id="toc5">ドメイン検証（Challenge）の仕組み</span></h2>



<p>ACMEの認証方式はHTTP-01とDNS-01の2種類が主流である。HTTP-01はWebサーバ上に特定ファイルを配置してアクセス検証を行う方法で、シンプルだがポート80が外部からアクセス可能でなければならない。一方DNS-01は、ドメインのTXTレコードを発行して認証局がDNS経由で所有確認を行う方式で、CDN配下やWAF環境、非公開サーバでも対応できる。legoはこのどちらにも対応しており、DNSプロバイダごとのAPIクレデンシャルを設定すれば完全自動化できる。</p>



<p>例として、example.comをRoute53で管理している場合を考える。legoは<code>AWS_ACCESS_KEY_ID</code>と<code>AWS_SECRET_ACCESS_KEY</code>を環境変数に設定すれば自動でDNSレコードを作成・削除してくれる。</p>



<pre class="wp-block-code"><code>export AWS_ACCESS_KEY_ID="XXXXXXXXXXXXXXXX"
export AWS_SECRET_ACCESS_KEY="YYYYYYYYYYYYYYYY"
sudo lego --email "admin@example.com" --domains "example.com" --dns "route53" run</code></pre>



<p>このコマンドを実行すると、legoはDNSレコードを作成し、ACMEサーバに挑戦を通知し、検証が完了すると証明書を発行する。発行後は<code>/etc/lego/certificates/example.com.crt</code>と<code>example.com.key</code>などが生成される。これをWebサーバ（nginxやApache）に反映すればHTTPS化が完了する。</p>



<h2 class="wp-block-heading"><span id="toc6">nginxへの反映設定</span></h2>



<p>nginxを使う場合、<code>/etc/nginx/conf.d/example.com.conf</code>などの設定ファイルでSSL証明書のパスを指定する。</p>



<pre class="wp-block-code"><code>server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate     /etc/lego/certificates/example.com.crt;
    ssl_certificate_key /etc/lego/certificates/example.com.key;
    location / {
        root /var/www/html;
        index index.html;
    }
}</code></pre>



<p>反映後、<code>sudo nginx -t &amp;&amp; sudo systemctl reload nginx</code>を実行すれば証明書が読み込まれる。この時点で<a href="https://example.com">https://example.com</a> にアクセスすれば、ブラウザの鍵マークが表示され、SSL通信が確立されているはずだ。</p>



<h2 class="wp-block-heading"><span id="toc7">自動更新の仕組み</span></h2>



<p>ACMEクライアントの真価は、証明書の期限を監視し、自動で更新できる点にある。legoの場合、<code>renew</code>サブコマンドを使えば手動更新できるが、systemdのtimerやcronに組み込むことで完全自動化が可能になる。</p>



<p>たとえばsystemdでの設定例を示そう。まず<code>/etc/systemd/system/lego-renew.service</code>を作成する。</p>



<pre class="wp-block-code"><code>&#91;Unit]
Description=Renew SSL certificates using lego
After=network.target

&#91;Service]
Type=oneshot
ExecStart=/usr/local/bin/lego --email admin@example.com --domains example.com --dns route53 --server https://acme-v02.api.letsencrypt.org/directory renew --days 30
ExecStartPost=/bin/systemctl reload nginx</code></pre>



<p>次に、タイマーを作成する。<code>/etc/systemd/system/lego-renew.timer</code>に以下を記述する。</p>



<pre class="wp-block-code"><code>&#91;Unit]
Description=Run lego renew daily

&#91;Timer]
OnCalendar=daily
Persistent=true

&#91;Install]
WantedBy=timers.target</code></pre>



<p><code>sudo systemctl enable --now lego-renew.timer</code>を実行すれば、毎日自動的に更新チェックが走り、残日数が30日未満であれば証明書を再取得してnginxをリロードする。これで「手動更新」という作業は完全に消滅する。systemctl list-timersで実行状況を確認できる。</p>



<h2 class="wp-block-heading"><span id="toc8">DNS-01方式の利点と落とし穴</span></h2>



<p>DNS方式は自動化に最適だが、API権限設定を誤るとセキュリティリスクにもなる。AWSのようなクラウドDNSならIAMポリシーを最小権限化すること、オンプレDNSなら更新スクリプトにトークンを直書きしないことが重要である。legoは主要DNSプロバイダ（Cloudflare、Google DNS、Route53、ConoHa、さくら、など）に対応している。環境変数のセットで完結する設計は安全かつ効率的だ。</p>



<p>HTTP方式を選ぶ場合は、<code>.well-known/acme-challenge/</code>ディレクトリを公開し、nginx設定に<code>location /.well-known/acme-challenge/ { root /var/www/html; }</code>を追加する必要がある。legoは内部的にそこへトークンファイルを配置するが、Dockerなどで運用している場合はボリューム共有を忘れないことが肝要だ。</p>



<h2 class="wp-block-heading"><span id="toc9">複数ドメイン・ワイルドカード対応</span></h2>



<p>legoはワイルドカード証明書（例：<code>*.example.com</code>）もDNS-01方式で発行できる。HTTP方式では不可能なので注意が必要だ。複数ドメインを同時に指定する場合は、<code>--domains</code>を複数書けば良い。</p>



<pre class="wp-block-code"><code>sudo lego --email admin@example.com --domains example.com --domains www.example.com --dns route53 run</code></pre>



<p>このようにすれば、両方のFQDNをSANに含んだ1枚の証明書が生成される。ワイルドカードを含める場合は、<code>--domains "*.example.com" --domains example.com</code>とする。生成された証明書はnginxやロードバランサのどちらでも使える。</p>



<h2 class="wp-block-heading"><span id="toc10">docker-composeを使ったlego運用</span></h2>



<p>Docker環境でlegoを実行する場合、cronと同等のスケジュールをDockerコンテナ内で動かすのはやや面倒だが、composeとvolumeを活用すれば整然と構成できる。</p>



<p>以下はdocker-compose.ymlの例である。</p>



<pre class="wp-block-code"><code>version: '3'

services:
  lego:
    image: goacme/lego:latest
    container_name: lego
    environment:
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
    volumes:
      - ./lego-data:/lego
      - /etc/nginx/certs:/etc/lego/certificates
    command: >
      --email admin@example.com
      --domains example.com
      --dns route53
      --server https://acme-v02.api.letsencrypt.org/directory
      renew --days 30</code></pre>



<p>このコンテナを日次で起動するようcronまたはホストのsystemd timerを設定すれば、同様に自動更新が実現する。更新後はnginxを再読み込みするジョブをhookとして連携させる。</p>



<h2 class="wp-block-heading"><span id="toc11">ACMEの裏側で起きていること</span></h2>



<p>legoを使うと数行のコマンドで証明書が得られるが、その背後では複雑な通信が行われている。ACMEサーバとの間では、JSON Web Signature (JWS) によって署名付きリクエストが交わされ、チャレンジ・オブジェクトを受け取り、検証を経て最終的にSigned Certificateをダウンロードする。legoはこの一連のフローを全自動で行い、<code>.lego/</code>ディレクトリ以下に履歴を管理する。renew時にはこのキャッシュを利用して同一アカウントでの再検証をスキップするため、毎回の登録や鍵生成は不要だ。</p>



<p>legoの特徴は、Goのシンプルな構造により、ログが読みやすい点でもある。<code>--debug</code>オプションを付けるとHTTPリクエストが詳細に出力され、ACMEサーバのレスポンスも確認できる。障害時のトラブルシュートにはこのログが重要であり、検証失敗やDNS伝播の遅延も可視化できる。</p>



<h2 class="wp-block-heading"><span id="toc12">47日時代を見据えたlegoの活用</span></h2>



<p>2029年以降、有効期限47日の証明書が主流となると、もはや人手の介入を前提にした運用は成立しない。legoをはじめとするACMEクライアントは、その未来に備えた最も実用的な選択肢だ。重要なのは、「自動発行ができる」という一点ではなく、「<strong>障害を起こさずに回り続ける仕組みを確立できる</strong>」ことである。systemdやDockerのタイマーによる定期実行、DNS-APIの権限設計、証明書ファイルのローテーション整備、そして再読み込み時の無停止反映が揃ってこそ、自動化は完成する。</p>



<p>多くの運用現場では、更新そのものよりも「反映の自動化」に課題が残る。たとえばロードバランサー配下のnginxが多数存在する環境では、更新完了後に各ノードへファイルを配布し、同時にサービスを再読み込みする仕組みが必要だ。この点でもlegoはシンプルで、証明書出力先を任意指定できるため、Ansibleやrsync、S3同期などと組み合わせて容易にスケールできる。</p>



<p>47日のサイクルは極端に短いが、legoを中心とした自動化基盤を一度作り上げれば、もはや手動更新という概念自体が消える。短命証明書の世界では、自動化の精度こそが信頼の証となる。</p>



<h2 class="wp-block-heading"><span id="toc13">自動化は「信頼の継続」である</span></h2>



<p>ACMEとlegoの登場は、証明書更新という作業を単なる定例業務から「システム的信頼維持のプロセス」へと変えた。かつてはSSL証明書を一度導入すれば数年間放置できたが、これからは運用設計そのものが継続的改善を要求される。legoはその過程を支える小さくも強力なツールであり、Goで書かれた堅牢性、DNS・HTTP両対応の柔軟性、systemdとの親和性によって、あらゆる環境に適用できる。</p>



<p>example.comという小さなドメインを例にしても、その構築過程に含まれるのは、ACMEの通信理解、DNS管理、サーバ設定、自動化設計、セキュリティ権限設計といった、運用エンジニアに必要なすべての要素である。legoを使いこなすことは、単にSSL更新を楽にすることではなく、「信頼の継続を自動化する文化」を築くことに他ならない。</p>



<p>証明書有効期限の短縮は運用者にとって試練のように見えるが、実はインフラを近代化する絶好のチャンスだ。legoを導入すれば、あなたのexample.comは今日から永続的に信頼され続ける。煩雑な更新作業は過去の遺物となり、未来の運用は静かに、確実に回り続ける。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.takeho.com/complete-guide-to-automating-ssl-certificate-issuance-and-renewal-with-acme-client-lego/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
