<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-01-04T22:34:58+00:00</updated><id>/feed.xml</id><entry><title type="html">Grapevine</title><link href="/2025/01/04/grapevine.html" rel="alternate" type="text/html" title="Grapevine" /><published>2025-01-04T00:00:00+00:00</published><updated>2025-01-04T00:00:00+00:00</updated><id>/2025/01/04/grapevine</id><content type="html" xml:base="/2025/01/04/grapevine.html"><![CDATA[<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/fV-OU2A2AYg?si=vrlTJQcEs1j1m7-h" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>]]></content><author><name></name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Homelab Ssl</title><link href="/2025/01/02/homelab-ssl.html" rel="alternate" type="text/html" title="Homelab Ssl" /><published>2025-01-02T00:00:00+00:00</published><updated>2025-01-02T00:00:00+00:00</updated><id>/2025/01/02/homelab-ssl</id><content type="html" xml:base="/2025/01/02/homelab-ssl.html"><![CDATA[<p>I’ve always liked playing around with web stuff, and I’m also getting into self-hosting services strictly on my private network. I’ve got a bit of a funky setup that helps me do that. Let’s say I want to deploy a notes app onto a server I call <code class="language-plaintext highlighter-rouge">tombombadil</code>.</p>

<ul>
  <li><strong>Server DNS.</strong> I run a DNS on my network, which is configured for all clients via DHCP. For this server, I’ll create an A record to resolve <code class="language-plaintext highlighter-rouge">tombombadil.home.arpa -&gt; 192.168.0.100</code>.</li>
  <li><strong>Ports per service.</strong> Deploy a service on <code class="language-plaintext highlighter-rouge">tombombadil</code> via Docker, exposing the port it exposes as <code class="language-plaintext highlighter-rouge">42024</code>. But who wants to remember all those ports? I’d rather have friendly names, especially in a browser.</li>
  <li><strong>Service DNS.</strong> Configure DNS CNAME records for each service: <code class="language-plaintext highlighter-rouge">notes.home.arpa -&gt; tombombadil.home.arpa</code>.</li>
  <li><strong>Reverse proxy.</strong> Configure nginx on <code class="language-plaintext highlighter-rouge">tombombadil</code> to reverse proxy, e.g., <code class="language-plaintext highlighter-rouge">notes.home.arpa:80 -&gt; localhost:42024</code>.</li>
</ul>

<p>This is all well and good, except that I can only access with HTTP, not HTTPS. That would prevent the hosted service from using fancy features like service workers, web bluetooth, or even accessing the clipboard. The solution would be to configure nginx to use an appropriate SSL certificate, and there are plenty of references for how to do that if you have a certificate. I’m documenting here how to get a good certificate.</p>

<p>There are three main options:</p>
<ol>
  <li>Get a “real” certificate. I don’t want to do that, because my services are not going to be on the Internet. No one needs to trust my certificate but me.</li>
  <li>Self-signed certificates. There are limitations to self-signed certificates, and a self-signed certificate is only trusted if it is manually trusted on each device each time it changes.</li>
  <li>Create a root certificate, and use it to sign the SSL certificate. This means that updating the SSL certificate does not mean it needs to be newly trusted on every device. Root certificates can have a much longer expiration time (e.g., 25 years).</li>
</ol>

<p>For my use case above, if only <code class="language-plaintext highlighter-rouge">tombombadil</code> runs a reverse proxy, then I only need one SSL certificate. However, Chrome will not trust an SSL certificate for <code class="language-plaintext highlighter-rouge">*.home.arpa</code>, so each service will need to be individually named in the certificate. (Could I use a wildcard for something like <code class="language-plaintext highlighter-rouge">*.c.home.arpa</code>? Not sure, but I want to avoid the typing…) In that case, the third option seems like the right one for me.</p>

<p>To generate an appropriate root certificate:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Private key
openssl genrsa -out MyHomeCA.key 4096
# Root certificate
openssl req -x509 -new -nodes -key MyHomeCA.key -sha256 -days 3650 \
  -out MyHomeCA.pem \
  -subj "/CN=My Home Root CA/O=Home Lab/C=US"
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">MyHomeCA.pem</code> is the file you’ll want to add to your trusted root certificates. Note that Windows doesn’t recognize the <code class="language-plaintext highlighter-rouge">.pem</code> extension, but if you select it anyway then Windows will accept it.</p>

<p>Here’s the script I used to generate a signed SSL cert; this is what you configure nginx to use.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CA_KEY="MyHomeCA.key"
CA_CERT="MyHomeCA.pem"

# "canonical" host listed first
HOSTS=(tombombadil adminer git links notes paste)

printf -v SAN_LIST 'DNS:%s.home.arpa,' "${HOSTS[@]}"
SAN_LIST=${SAN_LIST%,}

openssl x509 -req \
  -in &lt;( openssl req -new -nodes -newkey rsa:2048 \
           -keyout homearpa.key \
           -subj "/CN=${HOSTS[0]}.home.arpa"
   ) \
  -CA "$CA_CERT" -CAkey "$CA_KEY" -CAcreateserial \
  -out homearpa.crt -days 398 -sha256 \
  -extfile &lt;(cat &lt;&lt;EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = $SAN_LIST
EOF
)
</code></pre></div></div>

<p>If I weren’t using a CA, the openssl command could have been simpler:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout homearpa.key -out homearpa.crt -subj "/CN=${HOSTS[0]}.home.arpa" \
  -addext "subjectAltName=${names%,}"
</code></pre></div></div>]]></content><author><name></name></author><category term="homelab" /><category term="linux" /><category term="ssl" /><category term="https" /><category term="selfhosting" /><summary type="html"><![CDATA[I’ve always liked playing around with web stuff, and I’m also getting into self-hosting services strictly on my private network. I’ve got a bit of a funky setup that helps me do that. Let’s say I want to deploy a notes app onto a server I call tombombadil.]]></summary></entry><entry><title type="html">Beginnings</title><link href="/2022/01/05/beginnings.html" rel="alternate" type="text/html" title="Beginnings" /><published>2022-01-05T00:00:00+00:00</published><updated>2022-01-05T00:00:00+00:00</updated><id>/2022/01/05/beginnings</id><content type="html" xml:base="/2022/01/05/beginnings.html"><![CDATA[<p>I want to write down the things that I’m thinking about and doing.  I’m looking
to do it in a low-friction way, so that I can do it for all little interesting
things that I happen to come across or do.  It’s mainly for my own reference (a
bit of an external brain), but any readers can gain whatever benefit they deem
appropriate. :)</p>

<p>I hope that I’ll get to post something most days – as I go about my usual
business, it’s a rare day that I don’t encounter <em>something</em> unfamiliar or
interesting.  I’m on vacation today, so maybe you’d imagine that I’d have
nothing to share.</p>

<p>HOWEVER! :)</p>

<p>In my efforts to get <code class="language-plaintext highlighter-rouge">jekyll</code> running on my Chromebook, I did need and look up
some handy <code class="language-plaintext highlighter-rouge">apt</code> commands.  I had found these (or their <code class="language-plaintext highlighter-rouge">apt-get</code>, <code class="language-plaintext highlighter-rouge">apt-cache</code>,
<code class="language-plaintext highlighter-rouge">apt-query</code> counterparts) some years ago, but I ahd to find them again.  Here’s
a summary:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">apt list --installed</code> shows all installed packages.  I had done some funny
things with ruby, and wanted a clean start.</li>
  <li><code class="language-plaintext highlighter-rouge">apt autoremove</code> removes all packages that are deemed “autoremovable” (meaning
they weren’t installed explicitly, and neither were any of their reverse
dependencies.)  For example, say you issued <code class="language-plaintext highlighter-rouge">apt install jekyll</code> and later
issued <code class="language-plaintext highlighter-rouge">apt remove jekyll</code>.  There are probably a number of other packages
(e.g., <code class="language-plaintext highlighter-rouge">ruby</code> itself) which were automatically installed and still present.
<code class="language-plaintext highlighter-rouge">apt autoremove</code> will get rid of those.</li>
  <li><code class="language-plaintext highlighter-rouge">dpkg -S</code> searches for the package that provides a file.</li>
  <li><code class="language-plaintext highlighter-rouge">dpkg -L</code> lists the files in a package.</li>
</ul>]]></content><author><name></name></author><category term="apt" /><category term="linux" /><category term="jekyll" /><summary type="html"><![CDATA[I want to write down the things that I’m thinking about and doing. I’m looking to do it in a low-friction way, so that I can do it for all little interesting things that I happen to come across or do. It’s mainly for my own reference (a bit of an external brain), but any readers can gain whatever benefit they deem appropriate. :)]]></summary></entry></feed>