<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>invisiblethreat</title>
    <description></description>
    <link>https://invisiblethreat.ca/</link>
    <atom:link href="https://invisiblethreat.ca/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Thu, 19 Mar 2026 13:31:36 +0000</pubDate>
    <lastBuildDate>Thu, 19 Mar 2026 13:31:36 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Bypassing Synology&apos;s 32K NFS Block Size Limit with systemd</title>
        <description>&lt;p&gt;The Synology DSM GUI caps NFS read/write packet size at 32K. For a fileserver doing large sequential transfers — media files, backups, VM disk images — that’s leaving throughput on the table. The kernel supports up to 1MB block sizes, and the GUI limit is purely artificial.&lt;/p&gt;

&lt;p&gt;This post documents how to push past it on DSM 7, which uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; under the hood.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-the-setting-actually-controls&quot;&gt;What the setting actually controls&lt;/h2&gt;

&lt;p&gt;The NFS block size (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsize&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsize&lt;/code&gt;) determines how much data the client and server exchange in a single NFS operation. Larger blocks mean fewer round trips for the same transfer, which matters most for large sequential reads and writes over a local network.&lt;/p&gt;

&lt;p&gt;The server-side maximum is controlled by a kernel procfs entry:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/proc/fs/nfsd/max_block_size
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The DSM GUI writes a value into this at boot, but caps it at 32768 (32K). The kernel itself supports 1048576 (1MB).&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-you-cant-just-echo-a-value-at-boot&quot;&gt;Why you can’t just echo a value at boot&lt;/h2&gt;

&lt;p&gt;The obvious approach — write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1048576&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max_block_size&lt;/code&gt; at startup — hits two problems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem 1:&lt;/strong&gt; Once &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfsd&lt;/code&gt; threads are running, the file is locked:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# echo 1048576 &amp;gt; /proc/fs/nfsd/max_block_size
-ash: echo: write error: Device or resource busy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Problem 2:&lt;/strong&gt; Even if you write before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfsd&lt;/code&gt; starts, DSM’s NFS service resets the value during its own initialization. The kernel calculates a default block size based on available RAM when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpc.nfsd&lt;/code&gt; starts, and that write clobbers yours.&lt;/p&gt;

&lt;p&gt;The window you need is: &lt;strong&gt;after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/proc/fs/nfsd&lt;/code&gt; is mounted, but before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfsd&lt;/code&gt; threads spawn.&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;how-dsm-7-starts-nfs&quot;&gt;How DSM 7 starts NFS&lt;/h2&gt;

&lt;p&gt;DSM 7 uses systemd. The NFS startup sequence involves three units:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;proc-fs-nfsd.service   →   [your hook goes here]   →   nfs-server.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proc-fs-nfsd.service&lt;/code&gt; mounts the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfsd&lt;/code&gt; filesystem at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/proc/fs/nfsd&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfs-server.service&lt;/code&gt; calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/syno/lib/systemd/scripts/nfsd.sh start&lt;/code&gt;, which runs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpc.nfsd&lt;/code&gt; and spawns the kernel threads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfs-server.service&lt;/code&gt; runs, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max_block_size&lt;/code&gt; is locked. You need to write your value between these two units.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-fix&quot;&gt;The fix&lt;/h2&gt;

&lt;p&gt;Create a systemd drop-in unit that slots between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proc-fs-nfsd.service&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfs-server.service&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/systemd/system/nfs-blocksize.service &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;
[Unit]
Description=Set nfsd max_block_size before NFS server starts
After=proc-fs-nfsd.service
Before=nfs-server.service
Requires=proc-fs-nfsd.service

[Service]
Type=oneshot
ExecStart=/bin/sh -c &apos;echo 1048576 &amp;gt; /proc/fs/nfsd/max_block_size&apos;
RemainAfterExit=yes

[Install]
WantedBy=nfs-server.service
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Enable it:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;nfs-blocksize.service
systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verify the ordering was picked up:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl show nfs-server.service | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; after
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfs-blocksize.service&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;After=&lt;/code&gt; chain for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfs-server.service&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Reboot, then confirm:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/fs/nfsd/max_block_size
&lt;span class=&quot;c&quot;&gt;# 1048576&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;client-side&quot;&gt;Client side&lt;/h2&gt;

&lt;p&gt;The server-side change only sets the ceiling. Clients still need to request larger block sizes at mount time. On Linux clients, update &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fstab&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nas:/volume1/share  /mnt/nas  nfs  rsize=1048576,wsize=1048576,vers=4  0  0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or test before making it permanent:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mount &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; nfs &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1048576,wsize&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1048576,vers&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4 nas:/volume1/share /mnt/nas
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verify what was negotiated after mounting:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nfsstat &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;rsize
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;This survives reboots. The systemd unit is persistent.&lt;/li&gt;
  &lt;li&gt;DSM updates may overwrite files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib/systemd/system/&lt;/code&gt; but should leave &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/systemd/system/&lt;/code&gt; alone. If an update breaks it, just re-run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl enable nfs-blocksize.service &amp;amp;&amp;amp; systemctl daemon-reload&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;If you’re using NFSv4 exclusively (likely on a modern Linux-only homelab), you only need port &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2049/tcp&lt;/code&gt; open in your firewall. The additional ports required by NFSv3 (mountd, statd, lockd) are not needed.&lt;/li&gt;
  &lt;li&gt;The DS918+ ships with 4GB of RAM. The kernel’s default block size calculation targets 1MB on machines with that much memory, but DSM’s NFS init script overrides it. This fix restores what the kernel would have chosen anyway.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 18 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://invisiblethreat.ca/technology/2026/03/18/synology-nfs-blocksize/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/technology/2026/03/18/synology-nfs-blocksize/</guid>
        
        <category>synology</category>
        
        <category>nfs</category>
        
        
        <category>technology</category>
        
      </item>
    
      <item>
        <title>Something big/small/other is happening.</title>
        <description>&lt;h1 id=&quot;whats-coming&quot;&gt;What’s coming?&lt;/h1&gt;

&lt;p&gt;There’s a back and forth in technology on whether the current AI cycle is all
hype, or a true revolution that is just at the bottom of an exponential curve.
It seems that, like in so many things, a nuanced position is not a popular one.
I think that more than “back and forth” there are are actually three camps that
compose the current balance of the tech world: AI maximalists, AI doomers, and
AI doubters.&lt;/p&gt;

&lt;h2 id=&quot;the-perspectives-at-play&quot;&gt;The Perspectives at Play&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Maximalist view: &lt;a href=&quot;https://shumer.dev/something-big-is-happening&quot;&gt;Something Big is Happening&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Doubter view: &lt;a href=&quot;https://podcasts.apple.com/us/podcast/better-offline/id1730587238?i=1000749543323&quot;&gt;Better Offline: No, Something Big Isn’t Coming&lt;/a&gt;, Ed Zitron of “Where’s Your Ed At”&lt;/li&gt;
  &lt;li&gt;Doomer view: &lt;a href=&quot;https://www.theatlantic.com/technology/archive/2025/08/ai-doomers-chatbots-resurgence/683952/&quot;&gt;The AI Doomers Are Getting Doomier&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;It’s cool to hate on AI view: &lt;a href=&quot;https://x.com/johnpalmer/status/2021966462198460849&quot;&gt;Something Small is Happening&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-ai-maximalists&quot;&gt;The AI Maximalists&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is going to change everything forever.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The “maxi” is all in, all of the time. Maybe they were early, maybe not. Maybe
they missed out on other trends and want to be here first. They are true
believers in what the technology can do and won’t shut up about it.&lt;/p&gt;

&lt;h3 id=&quot;the-ai-doomers&quot;&gt;The AI Doomers&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;I hope they put us in the nice part of the human zoo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A negative-biased version of the “maxi” that believes in the potential, but sees
the outcomes in an almost exclusively negative light. It’s not clear to me if
this group thinks a lack of safety is the issue, or that it’s simply inevitable.&lt;/p&gt;

&lt;h3 id=&quot;the-ai-doubters&quot;&gt;The AI Doubters&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;It’s all hype just like the dot-com crash.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I will admit to finding this group the most frustrating and least informed. They
seem to relish mathematical tasks like counting the letter “r” in “strawberry”
and getting to a “look how stupid this thing is!” as quickly as possible.&lt;/p&gt;

&lt;h3 id=&quot;the-ai-hater-bonus&quot;&gt;The AI Hater (Bonus!)&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;I went offline before it was cool.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically a snotty vegan barista that judges you harshly for your life choices,
but for AI. This is something that I’m trying to engage less with(and be less of
a part of) as I age. I acknowledge that it exists as a perspective, but I just
don’t find it interesting and won’t devote time to it.&lt;/p&gt;

&lt;h2 id=&quot;where-im-atfor-now&quot;&gt;Where I’m At(for now)&lt;/h2&gt;

&lt;p&gt;Presuming that my opinion is worth the bits to get it to your screen, here’s
what I’m thinking about the personas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The maximalists are overselling, but not by large degree. Sure, Matt Shumer is
talking exclusively in a way that benefits himself, but that doesn’t make him
wrong. The failure to acknowledge the externalities is aggravating.  Timelines
are up for debate, but given my last several weeks, I think that I’m, reluctantly, in this camp.&lt;/li&gt;
  &lt;li&gt;The doomers love a good spiral. See the panic over Moltbook and the failure
how easy it was to manufacture a story out of the content there.&lt;/li&gt;
  &lt;li&gt;The doubters are judging fish on their ability to climb trees. I think that
they have largely formed opinions on older models, if they’ve tried them at all.
Some of the most ardent critics seem to have adopted “AI Luddite” personas when
models exponentially improving. I’m not sure what is to be gained by being
closed minded to the fact that every lab is trying to improve all of the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;things-im-keeping-in-mind&quot;&gt;Things I’m Keeping in Mind&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The models today are the worst they will ever be barring some training that
goes wrong. Expect improvements on an ongoing basis.&lt;/li&gt;
  &lt;li&gt;From my experience, using AI to get to discrete values is their best use.&lt;/li&gt;
  &lt;li&gt;Replit, as a business, has been replaced by models improving, and projects
like &lt;a href=&quot;https://github.github.com/spec-kit/&quot;&gt;Spec Kit&lt;/a&gt; in a matter of months.
Maybe I’m just late to this?&lt;/li&gt;
  &lt;li&gt;SaaS is in for a world of hurt- especially offerings full of bloat and
distractions. These are going to see the cost on a per seat basis drop. Buyers
are going to have huge amounts of leverage over pricing when they only use 1/3
of the features offered&lt;/li&gt;
  &lt;li&gt;Tired: putting AI in your product. Wired: enabling AI to interact with your
product. The value isn’t in summaries of your data within the platform it’s
housed in, but rather, combining it with disparate data easily. Trying to lock
folks in to a platform will only encourage them to attempt to exit more quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-ive-built&quot;&gt;What I’ve Built&lt;/h2&gt;

&lt;p&gt;In the last week, the things I’ve managed to build with minimal effort:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;App to ingest backup reports that were previously emails(and mostly
ignored)&lt;/li&gt;
  &lt;li&gt;App to replace Google’s BigQuery console.&lt;/li&gt;
  &lt;li&gt;App to map, pivot, and merge data from vastly different systems of record&lt;/li&gt;
  &lt;li&gt;App to speed read. Based on Rapid Serial Visual Presentation(RSVP).
Currently attaining 800 WPM on a consistent basis&lt;/li&gt;
  &lt;li&gt;App for home maintenance that can leverage check-ins triggered by NFC tags&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;going-forward&quot;&gt;Going Forward&lt;/h2&gt;

&lt;p&gt;I mostly agree with Shumer that pure coding is solved. Knowing the application
of techniques and understanding the problems that you’re trying to solve really
well is the most value you can have in the day-to-day. Reducing yourself to a
“spec engineer” feels like the best way to be replaced.&lt;/p&gt;

&lt;h4 id=&quot;posse-note&quot;&gt;POSSE Note&lt;/h4&gt;

&lt;p&gt;I own my own content. I subscribe to POSSE: Publish on Own Site, Syndicate
Everywhere. The original location of this content is
&lt;a href=&quot;https://invisiblethreat.ca&quot;&gt;invisiblethreat.ca&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 18 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://invisiblethreat.ca/technology/2026/02/18/something-something-is-happening/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/technology/2026/02/18/something-something-is-happening/</guid>
        
        <category>ai</category>
        
        <category>llm</category>
        
        <category>future</category>
        
        
        <category>technology</category>
        
      </item>
    
      <item>
        <title>Per-domain resolvers in macOS</title>
        <description>&lt;h1 id=&quot;macos-dns-and-you&quot;&gt;macOS, DNS, and you&lt;/h1&gt;

&lt;p&gt;First things first: I don’t fully understand the DNS resolution scheme that
Apple has dreamed up in macOS. Furthermore, I don’t really want to- I just want
things to work in a manner that let’s me get on with my life.&lt;/p&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;

&lt;p&gt;I run a fairly extensive home lab, with lots of projects and resources. I also
run the private DNS suffix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.lan&lt;/code&gt; to access all of these resources. I make
regular use of these resources for work. This comes into direct conflict with
our access control system for work. If I have the ACL software active, my
resolver address is replaced and I’m unable to access my lab via hostnames.&lt;/p&gt;

&lt;p&gt;However, this isn’t an outright block, I can still resolve things if I specify
the nameserver that I want to use. With this knowledge, I set out to fix access
to my internal hosts. It did not go well. Multiple calls with our ACL provider,
and lots of tampering with things in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/resolv.conf&lt;/code&gt; I was no further ahead.
Deploying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnsmasq&lt;/code&gt; via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew&lt;/code&gt; for conditional upstream DNS resolution suffered
from the same issues of being run over when the ACL software was active.&lt;/p&gt;

&lt;p&gt;I eventually stumbled across &lt;a href=&quot;https://medium.com/@jamieeduncan/i-recently-moved-to-a-macbook-for-my-primary-work-laptop-7c704dbaff59&quot;&gt;this article from 2019&lt;/a&gt; about this same thing. I’m not a huge fan of Medium, and the paywall model, so here’s the gist of the solution and a handy script to help you out!&lt;/p&gt;

&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;/h2&gt;

&lt;p&gt;The solution is available via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/resolver/&amp;lt;Private Namespace&amp;gt;&lt;/code&gt;. In my case,
my internal DNS is using the suffix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.lan&lt;/code&gt;. &lt;em&gt;Edit: this works for any arbitrary
domain or subdomain. You could employ the same solution for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.bar.com&lt;/code&gt; or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar.com&lt;/code&gt; and all requests that match the namespace will be routed to that
resolver.&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo mkdir -p /etc/resolver/lan

# 172.18.0.2 is my internal pihole instance, which has an upstream rule that
# points to my authoritative internal DNS server. There are some shell nuances
# about redirection that mean you need to actually either be root, or fully wrap
# the `echo` call in a subshell call to sudo.

echo &quot;nameserver 172.18.0.2&quot; &amp;gt;&amp;gt; /etc/resolver/lan
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To verify that you now have a private namespace resolver, use the following
command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scutil --dns

# ... many other results ...

resolver #10
  domain   : lan
  nameserver[0] : 172.18.0.2
  flags    : Request A records
  reach    : 0x00000002 (Reachable)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As an aside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dig&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host&lt;/code&gt; are using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/resolv.conf&lt;/code&gt; which makes
troubleshooting difficult. Make sure that you’re using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dscacheutil -q host -a
name&lt;/code&gt; instead.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# will use /etc/reslov.conf, which is contains the ACL resolver address
dig pihole.lan +short

# using the resolution chain from scutil --dns
dscacheutil -q host -a name pihole.lan
name: pihole.lan
ip_address: 172.18.0.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s it! It’s done!&lt;/p&gt;

&lt;h2 id=&quot;a-script&quot;&gt;A script&lt;/h2&gt;

&lt;p&gt;This script is the quickest path to a resolution(!). Enjoy!&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;RES_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/etc/resolver
&lt;span class=&quot;nv&quot;&gt;ZONE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;NS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Usage: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &amp;lt;zone&amp;gt; &amp;lt;nameserver IP address&amp;gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Don&apos;t clobber an existing configuration&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RES_PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;RESOLVER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$RES_PATH&lt;/span&gt;/&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;| &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{print $2}&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; already has a custom resolver at &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RES_PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; using &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RESOLVER&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# I forget if this exists in a clean install, so make sure it exists&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RES_PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$RES_PATH&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# make the file&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo touch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$RES_PATH&lt;/span&gt;/&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# this needs to be encapsulated because redirection is a shell function of the&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# current UID&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;echo &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;nameserver &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &amp;gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RES_PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# verify that things have worked&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;RESOLVER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$RES_PATH&lt;/span&gt;/&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;| &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{print $2}&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; now has a custom resolver at &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RES_PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; using &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$RESOLVER&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
scutil &lt;span class=&quot;nt&quot;&gt;--dns&lt;/span&gt; |grep &lt;span class=&quot;nt&quot;&gt;-B1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 12 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://invisiblethreat.ca/technology/2025/04/12/macos-resolvers/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/technology/2025/04/12/macos-resolvers/</guid>
        
        <category>macos</category>
        
        <category>technology</category>
        
        <category>dns</category>
        
        
        <category>technology</category>
        
      </item>
    
      <item>
        <title>Exim, ZDI, and the casualties</title>
        <description>&lt;h1 id=&quot;three-months-later--a-reflection&quot;&gt;Three months later- a reflection&lt;/h1&gt;

&lt;p&gt;I didn’t want to immediately post about the mess that was the “Exim VS ZDI” to
give myself some time to see if I still felt the same way given the initial mess
that was created. I still do feel the same way:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Everybody lost.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;zdi-lost&quot;&gt;ZDI Lost&lt;/h2&gt;

&lt;p&gt;ZDI is supposed to be a professional disclosure organization. Nothing in the
mailing list logs shows professionalism. There are most likely private
communications that will never see the light of day, but again, this is their
business. They are owned, now, by TrendMicro, and most likely have competing
interests of being a disclosure organization, and providing value of some sort
to Trend.&lt;/p&gt;

&lt;h2 id=&quot;security-people-lost&quot;&gt;Security People Lost&lt;/h2&gt;

&lt;p&gt;A late week disclosure on vulnerabilities with incomplete information is a
terrible place to exist. Many questions and few answers just sets people’s time
on fire. Thanks for nothing, ZDI. Given the extremely protracted timelines,
would it have killed ZDI to hold this until the following Monday or Tuesday? All
it does is raise questions around their motivations and the desired end results
of “helping” VS “getting press”.&lt;/p&gt;

&lt;h2 id=&quot;the-exim-project-lost&quot;&gt;The Exim Project Lost&lt;/h2&gt;

&lt;p&gt;I feel like the Exim project, and their users, were the biggest losers out of
all parties. The project was cavalier with the userbase’s trust in the project
and ability to interact with ZDI. They failed to find a way to move forward with
ZDI, at the expense of the reputation of the project’s reputation and the trust
from the users. In reality, if cPanel was not distributing Exim, there would be
far less fanfare around this software.&lt;/p&gt;
</description>
        <pubDate>Tue, 02 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://invisiblethreat.ca/general/2024/01/02/exim/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/general/2024/01/02/exim/</guid>
        
        <category>disclosure</category>
        
        <category>zdi</category>
        
        <category>exim</category>
        
        <category>users</category>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>AI Regulation</title>
        <description>&lt;h1 id=&quot;ai-regulation&quot;&gt;AI Regulation&lt;/h1&gt;

&lt;p&gt;All of the advancements in generative AI has led to somewhat of a natural
consequence: governments want to get involved. Yay. Of these, the US government
is the one that is able to exert the most influence due to the concentration of
tech giants within its sphere of influence.&lt;/p&gt;

&lt;p&gt;Of note, Sam Altman at OpenAI seems to be in favour of this regulation. My
feeling is that he is attempting be a participant in creating a regulatory moat
for keeping new entrants out of the market by creating barriers for any would-be
competitors.&lt;/p&gt;

&lt;p&gt;The coziness between the largest AI companies and the US government feels very
wrong to me in multiple ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;influence and pressure flowing from government to companies&lt;/li&gt;
  &lt;li&gt;internal safeties and biases propagating forward within companies creates a feedback loop of priors that will diminish future probabilistic outcomes.&lt;/li&gt;
  &lt;li&gt;combining the above two items can create paternalistic outcomes that don’t
serve citizens, but rather the interests of those in power&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;americanterism-and-a-failure-to-understand-the-internet&quot;&gt;Americanterism and a failure to understand the internet&lt;/h2&gt;

&lt;p&gt;In hearing all of the talks of regulation from the US government, it really
makes me wonder if anyone within it understands how AI models are trained,
distributed or otherwise used. During that last sentence, I downloaded a model
with 7 billion parameters that runs on my laptop. It’s mine now, forever.&lt;/p&gt;

&lt;p&gt;I’m Canadian, and who is the US government to tell me how act or what to do with
this technology? If I was to build something, would I have to submit to the US
government to do business in the US? Will US-based companies flee to less
restrictive locales? Will this stifle new entrants to the market, with eventual
lessening of competition, and ultimately, innovation?&lt;/p&gt;

&lt;h2 id=&quot;chaotic-actors&quot;&gt;Chaotic actors&lt;/h2&gt;

&lt;p&gt;Did you know that information classified as “top secret” by the US government
that’s leaked to the public creates a real problem for people that hold
clearances? Even though the information is “public” they’ve never been cleared
to view it and it can jeopardize their clearance renewal if they do so.&lt;/p&gt;

&lt;p&gt;Let’s now apply a similar treatment to AI in the US, and any regulatory
framework that companies must reside within. If a foreign entity(company,
country, whatever…) trains or gives a way a &lt;em&gt;vastly&lt;/em&gt; superior model that
companies in the US are forbidden from using, what then? Do they get left
behind? Do they leave the US? Does the government abandon their policies and
tactics(I think we know that this is a non-starter)?&lt;/p&gt;

&lt;p&gt;I can understand with the interest in being seen to be doing something, but at
the same time, I really don’t know how this doesn’t promote incentives around
being headquartered in an innovation-friendly country.&lt;/p&gt;

&lt;h2 id=&quot;information-wants-to-be-free&quot;&gt;Information wants to be free&lt;/h2&gt;

&lt;p&gt;I’m not sure if this is the answer, but I feel that it’s at least &lt;em&gt;something&lt;/em&gt;:
as many open source models as possible. A ubiquity of technology that becomes
anti-fragile to the whims of any one regulator and the ability to easily switch
out models and carry on as you were. Don’t code to a company’s or model’s API,
use an abstraction framework that allows flexibility. This allow for flexibility
and the ability to protect your work, and in the case of paid products, prevent
a hostage situation.&lt;/p&gt;

&lt;p&gt;The pace of innovation is often at odds with regulation, and in the case of AI,
the lack of consideration of second and third order consequences will have an
impact of some magnitude. The current pandering to hysteria around AI is
short-sighted and will lead to outcomes, some predictable, and some not, that
could be avoided.&lt;/p&gt;

</description>
        <pubDate>Tue, 02 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://invisiblethreat.ca/general/2024/01/02/ai-regulation/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/general/2024/01/02/ai-regulation/</guid>
        
        <category>ai</category>
        
        <category>regulation</category>
        
        <category>americentrism</category>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Infinity hurts my head</title>
        <description>&lt;h1 id=&quot;infinity-makes-me-question-precision-and-measurement&quot;&gt;Infinity makes me question precision and measurement&lt;/h1&gt;

&lt;p&gt;There is something deeply unsettling to be about the concept of infinity. I’ll
just talk about it in the concept of numbers, not in terms of space, because
that’s its own thing, even if it’s related.&lt;/p&gt;

&lt;p&gt;When conducting interviews for junior candidates, I often give a Body Mass
Index(BMI) challenge. It’s not a particularly hard thing to program, nor is BMI
that great of a measure health for various reasons, but sometimes it leads into
an interesting place.&lt;/p&gt;

&lt;h2 id=&quot;the-bmi-range&quot;&gt;The BMI Range&lt;/h2&gt;

&lt;p&gt;The BMI range is as follows:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;less than 18.5 is underweight&lt;/li&gt;
  &lt;li&gt;18.5 to 25 is ideal&lt;/li&gt;
  &lt;li&gt;greater than 25 and less than 30 is overweight&lt;/li&gt;
  &lt;li&gt;30 and over is overweight
… mostly. You see, in most of the scales, the values published use tenths of a
number, and they have gaps. For instance, this is what the CDC publishes:&lt;/li&gt;
  &lt;li&gt;less than 18.5 is underweight&lt;/li&gt;
  &lt;li&gt;18.5 to 24.9 is ideal&lt;/li&gt;
  &lt;li&gt;25 to 29.9 is overweight&lt;/li&gt;
  &lt;li&gt;30 and over is obese
This looks harmless and reasonable, right? Let me now mess with you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-gaps&quot;&gt;The gaps&lt;/h2&gt;

&lt;p&gt;So, here it is, while you can say that the distance between 24.9 and 25 is one
tenth numerically, in terms of the values that can take place between those two
points is infinite. There is infinite precision to be measured between these
points, even if we lack the instruments to make the measurements. If you have
24.9, with the 9s repeating millions of times, there’s still an infinite range
or precision between that last 9 and the next whole number of 25.&lt;/p&gt;

&lt;p&gt;That’s it. In the physical world, it seems that everything is an approximation,
because actually being able to measure to infinite precision is impossible.&lt;/p&gt;
</description>
        <pubDate>Sat, 19 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://invisiblethreat.ca/general/2022/11/19/infinity/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/general/2022/11/19/infinity/</guid>
        
        <category>learning</category>
        
        <category>infinity</category>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>2021- The year in review</title>
        <description>&lt;h1 id=&quot;another-year-in-the-books&quot;&gt;Another year in the books…&lt;/h1&gt;

&lt;p&gt;There are a few things that I was able to accomplish in 2021 that I’d like to
talk about, and probably a few others that should be mentioned. The things that
I’ll choose to omit are most likely gross failures to even get a project
started, so it may get kicked ahead to 2022. Maybe.&lt;/p&gt;

&lt;h2 id=&quot;my-internal-conflict&quot;&gt;My Internal Conflict&lt;/h2&gt;

&lt;p&gt;There are not enough hours in the day for me to learn all the things that are
interesting to me. I also find that as a specialize more and more at work, the
more that I want to branch out into other technical realms in order to be more
well rounded. It serves two purposes: I love learning, and I also love to be
self-sufficient. During the year I did find a few places where I could align
some of my technical learning goals with work goals, which was nice. Some of the
things that I wasn’t able to justify for work-purposes are getting rolled over
to 2022, but I haven’t decided on an approach just yet.&lt;/p&gt;

&lt;p&gt;My biggest challenge to learning new technical skills outside of work is the
allocation of time. Spending extra hours in front of a computer after I’m done
work for the day is done can sometimes be a real drain, and I don’t feel like
I’m unplugging. It also interferes with other things that are just as important
to me, like jiu jitsu and mountain biking. I don’t know how to balance it all.
I’ve also found that if I attempt to do technical learning first thing in the
morning, that it quickly leads to me starting work early, which has yet to
result in me walking away from the computer any earlier at the end of the day.
Maybe I have boundary issues? Working on a distributed team that has a -5h to
+4h spread means that there’s always something going on, or someone to chat with
about something that we can improve. Maybe time management should be at the top
of my list for 2022.&lt;/p&gt;

&lt;h3 id=&quot;start-stop-continue-but-in-a-different-order&quot;&gt;Start, Stop, Continue, but in a different order.&lt;/h3&gt;

&lt;p&gt;I find the “start, stop, continue” feedback process the most actionable sort of
way to think about moving forward, but I’ve never applied it to personal
development, so here we go.&lt;/p&gt;

&lt;h3 id=&quot;stop&quot;&gt;Stop&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Using R. I started using R in 2017 when I needed programmatic graphs and it
  fit the bill. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ggplot2&lt;/code&gt; can make some beautiful graphs. My main issue is
  that the &lt;em&gt;I&lt;/em&gt; find the language completely arcane. Between the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tidyverse&lt;/code&gt;,
  CRAN, and the standard language itself, there’s just too much variety. Too
  many calling conventions, arbitrary naming and syntax conventions , and and
  general lack of uniformity. RStudio is nice, but I find a lot of the tooling
  weak, and the error messages terse enough that I’d never attempt to code
  without access to the internet.&lt;/li&gt;
  &lt;li&gt;Complaining about JavaScript(on the front-end). I haven’t denied the utility
  of JS on the front-end, but I have willfully ignored it as something that
  I’m not willing to spend time learning. I maintain that NodeJS, while
  enormously popular, is a mistake.&lt;/li&gt;
  &lt;li&gt;Saying “yes” to all requests. The ability to be versatile doesn’t always mean
  that you should actually be versatile. The more things that you take on, the
  more obligations and interruptions you accumulate. This can become
  antithetical to deep work and learning.&lt;/li&gt;
  &lt;li&gt;Arguing on technical solutions. If I’m not the person doing the work, all I
  can do is offer my perspective and supporting evidence. If I’m not the one
  implementing, this needs to get to “disagree on the implementation, but
  agree that it’s the path forward”.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;continue&quot;&gt;Continue&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Improving at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt;, more specifically &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim&lt;/code&gt;. I overhauled my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.vimrc&lt;/code&gt; to be
  an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init.vim&lt;/code&gt; in the last few months as part of the exercise and have really
  enjoyed taking the time to attempt to master some of the core features. I’ve
  been using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt; for 15 years, and was still using arrows, and many other
  rookie methods. Leaning motions has been great, and I’m finally starting to
  really unlock the power of the “editing first” principles. I’ve been doing
  Python development for smaller projects exclusively in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt; and I hope to
  move my Go development into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt; as well.&lt;/li&gt;
  &lt;li&gt;Learning/relearning Python. I dabbled in Python 2.5ish days and it really felt
  like a more structured version of shell(this is an oversimplification, but
  that was my impression at the time). Watching the train-wreck of the 2 to 3
  migration(and the Perl 5 to 6… um, whatever that has turned in to) let me
  put it on the shelf as a “I’ll get back to this at some point” item. I knew
  that web frameworks had popped up, and that the push to Python 3 had picked
  up steam. In coming back in the last year, thing like type checking, and
  overall tooling seem to have really come along. The potential removal of GIL
  is also an exciting possibility moving forward.&lt;/li&gt;
  &lt;li&gt;Learning more abstractions in Go. I’ve spent a bit of time learning
  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interface{}&lt;/code&gt;, however, I don’t really find myself using it in projects.
  Generics landing in Go 1.18 mean that there will be more abstractions
  showing up in code bases, and knowing what’s going on will be very useful.&lt;/li&gt;
  &lt;li&gt;Improving SQL. The last year has had me write some queries that went beyond my
  initial comfort, and some were certainly killed by the DB engine for being
  abusive. Refining queries, and really understanding sub-queries and making
  results sets smaller earlier via constraints seems like an easy win. I’ve
  also had to translate queries to other engines that don’t support all of the
  features that I’m used to which has been interesting. Knowing when something
  is specific to an engine will also be important going forward.&lt;/li&gt;
  &lt;li&gt;Knowledge synthesis. I started very deliberate leaning for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt; and the
  results have been quite good. I plan to expand the technique into other
  technical realms.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;start&quot;&gt;Start&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Learn some JavaScript. This is only for front-end work(see above comments for
  thoughts on Node). It seems that Next.js is quite popular, and when I ask
  front end devs what framework they’d pick if they were able to start over
  today, and Next.js is almost always the answer. I’ve been doing all sorts of
  work from data generation/collection, to APIs to expose the information, but
  I’ve never done a modern front end to display the results. My last serious
  front end used PHP and tables for layout.&lt;/li&gt;
  &lt;li&gt;Get comfortable with pointers in C. I understand C just fine until folks break
  out multiple levels of indirection with pointers. It’s no wonder that
  dangling pointers and “use after free” bugs are a thing. Sadly it’s outside
  of my current skills to be effective in that area. Also, it’s a good bridge
  to being able to better understand assembly languages and other outputs from
  reverse engineering.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;onward&quot;&gt;Onward&lt;/h2&gt;

&lt;p&gt;Taking the time to reflect on my technical goals for the upcoming year should
help me direct my focus. It also gives me a reference for what I thought was
important to me if these things fail to materialize. Capturing information is
the first step, reviewing and reflecting on it at a later date may actually be
the much more powerful part of the equation.&lt;/p&gt;
</description>
        <pubDate>Sun, 26 Dec 2021 00:00:00 +0000</pubDate>
        <link>https://invisiblethreat.ca/general/2021/12/26/year-in-review/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/general/2021/12/26/year-in-review/</guid>
        
        <category>learning</category>
        
        <category>tools</category>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>VSCode, GOOS, and you.</title>
        <description>&lt;h2 id=&quot;update-2021-12-26&quot;&gt;&lt;em&gt;Update: 2021-12-26&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;After being off on a Python adventure for a few months, I had to refactor some
Go code. All of the issues came back. I was incensed. I deleted everything
related to VSCode. Rather than use any of my old configuration, I started from
scratch. I installed all my plugins by hand, and reconfigured &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;settings.json&lt;/code&gt; by
hand. It &lt;em&gt;seems&lt;/em&gt; that there were incompatible settings in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;settings.json&lt;/code&gt;
that caused &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go pls&lt;/code&gt; and the Go plugin in VSCode to spiral out of control. I
haven’t had time to fully debug the exact issue, but everything now works as
expected. I generally dislike “scorched earth” debugging, as it often stops when
things “work” without getting all the way to root cause analysis. In this case,
“working” is good enough and I’ve moved on with my life.&lt;/p&gt;

&lt;h2 id=&quot;vscode--gopls-friends-or-foes&quot;&gt;VSCode &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gopls&lt;/code&gt;: friends or foes?&lt;/h2&gt;

&lt;p&gt;I’ve had issues with VSCode and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gopls&lt;/code&gt; on macOS since it’s been a thing. I was
really excited about it at first, and then the problems started coming:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;unresponsiveness&lt;/li&gt;
  &lt;li&gt;no imports&lt;/li&gt;
  &lt;li&gt;no code hints&lt;/li&gt;
  &lt;li&gt;no IntelliSense&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This generally made the language server not worth using to me, and I reverted to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;goimports&lt;/code&gt; and friends. I had the feeling of always knowing that a day would
come when the language server would be foisted upon me and I’d have limited
options of what to do about it.&lt;/p&gt;

&lt;p&gt;When leaving my last job I took the time to drag my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;settings.json&lt;/code&gt; along with
me, just in case, but I tried a fresh install. Things just worked and life was
great. I didn’t give another thought to it, because I had no need to. This all
changed when I found out that I’d be targeting Windows on a project- everything
went sideways.&lt;/p&gt;

&lt;p&gt;The error was opaque and I was back to the above list of issues, minus the
unresponsiveness because most things just weren’t loading. Even the smallest
thing, like not knowing how many return values a function had ground my coding
to a halt. I then truly realized how heavily I depended on the Go toolchain to
help me get to workable code.&lt;/p&gt;

&lt;p&gt;Does this scream “I have a cross-compile issue when starting the language
server?”. It sure didn’t to me.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/code-error.png&quot; alt=&quot;terse error message&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That message didn’t return useful search results, so the debugging continued. On
a whim I tried &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GOOS=windows code .&lt;/code&gt; and everything was magical. Things just
worked.&lt;/p&gt;

&lt;p&gt;So it seems when dealing with build constrained packages, there needs to be
something that happens when the above situation occurs.&lt;/p&gt;

&lt;p&gt;I ended up testing workspace settings and all was revealed. It feels like there
should be a much more friendly way of getting to this solution through some sort
of detection, but I ended up scripting a solution instead.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; .vscode &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.vscode directory exists- refusing to overwrite.&quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; .vscode

&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;EOT&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt; &amp;gt; .vscode/settings.json
{
    &quot;go.toolsEnvVars&quot;: {
        &quot;GOOS&quot;: &quot;windows&quot;
    }
}
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOT
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Tue, 21 Sep 2021 22:47:19 +0000</pubDate>
        <link>https://invisiblethreat.ca/books/2021/09/21/vscode-goos/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/books/2021/09/21/vscode-goos/</guid>
        
        <category>golang</category>
        
        <category>goos</category>
        
        <category>vscode</category>
        
        <category>windows</category>
        
        <category>darwin</category>
        
        
        <category>books</category>
        
      </item>
    
      <item>
        <title>Limitless Book review</title>
        <description>&lt;h2 id=&quot;tldr-910&quot;&gt;tl;dr 9/10&lt;/h2&gt;

&lt;p&gt;If you pick up a single skill from the book it will improve your learning
forever. The return on investment is hard ignore.&lt;/p&gt;

&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;

&lt;p&gt;Limitless is a book on learning by Jim Kwik. It breaks down the components of
learning, and the different modes and strategies of the components. Since
learning is multi-faceted, it makes sense that there are improvements in several
areas that can be leveraged in concert to show fairly large(multiplicative)
result.&lt;/p&gt;

&lt;p&gt;My initial interest was around being able to enhance my reading abilities, as I
seem to have accumulated a rather large backlog of books around my home- each
now lingering in various states of completion, some with, shamefully, spines the
still creak and crack when opened. This had turned into guilt. I’ve been
building a list of new books that I want to read(ending of the gold standard,
physical performance, data science), but the unread pile has been haunting me.
Reading a book that would help me to learn, retain, and potentially help me read
faster seemed like the right investment before tackling the backlog.&lt;/p&gt;

&lt;h2 id=&quot;some-notes-on-notes&quot;&gt;Some notes on Notes&lt;/h2&gt;

&lt;p&gt;Note-taking is covered in this book, but I think it(and lots of other folks)
somewhat miss something that I feel is really foundational to
non-fiction/learning note-taking: &lt;em&gt;take your notes on a sheet of paper&lt;/em&gt;.  This
has several benefits in my opinion:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Brevity. You write what matters and can refer to the text if you need to expand.&lt;/li&gt;
  &lt;li&gt;Underlining/highlighting goes away. I remember seeing textbooks in university that looks like someone had soaked them with a glow stick. It also reduces “capture fatigue” of deciding when to start and stop. It also is influenced by/influences brevity&lt;/li&gt;
  &lt;li&gt;Your words. This allows for context that matters to you. It also allows for ideation on concepts that matter to you, and the takeaway of a sheet of paper.&lt;/li&gt;
  &lt;li&gt;Easy review. You now have a single sheet of paper that makes for quick review. I use giant graph paper folded into four to give me a pamphlet, which I also use as a bookmark.&lt;/li&gt;
  &lt;li&gt;A place to do exercises if needed. There were some reading speed exercises in Limitless that are now incorporated into my notes.&lt;/li&gt;
  &lt;li&gt;Simple review! All of your notes in one place- you don’t have to scan the book for your underlines/notes/etc.&lt;/li&gt;
  &lt;li&gt;Portable. A single sheet/pamphlet/whatever VS an entire book.&lt;/li&gt;
  &lt;li&gt;Loan the book, keep your notes. You also don’t bias another reader with what you think is important. Also, for some reason, writing in books feels wrong to me, like a desecration. Maybe it’s from the years of public school and knowing that books often needed to last decades?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;review&quot;&gt;Review&lt;/h2&gt;

&lt;p&gt;The book has autobiographical components, which are used to illustrate how
learning skills are not fixed and can be improved. This is a powerful message,
however I feel that the story gets repeated/tagged too many times for the
purpose of the book. Other than this relatively minor complaint, I found the
book to be very valuable. For me the most valuable sections were on all in Part
4:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Focus&lt;/li&gt;
  &lt;li&gt;Study&lt;/li&gt;
  &lt;li&gt;Memory&lt;/li&gt;
  &lt;li&gt;Speed reading&lt;/li&gt;
  &lt;li&gt;Thinking(if you haven’t read other books on mental models, this is a good introduction, but I’d recommend The Great Mental Models: General Thinking Concepts as a much more complete introduction)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;focus&quot;&gt;Focus&lt;/h3&gt;

&lt;p&gt;‘Focus’ is something we’re told to do, but not taught to do. At the most basic
form it is targeted meditation for the task at hand. It’s about noting/pushing
out interfering thoughts and staying on task.&lt;/p&gt;

&lt;h3 id=&quot;study&quot;&gt;Study&lt;/h3&gt;

&lt;p&gt;‘Study’ is another thing that we’re told to do, but not taught to do. This
section was a bit more involved that I initially expected. There are things that
are incorporated that I wasn’t expecting either: posture, scents, and baroque
music. Some of the more traditional parts are: spaced repetition and active
recall.&lt;/p&gt;

&lt;h3 id=&quot;memory&quot;&gt;Memory&lt;/h3&gt;

&lt;p&gt;There were exercises in this section that really demonstrated the value in
imagery as it impacts recall. Building vivid stories around things that you need
to remember had me immediately improve my score from a 5/10 to a 10/10. I was
also able to very easily obtain a 10/10 reversing the order as things weren’t
strictly placed, but were in a form that I found much more accessible. To this
day I still struggle slightly with alphabetization, and often find myself
running trough the list in my head to do comparisons, and always in the forward
order. I often think of the comedy sketch where someone is pulled over for a
roadside sobriety test and are asked to recite the alphabet backwards. The
payoff to the sketch is “I couldn’t do that even if I was sober”. It gives me
irrational anxiety as I know that I couldn’t recite the alphabet in reverse.
Furthermore, I know that it’s a waste of time to learn it in reverse, yet the
irrational anxiety persists!&lt;/p&gt;

&lt;p&gt;The concepts of ‘primacy’ and ‘recency’ are covered as the points that most
often facilitate recall. A time block of about 25 minutes is recommended. If
this sounds like a Pomodoro interval to you, that’s because it is.&lt;/p&gt;

&lt;h3 id=&quot;speed-reading&quot;&gt;Speed Reading&lt;/h3&gt;

&lt;p&gt;There’s a lot of information in this space, and lots of conflict. Personally I
found this very valuable, and this is the main reason the book bubbled to the
top of my list. If I can consume faster and retain the same(or more), then the
book becomes a very high leverage item for all future reading and learning.&lt;/p&gt;

&lt;p&gt;I have known since grade school that I read faster than the general population,
but had no real concept of what the general rates are, or where I was in
relation to those numbers. There was an exercise in the book to baseline, some
techniques presented, and then a retest. For me, it gave the following results:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;My initial words-per-minute(WPM) was 378. Population average is 150-200.&lt;/li&gt;
  &lt;li&gt;Post exercises and retesting was 726 WPM. With a little rounding up, that’s 2x, 1.92x if you want to be pedantic about things.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I find it hard to ignore this gain, in a matter of minutes, with relatively
little practice. Committing to regimented practice seems like it had the
potential to push things even further. Almost all of my gains came from using a
visual leader in the form of my finger. The other concept that I feel that will
take time to develop is widening of peripheral vision to chunk words. The
example given in the book is ‘report card’. ‘Report’ has a meaning, as does
‘card’, and when combined, there’s a different meaning- if you’re not chunking
‘report card’ as a single item, there’s processing overhead of pattern
recognition, and the time to access the meaning.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Get the book, take the notes, do the exercises. Improve the skills that improve
all other knowledge acquisition pursuits&lt;/p&gt;

&lt;h2 id=&quot;post-script-update-2021-06-01&quot;&gt;Post Script (Update 2021-06-01)&lt;/h2&gt;

&lt;p&gt;The construction of my books was pretty shoddy. The spine was twisted and seemed
partially delaminated. I’m not sure if this was due to, or the cause of, the
covers bowing away from the pages. Maybe it was just this run, or maybe it was
the company that did the binding.&lt;/p&gt;
</description>
        <pubDate>Mon, 31 May 2021 22:47:19 +0000</pubDate>
        <link>https://invisiblethreat.ca/books/2021/05/31/limitless/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/books/2021/05/31/limitless/</guid>
        
        <category>learning</category>
        
        <category>reading</category>
        
        <category>memory</category>
        
        <category>tools</category>
        
        
        <category>books</category>
        
      </item>
    
      <item>
        <title>.lan Docker Setup</title>
        <description>&lt;h1 id=&quot;lan-docker-setup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.lan&lt;/code&gt; Docker Setup&lt;/h1&gt;

&lt;p&gt;Docker is a great way to isolate processes. It also enables shipping things
that are almost fully configured and only require a few variables to be set
along the way&lt;/p&gt;

&lt;h2 id=&quot;tools&quot;&gt;Tools&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Docker, duh.&lt;/li&gt;
  &lt;li&gt;Ansible, because of automation&lt;/li&gt;
  &lt;li&gt;Python and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt; for environment management for Ansible&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt;. Sorry.&lt;/li&gt;
  &lt;li&gt;Git, so you can version all of your Ansible configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;networking-design&quot;&gt;Networking Design&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/lan.png&quot; alt=&quot;lan.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When depolying Docker at a network gateway, you get routing for the Docker
networks for free.&lt;/p&gt;

&lt;h3 id=&quot;the-docker-network&quot;&gt;The Docker Network&lt;/h3&gt;

&lt;p&gt;By default, on Linux, Docker creates the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;172.17.0.0/16&lt;/code&gt; network. The addresses
in this space are non-deterministic, which is a non-issue when you’re exposing
ports, as it’s the host that will weld things together via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-proxy&lt;/code&gt;. This
is not desireable for my uses. My goal is to avoid binding ports on the gateway
host if at all possible.&lt;/p&gt;

&lt;p&gt;The solution is to make another network that is not the default. I use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;172.18.0.0/16&lt;/code&gt;. This allows for static assignment, which enables DNS and
general sanity to prevail.&lt;/p&gt;

&lt;h3 id=&quot;ansible-yaml-for-creating-docker-network&quot;&gt;Ansible YAML for creating Docker network&lt;/h3&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Create lan-bridge&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;docker_network&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;lan-bridge&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ipam_options&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;subnet&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;172.18.0.0/16&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;management&quot;&gt;Management&lt;/h2&gt;

&lt;p&gt;To keep things portable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virtualenv&lt;/code&gt; is used in conjunction with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Makefile&lt;/code&gt;.
This permits provisioning of the environment on a new host in short order, with
a few safeguards for secrets.&lt;/p&gt;

&lt;p&gt;Both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end&lt;/code&gt; are sourced, rather than invoked as scripts, to retain
environments after running.&lt;/p&gt;

&lt;h3 id=&quot;init-sets-things-up&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt; sets things up&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;auth/ansible-mgmt.key&quot;&lt;/span&gt;
make

&lt;span class=&quot;nv&quot;&gt;VAULTID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$VAULTFILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VAULTID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;--vault-password-file=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VAULTFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; .ansible/bin/activate

&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;BEGIN OPENSSH PRIVATE KEY&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$KEY&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eq&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;0&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;auth/ansible.key is unencrypted. Ready to run playbooks&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;auth/ansible.key needs to be decrypted to run playbooks. Running ansible-vault.&quot;&lt;/span&gt;
  ansible-vault decrypt &lt;span class=&quot;nv&quot;&gt;$VAULTID&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$KEY&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# vim:ft=sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;makefile-bootstraps-your-environment&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Makefile&lt;/code&gt; bootstraps your environment&lt;/h3&gt;

&lt;div class=&quot;language-make highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;VIRTUALENV_VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;16.3.0
&lt;span class=&quot;nv&quot;&gt;SHELL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/bin/bash
&lt;span class=&quot;nv&quot;&gt;CACHE_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;./.cache

&lt;span class=&quot;c&quot;&gt;# fixes implicit rule converting *.sh to *
&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;.SUFFIXES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;.ansible&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;.PHONY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;all clean&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;.ansible&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;requirements.txt | $(CACHE_DIR)/virtualenv-$(VIRTUALENV_VERSION)/virtualenv.py&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;$(word&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;1,$|)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;--no-site-packages&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;./$@/bin/activate;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;./$@/bin/pip&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;.ansible/bin/activate&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;lint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;.ansible&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;.ansible/bin/python&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;.ansible/bin/ansible-lint&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;plays/compliance/*.yml&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;plays/jobs/*/*.yml&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;.ansible/bin/yamllint&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;--strict&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;.ansible/bin/pycodestyle&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;roles&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;resources&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;$(CACHE_DIR)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;$(CACHE_DIR)/virtualenv-$(VIRTUALENV_VERSION)/virtualenv.py&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(CACHE_DIR)/virtualenv-$(VIRTUALENV_VERSION).tar.gz&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-xzf&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&amp;lt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$(&amp;lt;D)&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;touch&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$@&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# this ensures this target doesn&apos;t get continually re-run
&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;$(CACHE_DIR)/virtualenv-$(VIRTUALENV_VERSION).tar.gz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;$(CACHE_DIR)&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;curl -o $@ -L https&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;//pypi.io/packages/source/v/virtualenv/virtualenv-$(VIRTUALENV_VERSION).tar.gz&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;clean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;.ansible&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;end-protects-us-from-ourselves&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end&lt;/code&gt; protects us from ourselves&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# This is the file that will be used to run vault. If it is not set, vault&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# will prompt for a password. It is controlled in this manner due to the&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# syntax that an assignement string as an argument.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;VAULTID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Look for the export of&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$VAULTFILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Using &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VAULTFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; for vault commands&quot;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;VAULTID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;--vault-password-file=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VAULTFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;VAULTFILE not set- will prompt for vault password&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# These files should never be committed unencrypted&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;auth/ansible-mgmt.key roles/docker/wiki/vars/main.yml roles/docker/pihole/vars/main.yml&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;file &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Check to see if the file has the vault header&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ANSIBLE_VAULT&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eq&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
      &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; is unencrypted. It needs to be encrypted before you&apos;re done.&quot;&lt;/span&gt;
      ansible-vault encrypt &lt;span class=&quot;nv&quot;&gt;$VAULTID&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else
      &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; is encrypted.&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi
done&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Get out of the virtualenv&lt;/span&gt;
deactivate

&lt;span class=&quot;c&quot;&gt;# Disable the zsh &quot;no matches found&quot; option. We will have to now redirect&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# STDERR for the &apos;ls&apos; comannd&lt;/span&gt;
setopt +o nomatch

&lt;span class=&quot;c&quot;&gt;# Cleanup stray &apos;retry&apos; files from runs that have partially failed&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls &lt;/span&gt;plays/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.retry 2&amp;gt;/dev/null&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Removing &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;... &quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Done.&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Re-enable nomatch&lt;/span&gt;
setopt &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; nomatch
&lt;span class=&quot;c&quot;&gt;# vim:ft=sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;example-service-pihole&quot;&gt;Example Service: PiHole&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pihole
├── README.md
├── tasks
│   └── main.yml
└── vars
    └── main.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;tasksmainyml&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tasks/main.yml&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Pull&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Image&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;docker_image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}/{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pull&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Include Common Runtime Variables&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;include_vars&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;../../vars/&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;docker_container&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}/{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;pull&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;started&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart_policy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;capabilities&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;NET_ADMIN&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;dns_servers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;127.0.0.1&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;8.8.8.8&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;purge_networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;bridge&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;ipv4_address&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ipaddr&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;ServerIP&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ipaddr&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;PUID&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;media.uid&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;PGID&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;media.gid&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;TZ&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tz.local&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;WEBPASSWORD&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;piholepass&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;media.container&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}/{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}:/etc/{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}:rw&quot;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;media.container&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}/{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}/dnsmasq.d/:/etc/dnsmasq.d:rw&quot;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/etc/localtime:/etc/localtime:ro&quot;&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/dev/rtc:/dev/rtc:ro&quot;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: DNS servers are important. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;127.0.0.1&lt;/code&gt; ensures that Pihole works, and 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8.8.8.8&lt;/code&gt; ensures that the container has fallback to the real internet if
something goes wrong&lt;/p&gt;

&lt;h3 id=&quot;varsmainyml&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vars/main.yml&lt;/code&gt;&lt;/h3&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;ctname&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;pihole&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;ipaddr&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;172.18.0.2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;vars-common-variables-to-all-containers&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;../../vars/&lt;/code&gt; Common variables to all containers&lt;/h3&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;bridge&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;lan-bridge&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;home&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/home/media&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/home/media/container&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;uid&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1001&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;gid&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1002&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;tz&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;America/Halifax&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;PUID&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;media&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;PGID&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;media&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/etc/localtime:/etc/localtime:ro&quot;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/dev/rtc:/dev/rtc:ro&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 16 Apr 2020 12:47:19 +0000</pubDate>
        <link>https://invisiblethreat.ca/technology/2020/04/16/docker-lan/</link>
        <guid isPermaLink="true">https://invisiblethreat.ca/technology/2020/04/16/docker-lan/</guid>
        
        <category>docker</category>
        
        <category>ansible</category>
        
        <category>containers</category>
        
        
        <category>technology</category>
        
      </item>
    
  </channel>
</rss>
