<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://brokenco.de//feed/by_tag/freebsd.xml" rel="self" type="application/atom+xml" /><link href="https://brokenco.de//" rel="alternate" type="text/html" /><updated>2026-05-03T00:12:50+00:00</updated><id>https://brokenco.de//feed/by_tag/freebsd.xml</id><title type="html">rtyler</title><subtitle>a moderately technical blog</subtitle><author><name>R. Tyler Croy</name></author><entry><title type="html">Using tmux with bhyve</title><link href="https://brokenco.de//2026/03/10/bhyve-tmux.html" rel="alternate" type="text/html" title="Using tmux with bhyve" /><published>2026-03-10T00:00:00+00:00</published><updated>2026-03-10T00:00:00+00:00</updated><id>https://brokenco.de//2026/03/10/bhyve-tmux</id><content type="html" xml:base="https://brokenco.de//2026/03/10/bhyve-tmux.html"><![CDATA[<p>Many aspects of FreeBSD follow the user-friendly unix philosophy, it’s just choosy about who its friends are. <a href="https://en.wikiquote.org/wiki/Unix">1</a>
I have always found <a href="https://bhyve.org/">bhyve</a> virtualization to be really
interesting but really unfriendly. The
<a href="https://github.com/freebsd/vm-bhyve">vm-bhyve</a> management system was what
finally cracked <code class="language-plaintext highlighter-rouge">bhyve</code> open and made it usable for me. The <code class="language-plaintext highlighter-rouge">vm</code> command has
paper cuts but generally speaking it does what I want on my primary FreeBSD
machine.</p>

<p>For the longest time I used the built-in VNC support to connect to machines
because the <code class="language-plaintext highlighter-rouge">vm console</code> command would use <code class="language-plaintext highlighter-rouge">/usr/bin/cu</code> which would
<em>inevitably</em> trap my console and no amount of <code class="language-plaintext highlighter-rouge">~&gt;~&gt;~&gt;&lt;~D~&gt;D&lt;S~&gt;D&lt;~&gt;&lt;D~&lt;L</code> would
help me exit.</p>

<p>Somewhere along the line <a href="https://github.com/tmux/tmux/wiki">tmux</a> support was
<a href="https://github.com/freebsd/vm-bhyve/wiki/Using-tmux">added to <code class="language-plaintext highlighter-rouge">vm-bhyve</code></a> and now <code class="language-plaintext highlighter-rouge">vm console &lt;name&gt;</code> simply opens up a new tmux
window!</p>

<p>I host everything under <code class="language-plaintext highlighter-rouge">/vm</code> on the machine, so in <code class="language-plaintext highlighter-rouge">/vm/.config/system.conf</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>console="tmux"
</code></pre></div></div>

<p>This seems like a simple thing to be excited about, and it is, but it makes
VMs <em>wildly</em> more accessible and useful for me.</p>]]></content><author><name>R. Tyler Croy</name></author><category term="freebsd" /><summary type="html"><![CDATA[Many aspects of FreeBSD follow the user-friendly unix philosophy, it’s just choosy about who its friends are. 1 I have always found bhyve virtualization to be really interesting but really unfriendly. The vm-bhyve management system was what finally cracked bhyve open and made it usable for me. The vm command has paper cuts but generally speaking it does what I want on my primary FreeBSD machine.]]></summary></entry><entry><title type="html">Quieting the server fans with ipmitool</title><link href="https://brokenco.de//2025/01/26/be-quiet-you.html" rel="alternate" type="text/html" title="Quieting the server fans with ipmitool" /><published>2025-01-26T00:00:00+00:00</published><updated>2025-01-26T00:00:00+00:00</updated><id>https://brokenco.de//2025/01/26/be-quiet-you</id><content type="html" xml:base="https://brokenco.de//2025/01/26/be-quiet-you.html"><![CDATA[<p>Some recent changes to the primary server in my office left the fans running
louder than previously. I do have some noise canceling headphones but I still
don’t want to hear the sound of jet fans from the other room, with a little bit
of free time I was able to nail down and correct the behavior using
<a href="https://man.freebsd.org/cgi/man.cgi?query=ipmitool"><code class="language-plaintext highlighter-rouge">ipmitool(1)</code></a> and <em>magic bytes</em>.</p>

<p>I don’t have a very clear idea what caused the baseline increase in fan speed,
but the <a href="/2025/01/18/pptdevs.html">updates I mentioned previously</a> did include
adding a PCI-e card to an otherwise PCI-e card-less machine. I would guess that
something in the
<a href="https://en.wikipedia.org/wiki/Intelligent_Platform_Management_Interface">IPMI/BMC</a>
resulted in the power profiles changing when the riser cards in the chassis
started to utilize power, indicating new peripherals that would benefit from
increased airflow.</p>

<p>Another homelab operator <a href="https://www.reddit.com/r/homelab/comments/aa3xj7/ibm_systemx_3650_m2_fan_speed_control/?rdt=59542">on
Reddit</a>
found the magic bytes to poke into the IPMI with <code class="language-plaintext highlighter-rouge">ipmitool</code> that would
manipulate the fan control for <em>similar</em> systems, in essence:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># ipmitool raw 0x3a 0x07 {fan_id} {speed} {fan_override}
</code></pre></div></div>

<p>My first attempt on this FreeBSD machine kicked back an error:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Could not open device at /dev/ipmi0 or /dev/ipmi/0 or /dev/ipmidev/0: No such file or directory
</code></pre></div></div>

<p>Oops! I need the kernel module, which can be loaded at runtime with <code class="language-plaintext highlighter-rouge">kldload
ipmi</code>, or at boot time with <code class="language-plaintext highlighter-rouge">impi_load="YES"</code>.</p>

<p>In my system’s case, the two fan IDs and settings that I ended up configuring were:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># ipmitool raw 0x3a 0x07 0x01 0x20 0x01
# ipmitool raw 0x3a 0x07 0x02 0x20 0x01
</code></pre></div></div>

<p>That was enough to knock the speed down to a nice quiet whirr rather than a
medium-loud whoosh! Should you find yourself in a similar position, I recommend
following <a href="https://www.cyberciti.biz/faq/freebsd-determine-processor-cpu-temperature-command/">nixCraft’s
article</a>
to monitor the CPU temperatures as you fiddle with the appropriate balance of
noise to cooling power!</p>]]></content><author><name>R. Tyler Croy</name></author><category term="freebsd" /><summary type="html"><![CDATA[Some recent changes to the primary server in my office left the fans running louder than previously. I do have some noise canceling headphones but I still don’t want to hear the sound of jet fans from the other room, with a little bit of free time I was able to nail down and correct the behavior using ipmitool(1) and magic bytes.]]></summary></entry><entry><title type="html">Why aren’t my pptdevs ready?</title><link href="https://brokenco.de//2025/01/18/pptdevs.html" rel="alternate" type="text/html" title="Why aren’t my pptdevs ready?" /><published>2025-01-18T00:00:00+00:00</published><updated>2025-01-18T00:00:00+00:00</updated><id>https://brokenco.de//2025/01/18/pptdevs</id><content type="html" xml:base="https://brokenco.de//2025/01/18/pptdevs.html"><![CDATA[<p>Whenever a system comes offline I try to always make multiple updates at once.
When I recently received some new mounting hardware for one of my big FreeBSD
servers, I decided to plonk an idle PCI-e device into the chassis while it was
out of the rack.</p>

<p>The FreeBSD machine doesn’t have any use for the PCI-e device but I <em>might</em> be
able to make use of the device from a <a href="https://bhyve.org">bhyve</a> virtual
machine. bhyve supports <a href="https://wiki.freebsd.org/bhyve/pci_passthru">pci
passthrough</a> but I have not
actually <em>used</em> it in my many years of FreeBSD virtualization.</p>

<p>Executing <code class="language-plaintext highlighter-rouge">vm passthru</code> lists out all the devices and whether they’re ready for
use, and suffice it to say even after my first crack at things, my PCI device
was <em>not ready!</em></p>

<p>The device must be “hidden” from the host in order for guests to acquire/use
the device which means a <code class="language-plaintext highlighter-rouge">pptdevs</code> entry in <code class="language-plaintext highlighter-rouge">/boot/loader.conf</code>. The
configuration syntax has an <em>antique</em> feel to it, so I re-read my <code class="language-plaintext highlighter-rouge">loader.conf</code>
numerous times, tried a couple reboots, and then went off searching the
internet.</p>

<p>I spotted a one-off comment on a semi-related GitHub issue stating:</p>

<blockquote>
  <p>Make sure <code class="language-plaintext highlighter-rouge">vmm_load="YES"</code> is in the <code class="language-plaintext highlighter-rouge">loader.conf</code></p>
</blockquote>

<p>I have been running bhyve for a while, with <code class="language-plaintext highlighter-rouge">vm_enable="YES"</code> and assorted
settings in <code class="language-plaintext highlighter-rouge">/etc/rc.conf</code>…but I didn’t have anything associated in the
<code class="language-plaintext highlighter-rouge">loader.conf</code>! For those unfamiliar, <code class="language-plaintext highlighter-rouge">loader.conf</code> is like your <code class="language-plaintext highlighter-rouge">grub.conf</code>
which has the kernel configuration and early boot time parameters, whereas
<code class="language-plaintext highlighter-rouge">rc.conf</code> is utilized at a much later stage of the boot process.</p>

<p>I posit that my <code class="language-plaintext highlighter-rouge">pptdevs</code> entry in <code class="language-plaintext highlighter-rouge">loader.conf</code> was not working because I was
relying on <code class="language-plaintext highlighter-rouge">rc.conf</code> to dynamically load the necessary bhyve kernel modules,
but by that point in the boot process it is just too late to configure PCI
passthrough devices!</p>

<p>A deep breath and one more reboot, and tada! The machine now is passing a PCI-e
card up to a Linux virtual machine which sees it as a native device!</p>

<p>There’s no telling what kind of mischief this will lead to!</p>]]></content><author><name>R. Tyler Croy</name></author><category term="freebsd" /><category term="bhyve" /><summary type="html"><![CDATA[Whenever a system comes offline I try to always make multiple updates at once. When I recently received some new mounting hardware for one of my big FreeBSD servers, I decided to plonk an idle PCI-e device into the chassis while it was out of the rack.]]></summary></entry><entry><title type="html">Mr. Sas, here to save the day.</title><link href="https://brokenco.de//2024/07/09/mister-sas.html" rel="alternate" type="text/html" title="Mr. Sas, here to save the day." /><published>2024-07-09T00:00:00+00:00</published><updated>2024-07-09T00:00:00+00:00</updated><id>https://brokenco.de//2024/07/09/mister-sas</id><content type="html" xml:base="https://brokenco.de//2024/07/09/mister-sas.html"><![CDATA[<p>I have always been a technology scavenger, picking up cheap or disused
computers for parts or tinkering. Last year when I picked up a
<em>full-height</em> server cabinet, a new world of rack-mountable junk finally became
possible! One lucky Craigslist find ended up being an older 2U IBM xSeries server with
8 drive sleds that was described as “sorta working” by the owner, who was
shedding some extra stuff for his move across the country. I accepted the
challenge, forked over a few
<a href="https://en.wikipedia.org/wiki/United_States_twenty-dollar_bill">Jacksons</a>, and
brought the machine home.</p>

<p>The thing about “server grade hardware” is that it never really is. The
consumer grade stuff is junk, the small-medium business grade stuff is junk.
It’s all junk. Servers tend to have more redundancies to compensate, but at the
end of the day: junk.</p>

<p>Anyways, the seller had trouble getting the server to recognize more than one
stick of RAM. I carefully unseated and reseated the RAM… and it just worked!</p>

<p>Onto the next challenge, sometimes the machine wouldn’t reboot. Somehow a cold boot, versus a “reboot” didn’t work properly. I found <a href="https://www.ibm.com/support/pages/system-board-lighpath-led-warning-and-cpumem-vrd-fault-ibm-system-x">a critical problem in the IMM</a> which could have resulted in me <em>bricking the board</em> and upgraded the out-of-date firmware, dreading any potential triggering of the bug.</p>

<p>I then fought against the RAID card, which really means I fought against the
<a href="https://en.wikipedia.org/wiki/Serial_Attached_SCSI">Serial-Attached-SCSI</a>
disks. Did you know that Serial-Attached-SCSI has a cable that’s functionally
compatible with SATA? Did you also know that SAS disks are obscenely expensive,
while SATA SSDs are plentiful? The difference it turns out is largely in
software and many SAS supporting devices also support SATA!</p>

<p>I wanted to boot directly into <a href="https://freebsd.org">FreeBSD</a> via ZFS, with a
nice array of SATA SSDs , but try as I might I could not get FreeBSD to boot
consistently. Inevitiably
<a href="https://man.freebsd.org/cgi/man.cgi?query=mfi&amp;sektion=4&amp;apropos=0&amp;manpath=FreeBSD+14.1-RELEASE+and+Ports">mfi(4)</a>
errors would appear and the system would become unusable. There were so many goblins in this machine, I continued searching forums, StackOverflow, and random mailing list posts. Until I finally met <strong>Mr. Sas.</strong></p>

<p>From the
<a href="https://man.freebsd.org/cgi/man.cgi?query=mrsas&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+14.1-RELEASE+and+Ports&amp;arch=default&amp;format=html">mrsas(4)</a>
man page:</p>

<blockquote>
  <p>Using <code class="language-plaintext highlighter-rouge">/boot/device.hints</code> (as mentioned below), the user can provide a
preference for the mrsas driver to detect a MR-Fusion card  instead  of the
mfi(4) driver.</p>
</blockquote>

<p>The <code class="language-plaintext highlighter-rouge">mfi(4)</code> driver and my hardware simply would <em>not</em> cooperate, so I updated <code class="language-plaintext highlighter-rouge">/boot/loader.conf</code> with:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hw.mfi.mrsas_enable="1"
</code></pre></div></div>

<p>I crossed my fingers, blew the petals off a dandelion, clutched a lucky charm
and rebooted the machine..</p>

<p>…</p>

<p>…</p>

<p>As the machine POSTed and booted into FreeBSD I quietly waited for something <em>else</em> to go wrong.</p>

<p>But it didn’t.</p>

<p>…</p>

<p>How about that? It just worked.</p>

<p><strong>Mr. Sas saved the day!</strong></p>

<p>I have probably spent $1000 on upgrades for the machine, which was retired from
some guy’s garage for $100. In turn I’ve gotten <em>far more benefit</em> from this
goofy steel slap resting at the bottom of the rack.</p>

<p>The machine has since had its disk capacity maxed out, it’s been upgraded to
136GB of RAM. It has become the central workhorse of my homelab: storing
backups, hosting a dozen jails, and even a few VMs!</p>

<p>None of which would have been possible without the friendly help of <code class="language-plaintext highlighter-rouge">mrsas(4)</code>.</p>]]></content><author><name>R. Tyler Croy</name></author><category term="freebsd" /><category term="hardware" /><category term="homelab" /><summary type="html"><![CDATA[I have always been a technology scavenger, picking up cheap or disused computers for parts or tinkering. Last year when I picked up a full-height server cabinet, a new world of rack-mountable junk finally became possible! One lucky Craigslist find ended up being an older 2U IBM xSeries server with 8 drive sleds that was described as “sorta working” by the owner, who was shedding some extra stuff for his move across the country. I accepted the challenge, forked over a few Jacksons, and brought the machine home.]]></summary></entry><entry><title type="html">Solving a FreeBSD Jails issue: interface already exists</title><link href="https://brokenco.de//2023/11/12/interface-already-exists.html" rel="alternate" type="text/html" title="Solving a FreeBSD Jails issue: interface already exists" /><published>2023-11-12T00:00:00+00:00</published><updated>2023-11-12T00:00:00+00:00</updated><id>https://brokenco.de//2023/11/12/interface-already-exists</id><content type="html" xml:base="https://brokenco.de//2023/11/12/interface-already-exists.html"><![CDATA[<p>For a long time after I rebuilt my jails host, I could not restart a certain
number of jails due to an “interface already exists” error. For the life of me
I could not make sense of it, The services running in the jails were useful but
not <em>required</em> so I put off tinkering with it. I thought that I would magically
stumble into the solution in my sleep or something equally silly.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>watermelon# service jail start gitea
Starting jails: cannot start jail  "gitea":
ifconfig: interface epair14 already exists
jail: gitea: ifconfig epair14 create up: failed
.
watermelon# service jail stop gitea
Stopping jails:.
</code></pre></div></div>

<p>What perplexed me about this issue is that I would run <code class="language-plaintext highlighter-rouge">ifconfig epair14a</code>
after the failure to start the jail, and the interface would be there. “Surely
this must be a FreeBSD bug!”</p>

<p>The “eureka!” happened earlier today, not while I was sleeping, but rather
while I was solving other problems. “I bet there’s something fishy in the
configuration, I should just rewrite it” I thought to myself. Most esoteric
bugs are not bugs with the compiler, libraries, or operating systems. Usually
they’re the user doing something slightly stupid and not realizing it.</p>

<p>My jail configuration (<code class="language-plaintext highlighter-rouge">/etc/jail.conf</code>) resembled the following:</p>

<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">gitea</span> {
        $<span class="n">id</span> = <span class="s2">"14"</span>;
        $<span class="n">ip_addr</span> = <span class="s2">"10.10.10.${id}"</span>;

        <span class="n">vnet</span>.<span class="n">interface</span> = <span class="s2">"epair${id}b"</span>;

        <span class="n">exec</span>.<span class="n">prestart</span> = <span class="s2">"ifconfig epair${id} create up"</span>;
        <span class="n">exec</span>.<span class="n">prestart</span> += <span class="s2">"ifconfig epair${id}a up descr vnet-${name}"</span>;
        <span class="n">exec</span>.<span class="n">prestart</span> += <span class="s2">"ifconfig $public_bridge addm epair${id}a up"</span>;

        <span class="n">exec</span>.<span class="n">start</span> = <span class="s2">"/sbin/ifconfig epair${id}b ${ip_addr}"</span>;
        <span class="n">exec</span>.<span class="n">start</span> += <span class="s2">"/sbin/route add default ${public_gw}"</span>;
        <span class="n">exec</span>.<span class="n">start</span> += <span class="s2">"/bin/sh /etc/rc"</span>;

        <span class="n">exec</span>.<span class="n">prestop</span> = <span class="s2">"ifconfig epair${id}b -vnet ${name}"</span>;
        <span class="n">exec</span>.<span class="n">poststop</span> = <span class="s2">"ifconfig ${public_bridge} deletem epair${id}a"</span>;
        <span class="n">exec</span>.<span class="n">poststop</span> += <span class="s2">"ifconfig epair${id}a destroy"</span>;
}
</code></pre></div></div>

<p>Looking at the block and comparing it to other <em>functional</em> jails, I saw something missing: a <code class="language-plaintext highlighter-rouge">vnet;</code> declaration:</p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gd">--- jail.conf   2023-11-12 20:09:03.028010000 -0800
</span><span class="gi">+++ /etc/jail.conf      2023-11-12 19:59:02.867271000 -0800
</span><span class="p">@@ -230,6 +230,7 @@</span>
        $id = "14";
        $ip_addr = "10.10.10.${id}";

+       vnet;
        vnet.interface = "epair${id}b";

        exec.prestart = "ifconfig epair${id} create up";
</code></pre></div></div>

<p>Sometimes you have to just walk away from a problem for a bit, but yeesh was that a silly one!</p>]]></content><author><name>R. Tyler Croy</name></author><category term="freebsd" /><category term="jails" /><summary type="html"><![CDATA[For a long time after I rebuilt my jails host, I could not restart a certain number of jails due to an “interface already exists” error. For the life of me I could not make sense of it, The services running in the jails were useful but not required so I put off tinkering with it. I thought that I would magically stumble into the solution in my sleep or something equally silly.]]></summary></entry><entry><title type="html">Invalid signature in boot block on FreeBSD</title><link href="https://brokenco.de//2023/03/13/freebsd-efi-boot-problems.html" rel="alternate" type="text/html" title="Invalid signature in boot block on FreeBSD" /><published>2023-03-13T00:00:00+00:00</published><updated>2023-03-13T00:00:00+00:00</updated><id>https://brokenco.de//2023/03/13/freebsd-efi-boot-problems</id><content type="html" xml:base="https://brokenco.de//2023/03/13/freebsd-efi-boot-problems.html"><![CDATA[<p>I don’t have a lot of opinions about
<a href="https://en.wikipedia.org/wiki/Extensible_Firmware_Interface">UEFI</a>, but it
seems that building something as critical as booting around the FAT32
filesystem is not a great idea. FAT32 is a simple but archaic filesystem which
has the resiliency of a paper boat. While moving machines around in my homelab
this weekend I was bit by that resiliency as halfway through booting my FreeBSD
NAS it complained that it could not complete <code class="language-plaintext highlighter-rouge">fsck</code> operations: <code class="language-plaintext highlighter-rouge">Invalid
signature in boot block: 0000</code>.</p>

<p>This FreeBSD machine uses UEFI and boots directly to ZFS. Imagine my surprise
that the operating system had complaints about my boot partitions…after it
had already booted. This machine had recently been rebuilt with new disks after
I discovered that the previous disks I had been sold were “SNR” (Shingled
Magnetic Recording), which have such abhorrent performance that it’s a wonder
they’re even marketed at all. Suffice it to say, disk issues on this machine
<em>terrify me</em>. I doni’t want to deal with another rebuild!</p>

<p>The boot process failed half-way through, which means that FreeBSD drops you
into a single-user mode in the console. With that I could poke around a little
bit:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">zfs list</code> showed all data sets I expected</li>
  <li><code class="language-plaintext highlighter-rouge">zpool status</code> showed  that each disk in the pool was healthy.</li>
  <li><code class="language-plaintext highlighter-rouge">zpool scrub</code> for good measure to make sure the pool was legitimately healthy.</li>
  <li><code class="language-plaintext highlighter-rouge">gpart</code> showed that the partitions on all the disks were in tact as well.</li>
  <li><code class="language-plaintext highlighter-rouge">fsck</code> reported errors on the EFI partitions for <em>three</em> of the <em>four</em> disks.</li>
</ul>

<p>For whatever reason, the <code class="language-plaintext highlighter-rouge">efi</code> partitions were all hosed in the same way on
3/4th of the disks: <code class="language-plaintext highlighter-rouge">Invalid signature in boot block</code>.</p>

<p>I am still not entirely sure how this corruption occurred but getting the
machine back online to do more disk diagnostics was a key step forward.
Fortunately with one valid <code class="language-plaintext highlighter-rouge">efi</code> partition, I was able to <code class="language-plaintext highlighter-rouge">dd</code> its contents
onto every other disk, since they’re all supposed to be identical anyways:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dd if=/dev/ada0p1 of=/dev/ada1p1 bs=4M
</code></pre></div></div>

<p>After a round of copying bytes around, I was able to reboot and everything came
up perfectly fine!</p>

<p>Since there are no other indications of disk failure or problems, I may never
know what originally caused the corruption. The consensus on IRC however is
that building a foundational part of the boot process on an unreliable
filesystem was perhaps a bad idea.</p>]]></content><author><name>R. Tyler Croy</name></author><category term="freebsd" /><summary type="html"><![CDATA[I don’t have a lot of opinions about UEFI, but it seems that building something as critical as booting around the FAT32 filesystem is not a great idea. FAT32 is a simple but archaic filesystem which has the resiliency of a paper boat. While moving machines around in my homelab this weekend I was bit by that resiliency as halfway through booting my FreeBSD NAS it complained that it could not complete fsck operations: Invalid signature in boot block: 0000.]]></summary></entry><entry><title type="html">Increasing the density of the home lab with FreeBSD Jails</title><link href="https://brokenco.de//2021/06/06/high-density-homelab.html" rel="alternate" type="text/html" title="Increasing the density of the home lab with FreeBSD Jails" /><published>2021-06-06T00:00:00+00:00</published><updated>2021-06-06T00:00:00+00:00</updated><id>https://brokenco.de//2021/06/06/high-density-homelab</id><content type="html" xml:base="https://brokenco.de//2021/06/06/high-density-homelab.html"><![CDATA[<p>Investing the time to learn FreeBSD jails has led to a dramatic increase in the
number of services I run in my “home lab.”
<a href="https://docs.freebsd.org/en/books/handbook/jails/">Jails</a>, which I have
<a href="/tag/freebsd.html">written about before</a>, are effectively a lightweight
quasi-virtualization technique which I use to create multiple software-defined
networks to segment workloads. Jails have allowed me to change my “home lab”
dramatically, allowing me to <em>reduce</em> the number of machines and increase
hardware utilization. For now, the days of stacking machines, dangling
Raspberry Pis, or hiding laptops on the shelf are all gone. Almost all my needs
have been consolidated into a single FreeBSD machine running on a 4 year old
used workstation.</p>

<p>I have attempted to consolidate the home lab before, but not with this
level of success. There was the time I tried deploying a single-node
Kubernetes cluster, which worked for a time until some upgrade caused the
software-defined networking to break in a way I wasn’t interested in debugging
in my free time. Following that I tried to go “old school” and started spinning
up <code class="language-plaintext highlighter-rouge">libvirt</code>-based virtual machines which worked <em>well</em> for a long time. The
major downside of that approach is that I simply wasn’t able to get much
density because of the significant overhead for each virtual machine. At some
point you run out of memory to commit to each VM.</p>

<p>Converting virtual machines to FreeBSD Jails took a few hours over a weekend,
and since then the <strong>quantity</strong> of what is running has jumped dramatically. Originally I was running:</p>

<ul>
  <li><a href="https://nextcloud.com">Nextcloud</a> (Apache)</li>
  <li>MySQl</li>
  <li>Gopher server</li>
  <li><a href="https://torproject.org/">Tor</a> relay</li>
  <li><a href="https://gitea.io">Gitea</a></li>
</ul>

<p>I now <em>also</em> run:</p>

<ul>
  <li>Elasticsearch</li>
  <li>Graylog</li>
  <li>Icinga</li>
  <li>Icecast</li>
  <li>MongoDB</li>
  <li>Nginx</li>
  <li><a href="https://joinpeertube.org">Peertube</a></li>
  <li>PostgreSQL, which replaced MySQL for Nextcloud and is now running for multiple services.</li>
  <li>Redis</li>
  <li>Plus some personal web apps</li>
</ul>

<p>To accomplish this, I use ZFS and Jails <strong>heavily</strong>. All the jails run on a
striped and mirrored ZFS disk array which allows for better performance and
redundancy than my previous incantation. These services are low-utilization
which allows them to cooperate effectively within this machine’s 4 cores and
16GB of RAM.</p>

<h2 id="benefits">Benefits</h2>

<p>The higher utilization of this single machine, which is always-on, has a better
power consumption profile than running multiple machines. More power efficiency wasn’t my original motivation however, I was much more interested in some of the system administration benefits of bringing these services “under one roof.”</p>

<p><strong>Backups</strong> are <em>much</em> easier than before. I’m using some ZFS scripts to
perform automatic snapshots on daily/weekly/monthly basis. Separately from
those, I regularly push backups off-site and that’s trivial because at the
“host” machine level, not the jail level, I can access all the filesystems at
once.</p>

<p><strong>Security</strong> is much easier as well since Jails are obviously providing a level
of isolation. On top of that, I am using the <code class="language-plaintext highlighter-rouge">vnet</code> functionality in FreeBSD to
provide additional network segmentation, something I never did with physical or
virtual machines.</p>

<p><strong>Management</strong> is pretty straightforward with all these services running in
Jails. I typically do all my administration from the host rather than the jail
level. As such I can pretty easily shuffle configuration files around.
Unfortunately to date I haven’t found a good configuration management tool,
including my own <a href="https://github.com/rtyler/zap">tinkering</a> that provides a
Jails-aware set of tools for more automation.</p>

<h2 id="downsides">Downsides</h2>

<p>The most notable downside to this approach is that a hardware failure <em>could</em>
take me offline for a bit. These services are all dependent on a single power
supply (PSU) and CPU. As such a failure of either would require me to keep all
these services offline until that part could be replaced. For a home lab setup,
I’m not expecting to support a specific SLA, so I’m quite comfortable with this
risk.</p>

<p>I can imagine some security arguments that could be made, but frankly I think
this Jails approach is <em>much</em> better secured than my previous home lab setups.</p>

<hr />

<p>At present this machine has just under 10GB of RAM in use and a load average
that floats between 1.0 and 2.0. Despite all the services that are running, it
still uses <em>less</em> than my workstation with a few browsers open. To deploy your
own “home lab” set up in this way you absolutely <em>do not</em> need a high powered
machine. I would argue that a ZFS-based disk array is likely more important,
after all most home lab tasks, that aren’t video-encoding, tend to be more disk
I/O heavy rather than memory/CPU heavy.</p>

<p>This path isn’t quite entry-level simple, but if you have some systems
administration experience, I think <a href="https://freebsd.org">FreeBSD</a> with ZFS and
Jails is worth considering for your home or office lab.</p>]]></content><author><name>R. Tyler Croy</name></author><category term="freebsd" /><category term="jails" /><summary type="html"><![CDATA[Investing the time to learn FreeBSD jails has led to a dramatic increase in the number of services I run in my “home lab.” Jails, which I have written about before, are effectively a lightweight quasi-virtualization technique which I use to create multiple software-defined networks to segment workloads. Jails have allowed me to change my “home lab” dramatically, allowing me to reduce the number of machines and increase hardware utilization. For now, the days of stacking machines, dangling Raspberry Pis, or hiding laptops on the shelf are all gone. Almost all my needs have been consolidated into a single FreeBSD machine running on a 4 year old used workstation.]]></summary></entry><entry><title type="html">Software-defined networks with FreeBSD Jails</title><link href="https://brokenco.de//2021/03/07/sdn-with-freebsd-jails.html" rel="alternate" type="text/html" title="Software-defined networks with FreeBSD Jails" /><published>2021-03-07T00:00:00+00:00</published><updated>2021-03-07T00:00:00+00:00</updated><id>https://brokenco.de//2021/03/07/sdn-with-freebsd-jails</id><content type="html" xml:base="https://brokenco.de//2021/03/07/sdn-with-freebsd-jails.html"><![CDATA[<p>As a comprehensive operating system FreeBSD never ceases to impress me, the
recent iterations of <a href="https://docs.freebsd.org/en/books/handbook/jails/">FreeBSD
Jails</a> as an example have been an
absolute joy to use. The introduction of the
<a href="https://www.freebsd.org/cgi/man.cgi?query=vnet&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+12.2-RELEASE+and+Ports&amp;arch=default&amp;format=html">vnet(9)</a>
network subsystem has completely transformed what I had originally thought
about software-defined networking. My previous exposure to the concept of
<a href="https://en.wikipedia.org/wiki/Software-defined_networking">software-defined
networking</a> was
through both <a href="https://www.openstack.org/">OpenStack</a> and Docker, two very
different approaches to the broad domain of “SDN”. FreeBSD’s <code class="language-plaintext highlighter-rouge">vnet</code> system has
resonated most strongly with me and has allowed me some measure of success in
deploying real production-grade virtualized networks.</p>

<p>One of the first blog posts I read was <a href="https://klarasystems.com/articles/virtualize-your-network-on-freebsd-with-vnet/">this post by klara
systems</a>,
which despite being painfully devoid of diagrams, does a fairly good job of
introducing the vnet feature set. In short, vnet allows jails to each have their
own isolated networking stack <em>including</em> the ability to assign virtual or
<strong>hardware interfaces</strong> to the jail. I cannot overstate how much of a super-power this is.</p>

<p>Consider an example where you want to do some testing of network security
tooling whether your firewall rules, intrusion detection, etc. You can set up a
bridge device to act as a “virtual switch” along with
<a href="https://www.freebsd.org/cgi/man.cgi?query=epair&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+12.2-RELEASE+and+Ports&amp;arch=default&amp;format=html">epair(4)</a>
devices to act as “virtual patch cables” to create a completely virtualized
network as diagrammed below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>+---------------------+
| Host                |
|                     |
| +-----------------+ |
| | ixl0 (ethernet) | |  +-------------+
| +-----------------+ |  | snort-jail  |
|                     |  |             |
| +---------+     +------&gt; epair1b     |
| | bridge0 |     |   |  +-------------+
| |         |     |   |
| | epair1a +-----+   |  +-----------------+
| | epair2a +------+  |  | some other jail |
| |         |      |  |  |                 |
| +---------+      +-----&gt; epair2b         |
+---------------------+  +-----------------+
</code></pre></div></div>

<p>In the setup described above, <code class="language-plaintext highlighter-rouge">epair1a</code> and <code class="language-plaintext highlighter-rouge">epair2a</code> would not have IP addresses:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">bridge0</code>: could be set up with <code class="language-plaintext highlighter-rouge">10.0.100.1</code></li>
  <li><code class="language-plaintext highlighter-rouge">epair1b</code>: would then be assigned <code class="language-plaintext highlighter-rouge">10.0.100.2</code></li>
  <li><code class="language-plaintext highlighter-rouge">epair2b</code>: would also take <code class="language-plaintext highlighter-rouge">10.0.100.3</code></li>
</ul>

<p>If it was desired to have <code class="language-plaintext highlighter-rouge">snort-jail</code> be able to route out to the network
connected on the host’s <code class="language-plaintext highlighter-rouge">ixl0</code> interface, then the host would need to be
configured as a
<a href="https://docs.freebsd.org/en_US.ISO8859-1/books/handbook/network-routing.html">gateway</a>
and <code class="language-plaintext highlighter-rouge">snort-jail</code> would the treat <code class="language-plaintext highlighter-rouge">10.0.100.1</code> as its default router.</p>

<p>Contrary to my experiences with Docker-based networking this is natively part
of the FreeBSD network stack, rather than iptables-style smoke and mirrors. As
a result, I have found this set up not only to be incredibly reliable but also
<em>very</em> nestable. It’s totally feasible to nest these virtualized network setups
to create completely isolated test networks or all manners of different network
topologies for development or production workloads.</p>

<p>On top of that, because you can assign <strong>hardware interfaces</strong> to Jails, it is
also possible to take another NIC (e.g. <code class="language-plaintext highlighter-rouge">ixl1</code>) and assign it into a Jail such
that the Jail could manage its own network, <code class="language-plaintext highlighter-rouge">pf</code>, and gateway configuration,
completely separate from the jail host. Thereby allowing a fairly strong
segmentation of <em>physical</em> networks by way of the FreeBSD vnet jails
infrastructure.</p>

<p><strong>So cool!</strong></p>

<p>For my own purposes I have been using an approach which is much better
documented in <a href="https://alpha.pkgbase.live/howto/jails.html">this page</a> for
isolating network services. For example, I run a <a href="https://torproject.org">Tor</a> relay inside
of a Jail with an isolated network, and then use
<a href="https://www.freebsd.org/cgi/man.cgi?query=pf&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+12.2-RELEASE+and+Ports&amp;arch=default&amp;format=html">pf</a>
on the jail host to restrict that network from ever reaching out onto my LAN.
It can only talk to the public internet, no other virtual or physical networks.
From a security standpoint this <em>should</em> mean even a compromise of the Tor
daemon would limit the blast-radius to that jail alone.</p>

<p>Since there are few practical limits on how many bridges and <code class="language-plaintext highlighter-rouge">epair</code> devices I
can create, I have taken the path of creating multiple independent networks for
Jails which don’t need to talk to each other or the same set of shared
resources. This gives me some level of comfort when trying out new pieces of
software or sharing services with other users that have varying trust profiles.</p>

<p>Overall I am immensely pleased with what has been possible between FreeBSD,
Jails, and <code class="language-plaintext highlighter-rouge">pf</code> to create rich topologies of software-defined networks for my
production and development needs. If you are curious to learn more, <a href="https://klarasystems.com/articles/virtualize-your-network-on-freebsd-with-vnet/">this blog
post</a>
and <a href="https://alpha.pkgbase.live/howto/jails.html">this page</a> are definitely worth reading!</p>]]></content><author><name>R. Tyler Croy</name></author><category term="freebsd" /><category term="security" /><summary type="html"><![CDATA[As a comprehensive operating system FreeBSD never ceases to impress me, the recent iterations of FreeBSD Jails as an example have been an absolute joy to use. The introduction of the vnet(9) network subsystem has completely transformed what I had originally thought about software-defined networking. My previous exposure to the concept of software-defined networking was through both OpenStack and Docker, two very different approaches to the broad domain of “SDN”. FreeBSD’s vnet system has resonated most strongly with me and has allowed me some measure of success in deploying real production-grade virtualized networks.]]></summary></entry><entry><title type="html">Multiple Let’s Encrypt domains in a single Nginx server block</title><link href="https://brokenco.de//2021/02/15/dynamic-certificates-nginx.html" rel="alternate" type="text/html" title="Multiple Let’s Encrypt domains in a single Nginx server block" /><published>2021-02-15T00:00:00+00:00</published><updated>2021-02-15T00:00:00+00:00</updated><id>https://brokenco.de//2021/02/15/dynamic-certificates-nginx</id><content type="html" xml:base="https://brokenco.de//2021/02/15/dynamic-certificates-nginx.html"><![CDATA[<p><a href="https://nginx.org">Nginx</a> is a fantastic web server and reverse proxy to use
with <a href="https://letsencrypt.org/">Let’s Encrypt</a>, but when dealing with multiple
domains it can be a bit tedious to configure.  I have been moving services into
more <a href="https://freebsd.org">FreeBSD</a> jails as I alluded to <a href="/2021/02/02/freebsd-pkg-with-an-offline-jail.html">in my previous
post</a>, among them the
general Nginx proxy jail which I have serving my HTTP-based services. Using
Let’s Encrypt for TLS, I found myself declaring multiple <code class="language-plaintext highlighter-rouge">server</code> blocks inside
my virtual host configurations to handle the apex domain (e.g.
<code class="language-plaintext highlighter-rouge">dotdotvote.com</code>), the <code class="language-plaintext highlighter-rouge">www</code> subdomain, and vanity domains (e.g.
<code class="language-plaintext highlighter-rouge">dotdot.vote</code>). With the help <code class="language-plaintext highlighter-rouge">Membear</code> and <code class="language-plaintext highlighter-rouge">MTecknology</code> in the <code class="language-plaintext highlighter-rouge">#nginx</code>
channel on <a href="https://freenode.net">Freenode</a>, I was able to refactor multiple
largely redundant <code class="language-plaintext highlighter-rouge">server</code> blocks into one.</p>

<p>With Nginx 1.15.9 a feature I have seen referred to as “dynamic certificates”
was released. Originally the <code class="language-plaintext highlighter-rouge">ssl_certificate</code> and <code class="language-plaintext highlighter-rouge">ssl_certificate_key</code> were
loaded when Nginx <em>started</em>. This meant that you could not refer to any of the
<a href="http://nginx.org/en/docs/varindex.html">Nginx variables</a> when creating the
setting. With dynamic certificates, the resolution of the <code class="language-plaintext highlighter-rouge">ssl_certificate</code>
directive is done <em>later</em> by the worker(s) process(es). It’s a <em>very</em> handy
feature!</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name dotdotvote.com www.dotdotvote.com dotdot.vote;
  ##
  # Certificates
  ssl_certificate     /usr/local/etc/letsencrypt/live/$ssl_server_name/fullchain.pem;
  ssl_certificate_key /usr/local/etc/letsencrypt/live/$ssl_server_name/privkey.pem;

  # ... snip ...
  location / {
    # ... snip ...
    proxy_pass http://dotdotvote;
  }
}
</code></pre></div></div>

<p>In the example above, I’m using the <code class="language-plaintext highlighter-rouge">$ssl_server_name</code> variable which will
correspond to the server name requested in the SNI part of the TLS payload.
This ensures that the right hostname’s certificate is utilized.</p>

<p>My first attempt was with <code class="language-plaintext highlighter-rouge">$server_name</code>, which I recommend you avoid using
<code class="language-plaintext highlighter-rouge">$server_name</code> since that will not be computed per request. For example, in the
block below the <code class="language-plaintext highlighter-rouge">$server_name</code> variable will <em>always</em> be <code class="language-plaintext highlighter-rouge">dotdotvote.com</code> and
requests served on <code class="language-plaintext highlighter-rouge">www.dotdotvote.com</code> will use the incorrect certificate.:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
    server_name dotdotvote.com www.dotdotvote.com;

    ssl_certificate '/some/path/$server_name/fullchain.pem';
}
</code></pre></div></div>

<p>When I was originally setting this up, I also stumbled into some “Permission
denied” errors from Nginx. With the static certificate declaration, the <em>main</em>
Nginx process would load the file. That process would run as root before
dropping privileges to the <code class="language-plaintext highlighter-rouge">www</code> user for the Nginx worker(s). To address this
I needed to go change filesystem ownership in order for the <code class="language-plaintext highlighter-rouge">www</code> user to
properly read the certificate files.</p>

<hr />

<p>In retrospect, this feature seems relatively simple to use if you have a good
understanding of the Nginx process and permissions model. Suffice it to say, I
wouldn’t have figured this out without a bit of help from the folks in
<code class="language-plaintext highlighter-rouge">#nginx</code>. With the change in place my Nginx configurations are now much more
succinct and readable!</p>]]></content><author><name>R. Tyler Croy</name></author><category term="nginx" /><category term="freebsd" /><category term="security" /><summary type="html"><![CDATA[Nginx is a fantastic web server and reverse proxy to use with Let’s Encrypt, but when dealing with multiple domains it can be a bit tedious to configure. I have been moving services into more FreeBSD jails as I alluded to in my previous post, among them the general Nginx proxy jail which I have serving my HTTP-based services. Using Let’s Encrypt for TLS, I found myself declaring multiple server blocks inside my virtual host configurations to handle the apex domain (e.g. dotdotvote.com), the www subdomain, and vanity domains (e.g. dotdot.vote). With the help Membear and MTecknology in the #nginx channel on Freenode, I was able to refactor multiple largely redundant server blocks into one.]]></summary></entry><entry><title type="html">Using FreeBSD’s pkg(1) with an ‘offline’ jail</title><link href="https://brokenco.de//2021/02/02/freebsd-pkg-with-an-offline-jail.html" rel="alternate" type="text/html" title="Using FreeBSD’s pkg(1) with an ‘offline’ jail" /><published>2021-02-02T00:00:00+00:00</published><updated>2021-02-02T00:00:00+00:00</updated><id>https://brokenco.de//2021/02/02/freebsd-pkg-with-an-offline-jail</id><content type="html" xml:base="https://brokenco.de//2021/02/02/freebsd-pkg-with-an-offline-jail.html"><![CDATA[<p>In the modern era of highly connected software, I have been trying to “offline”
as many of my personal services as I can. The ideal scenario being a service
running in an environment where it cannot reach other nodes on the network, or
in some cases even route back to the public internet. To accomplish this I have
been working with <a href="https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/jails.html">FreeBSD
jails</a> a
quite a bit, creating a service per-jail in hopes of achieving high levels of
isolation between them. This approach has a pretty notable problem at first
glance: if you need to install software from remote sources in the jail, how do
you keep it “offline”?</p>

<p><strong>2021-02-14 update</strong> with more tips <a href="#update">below</a></p>

<p><em>Note: if you’re already familiar with how great FreeBSD jails are, you can skip <a href="#pkg">ahead</a></em></p>

<p>Without trying to start a flamewar, I think FreeBSD jails are basically what
Linux containers aspired to be when they grew up. In short:</p>

<blockquote>
  <p>The jail mechanism is an implementation of FreeBSD’s OS-level virtualisation
that allows system administrators to partition a FreeBSD-derived computer
system into several independent mini-systems called jails, all sharing the same
kernel, with very little overhead</p>
</blockquote>

<p><em>From <a href="https://en.wikipedia.org/wiki/FreeBSD_jail">Wikipedia</a></em></p>

<p>Since FreeBSD 12, FreeBSD jails can “natively” do something which I haven’t
seen done seriously in other container or virtualization stacks: <strong>provide full
network isolation</strong>. VNET allows attaching an entire virtualized network stack
to a jail, which allows you to delegate an actual hardware interface to a jail,
after which the host no longer sees the interface at all!</p>

<blockquote>
  <p>VNET is the name of a technique to virtualize the network stack.  The
basic idea is to change global resources most notably variables into per
network stack resources and have functions, sysctls, eventhandlers, etc.
access and handle them in the context of the correct instance.  Each
(virtual) network stack is attached to a prison, with vnet0 being the
unrestricted default network stack of the base system.</p>
</blockquote>

<p><em>From <code class="language-plaintext highlighter-rouge">vnet(9)</code></em></p>

<p>Using this capability you can set up entirely software-defined virtualized networks inside of FreeBSD jails for everything from network software testing (e.g. VPNs), to pre-flighting firewall changes in a simulated environment. If this sounds compelling to you, I recommend bouncing over to <a href="https://klarasystems.com/articles/virtualize-your-network-on-freebsd-with-vnet/">this blog post</a> to learn more.</p>

<p>FreeBSD has also supported
<a href="https://www.freebsd.org/doc/handbook/zfs-zfs.html">ZFS</a>
natively, including as the boot <code class="language-plaintext highlighter-rouge">/</code> partition for a number of major releases.
It should therefore be no surprise that jails integrate <em>very</em> well with ZFS.
In my setup each jail is its own file system in the main ZFS pool (<code class="language-plaintext highlighter-rouge">zroot</code>),
which allows me to snapshot each jail independently for backup purposes.</p>

<p>“Excuse me, I believe I was promised some <code class="language-plaintext highlighter-rouge">pkg(1)</code> related content?”</p>

<p>Yes yes, getting to that. Since FreeBSD jails are not well appreciated by the
broader systems engineering world, I wanted to take a moment to highlight some
of what we’ve been missing out the past couple years while we’ve been screwing
around with container orchestration engines.</p>

<p><code class="language-plaintext highlighter-rouge">pkg(1)</code> is a binary package management tool akin to <code class="language-plaintext highlighter-rouge">apt</code> or <code class="language-plaintext highlighter-rouge">yum</code>. On modern
FreeBSD installations compiling ports is no longer required, which is an
incredibly welcome change to FreeBSD in recent years.  Like its Linux
relatives, <code class="language-plaintext highlighter-rouge">pkg</code> retrieves package metadata and tarballs from a remote
repository by default, from the “offline jail” perspective this is a problem.</p>

<p>Jails however, are just running off slices of my host filesystem, e.g. <code class="language-plaintext highlighter-rouge">/jails/postgresql</code> which allows me to commands from the host in that file tree, for example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>freebsd# ls /jails/postgressql
.cshrc          bin             entropy         libexec         net             root            tmp
.profile        boot            etc             media           proc            sbin            usr
COPYRIGHT       dev             lib             mnt             rescue          sys             var
freebsd#
</code></pre></div></div>

<p>You should note that this looks surprisingly identical to what a default base
install of FreeBSD, and that’s because it is!</p>

<p><a name="pkg"></a></p>
<h2 id="installing-packages">Installing packages</h2>

<p>The <code class="language-plaintext highlighter-rouge">pkg(1)</code> utility has a <em>very useful</em> flag <code class="language-plaintext highlighter-rouge">-c</code> which I can use for these jails:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-c &lt;chroot path&gt;, --chroot &lt;chroot path&gt;
    pkg will chroot in the &lt;chroot path&gt; environment.
</code></pre></div></div>

<p>From the jail host’s perspective, I can poke around the jail’s filesystem with ease, which makes installing packages <em>trivial</em> from the host’s perspective. For example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>freebsd# pkg -c /jails/postgresql install postgresql13-server
</code></pre></div></div>

<p>The above command will install the PostgreSQL v13 package and all its dependencies within the jail’s filesystem path:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># postgres --version
postgres (PostgreSQL) 13.1
#
</code></pre></div></div>

<p>“Try this one weird trick and your jails will never have to know anything about
packages ever again!”</p>

<p><strong>Caveats</strong>:</p>

<ul>
  <li>My host distribution is identical to the distribution installed in the jail,
e.g. <code class="language-plaintext highlighter-rouge">12.2-RELEASE</code>. If there were drift I’m sure there would be problems
with using <code class="language-plaintext highlighter-rouge">pkg(1)</code> in this way.</li>
  <li>This approach can feel goofy with configuration management, since the jail
host is where all the configuration and package management happens.</li>
</ul>

<p>Nonetheless, I was incredibly excited to discover this feature which made
setting up and managing my heavily isolated vnet-based jails <em>much</em> easier!</p>

<hr />

<p><a name="update"></a>
<strong>2021-02-14 update:</strong> Here’s a tip passed along from a reader:</p>

<blockquote>
  <p>you might be interested in a tip for your jail post.</p>

  <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pkg -o ABI=... \
--chroot /path/to/jail \
--config /some/package/repo/FreeBSD.conf \
install -y ...
</code></pre></div>  </div>

  <p>where ABI could be FreeBSD:14:aarch64 (FreeBSD current on armv8/aarch64) or a more prosaic FreeBSD:12:amd64 (amd64 architecture, FreeBSD 12).</p>

  <p>the config file is similar to <code class="language-plaintext highlighter-rouge">/etc/pkg/FreeBSD.conf</code> and is acquired by <code class="language-plaintext highlighter-rouge">pkg(8)</code> before dropping into the chroot.</p>

  <p>NB I usually need to mount_devfs inside the jail before &amp; after pkg, as it now requires /dev/null - see <a href="https://github.com/freebsd/pkg/issues/1763">#1763</a></p>

  <p>This allows us to install packages into a directory that is not for the same FreeBSD version (and possibly even architecture!), such as a FreeBSD 13.0 armv8 nfs mount, running on a FreeBSD 14.0-current amd64 server.</p>

  <p>There’s also pkg –rootdir … which is similar to chroot, but IIRC handles pre/post/user/group scripts differently.</p>
</blockquote>

<hr />

<p>In the future I hope to write more about the home lab FreeBSD set up that I
have been working on over the past couple weeks. FreeBSD 12.x is by far the
most exciting FreeBSD release I have used since the transition to full SMP in
the 4.x -&gt; 6.x timeframe. If you haven’t looked at FreeBSD lately, I highly
recommend giving it a spin!</p>]]></content><author><name>R. Tyler Croy</name></author><category term="freebsd" /><category term="jails" /><summary type="html"><![CDATA[In the modern era of highly connected software, I have been trying to “offline” as many of my personal services as I can. The ideal scenario being a service running in an environment where it cannot reach other nodes on the network, or in some cases even route back to the public internet. To accomplish this I have been working with FreeBSD jails a quite a bit, creating a service per-jail in hopes of achieving high levels of isolation between them. This approach has a pretty notable problem at first glance: if you need to install software from remote sources in the jail, how do you keep it “offline”?]]></summary></entry></feed>