<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Letsencrypt on Chanyeol Dev</title>
    <link>https://chanyeols.com/tags/letsencrypt/</link>
    <description>Recent content in Letsencrypt on Chanyeol Dev</description>
    <generator>Hugo</generator>
    <language>ko-kr</language>
    <lastBuildDate>Tue, 31 Mar 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://chanyeols.com/tags/letsencrypt/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>노트북으로 홈서버 구축하기 - certbot --expand로 SSL 서브도메인 추가하기 (9편)</title>
      <link>https://chanyeols.com/posts/part-09-ssl/</link>
      <pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://chanyeols.com/posts/part-09-ssl/</guid>
      <description>서비스가 늘어나면서 서브도메인이 추가될 때마다 SSL 인증서에 도메인을 추가해야 했다. certbot --expand 옵션으로 기존 인증서에 서브도메인을 추가하는 방법을 정리합니다.</description>
      <content:encoded><![CDATA[<h2 id="문제-상황">문제 상황</h2>
<p>처음 SSL 인증서를 발급할 때 메인 도메인만 포함해서 발급했다.</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>certbot certonly --nginx -d yourdomain.com
</span></span></code></pre></div><p>이후 서비스가 하나씩 늘어나면서 서브도메인이 추가됐는데, 브라우저에서 <code>photo.yourdomain.com</code>에 접속하면 아래 에러가 발생했다.</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-plain" data-lang="plain"><span style="display:flex;"><span>NET::ERR_CERT_COMMON_NAME_INVALID
</span></span><span style="display:flex;"><span>연결이 비공개로 설정되어 있지 않습니다.
</span></span></code></pre></div><p>인증서에 <code>photo.yourdomain.com</code>이 포함돼 있지 않아서 생기는 문제였다.</p>
<hr>
<h2 id="해결-expand-옵션">해결: &ndash;expand 옵션</h2>
<p>기존 인증서에 서브도메인을 추가할 때는 <code>--expand</code> 플래그를 써야 한다.</p>
<p><code>--expand</code> 없이 서브도메인을 추가하려고 하면 아래 에러가 난다.</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-plain" data-lang="plain"><span style="display:flex;"><span>Missing command line flag or config entry for this setting:
</span></span><span style="display:flex;"><span>You have an existing certificate that contains a portion of the domains you requested.
</span></span><span style="display:flex;"><span>It contains these names: yourdomain.com
</span></span><span style="display:flex;"><span>You requested these names for the new certificate: yourdomain.com, photo.yourdomain.com
</span></span><span style="display:flex;"><span>Do you want to expand and replace this existing certificate with the new certificate?
</span></span><span style="display:flex;"><span>(You can set this with the --expand flag)
</span></span></code></pre></div><p>certbot이 친절하게 <code>--expand</code> 쓰라고 안내해주긴 한다.</p>
<hr>
<h2 id="셸-스크립트로-관리">셸 스크립트로 관리</h2>
<p>서브도메인이 추가될 때마다 명령어를 직접 치는 건 번거롭다. 스크립트로 관리하면 나중에 도메인 하나 추가할 때 <code>-d</code> 줄만 늘리면 된다.</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#8b949e;font-weight:bold;font-style:italic">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#79c0ff">DOMAIN</span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">&#34;yourdomain.com&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#79c0ff">EMAIL</span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">&#34;your@email.com&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#79c0ff">SSL_DIR</span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">&#34;/ssl&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>certbot certonly --nginx <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  --non-interactive <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  --agree-tos <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  --expand <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  --email <span style="color:#79c0ff">$EMAIL</span> <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  -d <span style="color:#79c0ff">$DOMAIN</span> <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  -d photo.<span style="color:#79c0ff">$DOMAIN</span> <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  -d files.<span style="color:#79c0ff">$DOMAIN</span> <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  -d vault.<span style="color:#79c0ff">$DOMAIN</span> <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  --config-dir <span style="color:#79c0ff">$SSL_DIR</span> <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  --work-dir <span style="color:#79c0ff">$SSL_DIR</span>/work <span style="color:#79c0ff">\
</span></span></span><span style="display:flex;"><span>  --logs-dir <span style="color:#79c0ff">$SSL_DIR</span>/logs
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">if</span> <span style="color:#ff7b72;font-weight:bold">[</span> <span style="color:#79c0ff">$?</span> -ne <span style="color:#a5d6ff">0</span> <span style="color:#ff7b72;font-weight:bold">]</span>; <span style="color:#ff7b72">then</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#a5d6ff">&#34;인증서 발급 실패&#34;</span>
</span></span><span style="display:flex;"><span>    exit <span style="color:#a5d6ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#a5d6ff">&#34;인증서 발급 성공&#34;</span>
</span></span><span style="display:flex;"><span>nginx -t <span style="color:#ff7b72;font-weight:bold">&amp;&amp;</span> systemctl restart nginx
</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>옵션</th>
          <th>설명</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>--expand</code></td>
          <td>기존 인증서에 새 도메인 추가</td>
      </tr>
      <tr>
          <td><code>--non-interactive</code></td>
          <td>사용자 입력 없이 자동 실행</td>
      </tr>
      <tr>
          <td><code>--agree-tos</code></td>
          <td>서비스 약관 자동 동의</td>
      </tr>
      <tr>
          <td><code>-d</code></td>
          <td>인증서에 포함할 도메인 (여러 개 가능)</td>
      </tr>
  </tbody>
</table>
<p>새 서브도메인이 생길 때마다 <code>-d newservice.$DOMAIN \</code> 한 줄만 추가하고 스크립트를 실행하면 된다.</p>
<hr>
<h2 id="인증서-확인">인증서 확인</h2>
<p>발급 후 포함된 도메인 목록 확인:</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>certbot certificates --config-dir /ssl
</span></span></code></pre></div><p><img alt="certbot certificates 결과 - 서브도메인 목록 확인" loading="lazy" src="/images/homeserver-09-certbot-certificates.png"></p>
<p>인증서에 서브도메인이 모두 포함된 것을 확인할 수 있다. 브라우저에서 접속하면 자물쇠 아이콘을 클릭해서 인증서에 포함된 도메인 목록을 직접 확인할 수 있다.</p>
<p><img alt="브라우저 인증서 정보 - 서브도메인 포함 확인" loading="lazy" src="/images/homeserver-09-browser-cert.png"></p>
<hr>
<h2 id="자동-갱신-설정">자동 갱신 설정</h2>
<p>Let&rsquo;s Encrypt 인증서는 90일마다 갱신해야 한다. cron으로 자동화해뒀다.</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>crontab -e
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-plain" data-lang="plain"><span style="display:flex;"><span>0 3 1 */2 * certbot renew --config-dir /ssl --work-dir /ssl/work --logs-dir /ssl/logs &amp;&amp; nginx -s reload
</span></span></code></pre></div><p>60일마다 새벽 3시에 갱신 시도한다. 갱신 후 Nginx를 리로드해서 새 인증서를 바로 적용한다.</p>
<hr>
<h2 id="정리">정리</h2>
<ul>
<li>기존 인증서에 서브도메인 추가할 때는 반드시 <code>--expand</code> 플래그 사용</li>
<li>서브도메인 관리를 스크립트로 해두면 나중에 도메인 추가가 편하다</li>
<li>cron으로 자동 갱신 설정해두면 인증서 만료 걱정이 없다</li>
</ul>
<p>다음 편에서는 Immich PostgreSQL DB를 매일 새벽 자동으로 백업하는 스크립트를 만든다.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
