<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Letsencrypt on bramp.net</title>
    <link>https://blog.bramp.net/</link>
    <description>Recent content in Letsencrypt on bramp.net</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-GB</language>
    <lastBuildDate>Sun, 27 Dec 2020 09:14:22 -0800</lastBuildDate>
    <atom:link href="https://blog.bramp.net/tags/letsencrypt/" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Local HTTPS Server for development</title>
      <link>https://blog.bramp.net/post/2020/12/27/local-https-server-for-development/</link>
      <pubDate>Sun, 27 Dec 2020 09:14:22 -0800</pubDate>
      
      <guid>https://blog.bramp.net/post/2020/12/27/local-https-server-for-development/</guid>
      <description><p>I regularly do web development with the host localhost. Running a simple HTTP server to service my site. Recently I came across a problem where some of the newer web APIs (such as DeviceMotionEvent) do not work unless the site is served via SSL. So I went about setting up a local SSL server, and certificate.</p>
<p>Many of the <a href="https://matthewhoelter.com/2019/10/21/how-to-setup-https-on-your-local-development-environment-localhost-in-minutes.html">instructions out there</a> create a self-signed certificate, that you install to be trusted locally. I wanted my development server to be accessible from other devices on my network, and I didn&rsquo;t want the hassle of installing this self-signed cert. Instead I wanted a SSL certificate that uses a real/trusted CA.</p>
<p>Enter <a href="https://letsencrypt.org/">Let&rsquo;s Encrypt</a>, a free service to provide SSL certificates, providing you can prove you own the domain. To go about this, I did the following on my macbook:</p>
<h1 id="install-certbot-to-generate-the-cert">Install Certbot (to generate the cert)</h1>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew install certbot
</span></span></code></pre></div><p>There are a few ways to prove you own a domain, the HTTP based ones require a public web server. Since my development server is only on my local network, I&rsquo;m going to use a DNS based proof. Since I use Cloudflare for my DNS, I&rsquo;ll be using their plugin.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">pip3 install certbot-dns-cloudflare
</span></span></code></pre></div><h1 id="setup-the-domain-localbrampnet">Setup the domain (local.bramp.net)</h1>
<p>I use cloudflare to host the DNS for my domain, so I setup a new domain, local.bramp.net, that points to an internal IP address (192.168.0.123). This domain won&rsquo;t actually be used via the Internet, but will happily work for any devices on my local network.</p>
<figure><img src="/post/2020/12/27/local-https-server-for-development/setup-dns.png" width="720" height="208"><figcaption>
      <h4>Setup DNS record for local.bramp.net</h4>
    </figcaption>
</figure>

<p>You&rsquo;ll also need a <a href="https://support.cloudflare.com/hc/en-us/articles/200167836-Where-do-I-find-my-Cloudflare-API-key-">API key from Cloudflare</a>. They allow you to scope the key to only access this test domain. For example:</p>
<figure><img src="/post/2020/12/27/local-https-server-for-development/create-token.png" width="720" height="304"><figcaption>
      <h4>Create a API token</h4>
    </figcaption>
</figure>

<p>That will give you a token, that is a long string of letters and numbers.</p>
<h1 id="configure-certbot">Configure Certbot</h1>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Create a place to store your secrets, that only you can access</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mkdir ~/.secrets
</span></span><span class="line"><span class="cl">cat <span class="s">&lt;&lt;EOF &gt; ~/.secrets/cloudflare.ini
</span></span></span><span class="line"><span class="cl"><span class="s">dns_cloudflare_api_token = **your_key**
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">chmod <span class="m">0700</span> ~/.secrets/
</span></span><span class="line"><span class="cl">chmod <span class="m">0400</span> ~/.secrets/cloudflare.ini
</span></span></code></pre></div><h1 id="generate-the-certificate">Generate the Certificate</h1>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">certbot certonly <span class="se">\
</span></span></span><span class="line"><span class="cl">  --config-dir ~/.secrets/ <span class="se">\
</span></span></span><span class="line"><span class="cl">  --work-dir ~/.secrets/ <span class="se">\
</span></span></span><span class="line"><span class="cl">  --logs-dir ~/.secrets/ <span class="se">\
</span></span></span><span class="line"><span class="cl">  --dns-cloudflare <span class="se">\
</span></span></span><span class="line"><span class="cl">  --dns-cloudflare-credentials ~/.secrets/cloudflare.ini <span class="se">\
</span></span></span><span class="line"><span class="cl">  -d local.bramp.net
</span></span></code></pre></div><p>and voila:</p>
<pre tabindex="0"><code> - Congratulations! Your certificate and chain have been saved at:
   /Users/bramp/.secrets/live/local.bramp.net/fullchain.pem
   Your key file has been saved at:
   /Users/bramp/.secrets/live/local.bramp.net/privkey.pem
</code></pre><p>The <code>privkey.pem</code> is important to keep secret. Normally certbot runs as root, but here we run it as your user for convenience.</p>
<p>If you want this to automatically renew, just run to add a renewal that occurs twice daily at a random minute after 12pm and 12am.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># List your current crontab, and append certbot renewal</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">(</span>crontab -l <span class="p">;</span> <span class="nb">echo</span> <span class="s2">&#34;</span><span class="k">$((</span> RANDOM <span class="o">%</span> <span class="m">60</span> <span class="k">))</span><span class="s2"> 0,12 * * * </span><span class="k">$(</span>which certbot<span class="k">)</span><span class="s2"> renew -q --config-dir ~/.secrets/ --work-dir ~/.secrets/ --logs-dir ~/.secrets/&#34;</span><span class="o">)</span> <span class="p">|</span> crontab -
</span></span></code></pre></div><p>Or you can renew (all certificates) on demand with a simple:</p>
<pre tabindex="0"><code>certbot renew \
  --config-dir ~/.secrets/ \
  --work-dir ~/.secrets/ \
  --logs-dir ~/.secrets/
</code></pre><h1 id="install-a-simple-https-web-server">Install a simple HTTPS web server</h1>
<p>I use <a href="https://github.com/http-party/http-server">http-server</a>, &ldquo;a simple, zero-configuration command-line http server.&rdquo;. It supports many useful features, including SSL.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew install http-server
</span></span></code></pre></div><h1 id="running-the-https-web-server">Running the HTTPS web server</h1>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">http-server -S <span class="se">\
</span></span></span><span class="line"><span class="cl">  -C ~/.secrets/live/local.bramp.net/fullchain.pem <span class="se">\
</span></span></span><span class="line"><span class="cl">  -K ~/.secrets/live/local.bramp.net/privkey.pem
</span></span></code></pre></div><p>You may wish to alias this to something shorter, for example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nb">alias</span> <span class="nv">https</span><span class="o">=</span><span class="s2">&#34;http-server -S \
</span></span></span><span class="line"><span class="cl"><span class="s2">  -C ~/.secrets/live/local.bramp.net/fullchain.pem \
</span></span></span><span class="line"><span class="cl"><span class="s2">  -K ~/.secrets/live/local.bramp.net/privkey.pem&#34;</span>
</span></span></code></pre></div><p>Now you can run <code>https</code> from any directory and it&rsquo;ll be served over SSL.</p>
<h1 id="additional-reading">Additional Reading</h1>
<ul>
<li><a href="https://support.cloudflare.com/hc/en-us/articles/200167836-Where-do-I-find-my-Cloudflare-API-key-">Cloudflare - Managing API Tokens and Keys</a></li>
<li><a href="https://certbot.eff.org/lets-encrypt/osx-other">certbot instructions</a></li>
<li><a href="https://mangolassi.it/topic/18355/setup-letsencrypt-certbot-with-cloudflare-dns-authentication-ubuntu/2">Setup LetsEncrypt Certbot with CLoudFlare DNS authentication (Ubuntu)</a></li>
<li><a href="https://matthewhoelter.com/2019/10/21/how-to-setup-https-on-your-local-development-environment-localhost-in-minutes.html">How to setup HTTPS (SSL) on your local development environment (localhost) in minutes</a></li>
<li><a href="https://certbot-dns-cloudflare.readthedocs.io/en/stable/">certbot-dns-cloudflare’s documentation!</a></li>
</ul>
</description>
    </item>
    
    <item>
      <title>Certbot: Unexpected Error</title>
      <link>https://blog.bramp.net/post/2018/05/26/certbot-unexpected-error/</link>
      <pubDate>Sat, 26 May 2018 11:28:44 -0700</pubDate>
      
      <guid>https://blog.bramp.net/post/2018/05/26/certbot-unexpected-error/</guid>
      <description><p>I got a <a href="https://letsencrypt.org/docs/expiration-emails/">nice warning email</a> from <a href="https://letsencrypt.org/">Let&rsquo;s Encrypt</a> that my cert was going to expire soon, and hadn&rsquo;t been renewed. I found in  <code>/var/log/letsencrypt/letsencrypt.log</code> the following error:</p>
<pre tabindex="0"><code>Renewal configuration file /etc/letsencrypt/renewal/mydomain.bramp.net.conf (cert: mydomain.bramp.net) produced an unexpected error: &#39;Namespace&#39; object has no attribute &#39;dns_cloudflare_credentials&#39;. Skipping.
</code></pre><p>I manually ran certbot in dry-run mode and it worked fine:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ sudo certbot renew --dry-run
</span></span></code></pre></div><p>So this error only occurs when certbot is running as a cron job. Looking at <code>/etc/cron.d/certbot</code> I see the user runs as root, so I tried the <code>certbot renew --dry-run</code> again, but this time as the root user:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ sudo su
</span></span><span class="line"><span class="cl">root@:~$ sudo certbot renew --dry-run
</span></span></code></pre></div><p>and bam, the same error. This error somehow related to the <a href="https://certbot-dns-cloudflare.readthedocs.io/en/latest/">certbot-dns-cloudflare plugin</a>, which proves the ownership of the domain with a <a href="https://acme-python.readthedocs.io/en/latest/api/challenges.html#acme.challenges.DNS01">DNS01 challenge</a> via Cloudflare&rsquo;s DNS. I use this form of challenge, because the domain in question is internal and not available on the Internet.</p>
<p>I had forgotten how I installed the plugin, but searching Google, it seems to be via <code>pip3</code>. Clearly something was different between my root and normal user w/ sudo environments. So I did the following</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">$ sudo pip3 list <span class="p">|</span> grep certbot
</span></span><span class="line"><span class="cl">certbot <span class="o">(</span>0.23.0<span class="o">)</span>
</span></span><span class="line"><span class="cl">certbot-apache <span class="o">(</span>0.23.0<span class="o">)</span>
</span></span><span class="line"><span class="cl">certbot-dns-cloudflare <span class="o">(</span>0.24.0<span class="o">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">$ sudo su
</span></span><span class="line"><span class="cl">root@:~$ pip3 list <span class="p">|</span> grep certbot
</span></span><span class="line"><span class="cl">certbot <span class="o">(</span>0.23.0<span class="o">)</span>
</span></span><span class="line"><span class="cl">certbot-apache <span class="o">(</span>0.23.0<span class="o">)</span>
</span></span></code></pre></div><p>Aha, no certbot-dns-cloudflare when running as root. Clearly I hadn&rsquo;t installed this correctly. Running <code>pip3 install certbot-dns-cloudflare</code> as root fixed the problem, and voila, certbot correctly fetches new certs via a regular cron.</p>
</description>
    </item>
    
  </channel>
</rss>
