<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.3">Jekyll</generator><link href="https://jonathangerlach.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://jonathangerlach.com/" rel="alternate" type="text/html" /><updated>2025-12-07T13:37:51-05:00</updated><id>https://jonathangerlach.com/feed.xml</id><title type="html">Jonathan Gerlach</title><subtitle>© 2025 Jonathan Gerlach</subtitle><entry><title type="html">What is NeptuneOS?</title><link href="https://jonathangerlach.com/neptuneos/2025/12/06/what-is-neptuneos.html" rel="alternate" type="text/html" title="What is NeptuneOS?" /><published>2025-12-06T14:55:00-05:00</published><updated>2025-12-06T14:55:00-05:00</updated><id>https://jonathangerlach.com/neptuneos/2025/12/06/what-is-neptuneos</id><content type="html" xml:base="https://jonathangerlach.com/neptuneos/2025/12/06/what-is-neptuneos.html"><![CDATA[<p>In 2003, I got my first Mac and I heard that MacOS X ran on top of Mach, which is a microkernel. This started my whole “What’s a microkernel” thing, which has lived rent-free in my brain ever since. In 2016, I saw that QEMU had made an <a href="https://www.qemu-advent-calendar.org/2016/">advent calendar with different computer architectures</a>, which included a microkernel on day 11 called seL4. There’s a project called Genode, which is an operating system framework that can be run on top of various microkernels. I played around with Genode for a bit, but it didn’t spark joy, as it isn’t similar to other desktop experiences I’m used to. I wondered if someone could build a more familiar system on seL4, but I didn’t have the skillset to be that person. Later, a PH.D sort of person did just that.</p>

<h2 id="what-is-neptuneos">What is NeptuneOS?</h2>

<p>An operating system that I’ve been following for a while is NeptuneOS. The goal of this operating system is to implement a Windows NT ntdll.dll on top of the seL4 microkernel. MacOS and iOS both run on Mach, which was originally a pure microkernel, but traditional system calls were added later for performance reasons. The L4 microkernel is a next-gen successor to the Mach microkernel which solves a lot of the performance problems inherent in the previous generation. I don’t completely understand the differences, but Wikipedia has <a href="https://en.wikipedia.org/wiki/L4_microkernel_family">some explanations</a>. SeL4 is a variant of the L4 microkernel which has been proven correct, which means that it won’t crash or deadlock on non-faulty hardware, assuming the specification of the OS is correct.</p>

<p>When NeptuneOS is launched, the seL4 kernel is loaded. Next, a file called ntos is loaded, which contains the “root task”, which owns and manages the rest of the tasks. Once the system is booted, applications are started. Each application links to a library called ntdll.dll. On Linux, applications communicate with the kernel via system calls, which tell the operating system what to do. On Windows, ntdll.dll exposes an API which doesn’t change from version to version of Windows. This is nicer, IMO, because Microsoft can redesign the system calls without breaking the API of the operating system. Neptune currently shows a command prompt interface, but at some point a Windows-like desktop interface will be possible.</p>

<p>It occurs to me that you could build something like DOS on seL4, not taking advantage of the microkernel’s affordances for subtasks. It’s not clear to me when you are meant to spawn a subtask and communicate via messaging or shared memory and when you should use a function call in the same task. In iOS 7, the software keyboard transitioned from an-process library to a separate tasks, which caused stuttering during typing on some older phones. I’m sure there are dozens of examples with similar tradeoffs inside the implementation of ntdll.dll. In the next few weeks, I plan to investigate this. Maybe I’ll find code which has been made into separate tasks which could have been function calls.</p>

<h2 id="how-do-we-build-it">How do we build it?</h2>

<p>The remainder of this post will cover how to set up a Debian 12 (bookworm) system to build NeptuneOS from <a href="https://github.com/cl91/NeptuneOS">the sources on GitHub</a>.</p>

<p>First, we install all the packages we’ll need.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl git \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev \
libffi-dev liblzma-dev cmake jq ninja-build clang libxml2-utils \
cpio grub-common xorriso
</code></pre></div></div>

<p>Install pyenv, which will help manage multiple versions of Python.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl -fsSL https://pyenv.run | bash
</code></pre></div></div>

<p>List the versions of Python which are available.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pyenv install --list
</code></pre></div></div>

<p>Install Python 3.10.0. You probably don’t need to use exactly the same version if you don’t want to.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pyenv install 3.10.0
</code></pre></div></div>

<p>Set Python 3.10.0 for the local session. This will take a long time, as it’s compiling Python from source. You can also use global to affect all logins.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pyenv local 3.10.0
</code></pre></div></div>

<p>Create a virtual environment for the NeptuneOS build and activate it.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pyenv virtualenv 3.10.0 neptune
pyenv activate neptune
</code></pre></div></div>

<p>Install all the Python dependencies.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip install jinja2
pip install future
pip install ply
pip install setuptools
pip install six
pip install lxml
pip install pyyaml
</code></pre></div></div>

<p>Check out the repository.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone --recurse-submodules https://github.com/cl91/NeptuneOS.git
cd NeptuneOS
</code></pre></div></div>

<p>Check out the latest release.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout tags/v0.2.0002
</code></pre></div></div>

<p>On Debian, a lot of the LLVM utilities are suffixed with their major version, 14. I decided to fix this by making symlinks in <code class="language-plaintext highlighter-rouge">/opt/local/bin</code> for each tool.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /opt/local/bin
cd /opt/local/bin
ln -s `which llvm-ar-14` llvm-ar
ln -s `which lld-link-14` lld-link
ln -s `which llvm-objcopy-14` llvm-objcopy
ln -s `which ld.lld-14` ld.lld
ln -s `which llvm-strip-14` llvm-strip
cd
cd NeptuneOS
</code></pre></div></div>

<p>Once everything is done, the build should succeed.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>RC=`which llvm-rc-14` ./build.sh amd64 release
</code></pre></div></div>

<p>You’ll see this message when it’s finished building.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>####################################
		 Build successful!
####################################
</code></pre></div></div>

<p>Once that’s done, you need to build a CD image with the following command</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./mkiso.sh amd64 release
</code></pre></div></div>]]></content><author><name></name></author><category term="NeptuneOS" /><summary type="html"><![CDATA[In 2003, I got my first Mac and I heard that MacOS X ran on top of Mach, which is a microkernel. This started my whole “What’s a microkernel” thing, which has lived rent-free in my brain ever since. In 2016, I saw that QEMU had made an advent calendar with different computer architectures, which included a microkernel on day 11 called seL4. There’s a project called Genode, which is an operating system framework that can be run on top of various microkernels. I played around with Genode for a bit, but it didn’t spark joy, as it isn’t similar to other desktop experiences I’m used to. I wondered if someone could build a more familiar system on seL4, but I didn’t have the skillset to be that person. Later, a PH.D sort of person did just that.]]></summary></entry><entry><title type="html">Why a Snow Sequoia Won’t Help</title><link href="https://jonathangerlach.com/apple/2025/03/28/why-a-snow-sequoia-wont-help.html" rel="alternate" type="text/html" title="Why a Snow Sequoia Won’t Help" /><published>2025-03-28T10:28:00-04:00</published><updated>2025-03-28T10:28:00-04:00</updated><id>https://jonathangerlach.com/apple/2025/03/28/why-a-snow-sequoia-wont-help</id><content type="html" xml:base="https://jonathangerlach.com/apple/2025/03/28/why-a-snow-sequoia-wont-help.html"><![CDATA[<p>I’ve seen a couple posts online saying that Apple’s quality has diminished and that they need a release of their various operating systems which focuses on fixing bugs instead of adding new features. Back in the day, Apple got off track and was able to course correct by shipping Snow Leopard. The reason they got off track was that their implementations and intents were out of alignment. They really just needed to fix some bugs to fix the problem to get themselves back into alignment, where their intents and actions match.</p>

<p>That’s not what’s happening today. Modern Apple’s intent is malicious. They want to capture more and more of your hard-earned money. The old Apple built Time Machine, which was designed to scale to your needs. You could buy a hard drive and plug it in to implement the basic support for incremental backups. If you had a fast network and AFP, you could use a network share instead. This could be way faster and could support redundant storage, so your data was safe from losing a disk. It was a “Choose Your Own Adventure” of how you wanted to implement the solution with Apple’s protocol.</p>

<p>New Apple built iCloud Backup, which was designed to scale to <em>their</em> needs of ever-increasing profit. They control how much it costs and how it’s implemented. As the cost of implementing this backup decreases, they’re pocketing the difference. Over time, they’re providing the same amount of storage for their users, but they’re making more and more profit.</p>

<p>Across much of Apple’s ecosystem are tools and products which are increasingly designed to extract your wealth, instead of the original goal of being a creative professional’s tool. In order for Apple to fix their software, they’re going to need to course correct upstream of the software. The leaders of the company must set goals of valuing users’ creative potential above profitability and those intents need to trickle down to the team leads, and then finally to the actual code itself.</p>]]></content><author><name></name></author><category term="Apple" /><summary type="html"><![CDATA[I’ve seen a couple posts online saying that Apple’s quality has diminished and that they need a release of their various operating systems which focuses on fixing bugs instead of adding new features. Back in the day, Apple got off track and was able to course correct by shipping Snow Leopard. The reason they got off track was that their implementations and intents were out of alignment. They really just needed to fix some bugs to fix the problem to get themselves back into alignment, where their intents and actions match.]]></summary></entry><entry><title type="html">The War on C++ Island</title><link href="https://jonathangerlach.com/code/2024/10/24/war-on-cpp-island.html" rel="alternate" type="text/html" title="The War on C++ Island" /><published>2024-10-24T10:25:00-04:00</published><updated>2024-10-24T10:25:00-04:00</updated><id>https://jonathangerlach.com/code/2024/10/24/war-on-cpp-island</id><content type="html" xml:base="https://jonathangerlach.com/code/2024/10/24/war-on-cpp-island.html"><![CDATA[<p>In your tech journey, you hear a lot of takes. Some of them are bad takes, while others are misguided. About Ruby, I once heard “There are lots of good ideas in that language, but everything is implemented in the slowest way possible.” This is a quote from a C++ developer. If you have strong feelings about certain programming concepts being “natural”, your lizard brain is going to reject an idea that doesn’t fit. This is what happens to people who have C++ in their brain and they look at Ruby or Objective-C. They want to remove message passing so badly, but message passing is what makes it good, actually. If your mind is full of Ruby problem solving, you think things like “Computer time is cheaper than developer time”, which is horrible and gross from the C++ engineer’s standpoint. We need a way of accepting both statements as true, but in different contexts.</p>

<p>What I propose is that there are different places you can be in the programming universe. If you’re on C++ island, your truth is probably that lots of dynamic dispatch is bad and that types are good, but you can only take the type system so far before there are diminishing returns. The C++ community is full of people who all believe they’re in the same world, but they’re actually not. The community is fractured across a few core concepts being either good or bad. The truth is that most things contain both good and bad, but that’s another post. The divisive concepts are RAII, OOP, dynamic dispatch, exceptions, and more. There are probably thousands of distinct items you can argue about. One of my pet peeves is that C++ header files usually contain implementation details. Yuck. My preferred “C++” is using as little of these things as possible. A decade ago, Mike Acton gave <a href="https://www.youtube.com/watch?v=rX0ItVEVjHc">my favorite talk ever at CppCon</a>. He proposes that you mostly use C in C++ files. This is exactly what I do when I write C++. There are people lined up after the talk to explain how wrong he is. Building efficient system code goes beyond one intergalactic system language. You can’t describe all good system code in C++, so C++ can’t be the center of it all. I’ll come back to this in a bit.</p>

<p>There’s another island. The Alan Kay style OOP island (or maybe Adele Goldberg island) using late binding and message passing to build reusable software components which can snap together at runtime like Lego bricks. The reason I call out Alan Kay specifically is that his Smalltalk language used message passing instead of function calls and vtables. When you solve problems in this style, you use class clusters to break down a problem into its sub-problems. You think of the solution to a problem the same way you think of how you’d coordinate team members. Each person has a role and they communicate back and forth about their tasks. The great thing about this style of programming is that it maps to your own problem solving intuition. You can divide up the work and break it up among separate classes which coordinate to produce an output. This style of programming is distinct from others, which is why it lives on its own island. You will benefit from this style if you have a lot of business logic rules which map to human behavior. An example of a bad fit, which is my opinion BTW, is Apple’s CoreData. It was designed to be Alan Kay OOP, but is actually not a great fit because the problem itself is to get values from a database. You can trivially outperform CoreData with C functions which get the data. You don’t actually need class clusters to solve this problem.</p>

<p>Objective-C and C++ developers don’t really get along because the high-level code in Objective-C is actually from Alan Kay OOP island. It zero-cost bridges to C, which lives on C++ island. The fact that you have to be good at both programming methodologies to build certain types of apps is why Objective-C-based apps could be so good, but it’s also why it’s difficult to find people who can do that type of work.</p>

<p>There are more than just the two islands. Functional Programming is its own dinstinct island. You’ve probably seen people from this island showing up in your community. They’re known to be polyglots and are quite friendly, in my experience. There are truths from that island which are beneficial, so make sure to add some of these ideas to your brain if you want to.</p>

<p>Back to C++. An important thing to note here is that C++ island has never been just C++. It’s really a system code island. With Rust gaining popularity and getting to be a capable replacement for C and C++, it’s important that we change the name of the island in our hearts and minds. The real goal of this island all along is best described by Abner Coimbre in <a href="https://www.youtube.com/watch?v=Lzc3HcIgXis">this talk</a>. In the video, he says that good software is about transforming inputs into outputs in the most efficient way. I think this is completely true for games and operating systems, but not for all software. Note that Abner only really believes that C++ island exists and that everyone else is misguided.</p>

<p>A goal of mine is to always be kind to people who are entering your community and try to share space and power with them. Try to make some room for others. Be kind to Rust people who want to share this intellectual space with you. The best of the D programming language has been folded into C++ over the last decade or so. The same thing will happen with Rust. C++ can get optional lifetime tracking in the future and will be better for it.</p>]]></content><author><name></name></author><category term="Code" /><summary type="html"><![CDATA[In your tech journey, you hear a lot of takes. Some of them are bad takes, while others are misguided. About Ruby, I once heard “There are lots of good ideas in that language, but everything is implemented in the slowest way possible.” This is a quote from a C++ developer. If you have strong feelings about certain programming concepts being “natural”, your lizard brain is going to reject an idea that doesn’t fit. This is what happens to people who have C++ in their brain and they look at Ruby or Objective-C. They want to remove message passing so badly, but message passing is what makes it good, actually. If your mind is full of Ruby problem solving, you think things like “Computer time is cheaper than developer time”, which is horrible and gross from the C++ engineer’s standpoint. We need a way of accepting both statements as true, but in different contexts.]]></summary></entry><entry><title type="html">Home Lab Rough Draft</title><link href="https://jonathangerlach.com/homelab/2024/06/16/home-lab-rough-draft.html" rel="alternate" type="text/html" title="Home Lab Rough Draft" /><published>2024-06-16T13:56:00-04:00</published><updated>2024-06-16T13:56:00-04:00</updated><id>https://jonathangerlach.com/homelab/2024/06/16/home-lab-rough-draft</id><content type="html" xml:base="https://jonathangerlach.com/homelab/2024/06/16/home-lab-rough-draft.html"><![CDATA[<p>I’m getting a new circuit installed this week, so I can finally move my home lab off of my desk and into a small rack in the utility room. I haven’t decided most of the things I’ll be changing yet, but I wanted to show my current rough draft of my thoughts.</p>

<h2 id="home-lab-10-retrospective">Home Lab 1.0 — Retrospective</h2>

<p>Version 1 was a Supermicro SuperChassis (CSE-721TQ-250B) case with a mini-ITX Xeon-D board (Supermicro MBD-X10SDV-4C-TLN2F-O) with 32GB of RAM. It ran SmartOS (an <a href="https://www.illumos.org">illumos</a> distribution) and used a combination of SmartOS and LX (Linux compatibility mode) containers. Debian was used only where appropriate. Alpine was the “default Linux”. Anything that would be better solved by SmartOS (basically all problems) used SmartOS.</p>

<p>A major upside of this configuration was that all the data at rest was in a hardware redundant ZFS pool. Over the years, a few hard drives went bad, but I was able to replace them without losing data. A container acted as a file server for my Macs, so I didn’t need to buy expensive Apple hardware to get a lot of storage. Originally, this machine had 6TB of storage, but I outgrew that and I’m currently at 32TB. Another upside was that it was just one machine with many contanerized services. It sat on the corner of my desk and was almost entirely silent. It ran file services, DNS, a Minecraft server, various git repos, automated backups of cloud services, Plex, and many ephemeral containers for screwing around with compilers and new software development tools.</p>

<p>The big issues I had with this system were related to KVM/QEMU or bhyve. KVM support came out first and worked out pretty well for me. I created a Windows Server 2008 VM and used that with Remote Desktop to do a lot of my side projects over the years. When I moved to bhyve, I followed a lot of tutorials, but never got it working correctly. bhyve isn’t as integrated, so you have to manually create a virtual network and attach it to the VM. This isn’t difficult to do, but it’s not obvious and it’s not well documented. Even after getting your VM set up exactly correctly with a manual <code class="language-plaintext highlighter-rouge">bhyvectl</code> command and a ZFS volume for storage, there’s some magic I’m missing to properly integrate this into the <code class="language-plaintext highlighter-rouge">vmadm</code> tooling. If I create a bhyve VM and replace the ZFS volume with a copy of what I previously got working, something doesn’t work correctly and the VM doesn’t boot. VNC never comes up and there are no errors in the console. I’m sure if I was more experienced with bhyve, I could figure out why the VNC service never comes up, but I’m just not able to figure it out.</p>

<h2 id="home-lab-20--planning">Home Lab 2.0 — Planning</h2>

<p>My current system is pretty close to my ideal, but there are some untried and experimental solutions I want to test out before I commit to a new system. My only real constraints are that I want to stay in the same energy ballpark. I have a solar system and I’m committed to keeping my lifestyle within the bounds of net metering.</p>

<p><strong>Idea A</strong>: Oxide Computer created their own hyperscaler system that uses bhyve and illumos behind the scenes. I would like to use their API, but I want the backend to be either a cheap Xeon machine or a Turing Pi ARM64 machine. Maybe I could get both working. I need to follow the instructions and try to build an image that will boot. This isn’t impossible, so I will make an effort to get this working on my new home network. This is my ideal platform, but it technically doesn’t exist yet. The goal here is to do what Oxide is doing on a smaller scale. bhyve is higher overhead than I want, so I want to get this working with containers too. That might be beyond my capabilities, but I don’t know that yet.</p>

<p><strong>Idea B</strong>: k3s is a lightweight Kubernetes distribution, which works on ARM64 and x86_64 hardware. This is probably the easiest technology to switch to, but it will require me to use Kubernetes tooling, which I can do, but maybe I don’t want to? (Explain this better) Things aren’t automatically good because they’re new. They have to earn being good by succeeding at my specific use case. I’m just running a few things in my house with solar power. I don’t need full Kubernetes. If I cut down to a subset of Kubernetes, have I lost what makes it great? I don’t know the answer yet.</p>

<p><strong>Idea C</strong>: Proxmox is a VM solution, which is what I used before I switched to containers in 2008. I don’t really want to use VMs because they’re more overhead than containers. There are a lot of people who use Proxmox and VMs, so I want to make sure I investigate this option.</p>

<p><strong>Idea D</strong>: SmartOS is an OS for datacenter nodes. It’s made to be netbooted, but you can run it as a live CD from a USB disk. This is how I’m using it. It would be really easy for me to keep this as my solution for my homelab, but I want to at least consider all the other options before I commit to this.</p>]]></content><author><name></name></author><category term="Homelab" /><summary type="html"><![CDATA[I’m getting a new circuit installed this week, so I can finally move my home lab off of my desk and into a small rack in the utility room. I haven’t decided most of the things I’ll be changing yet, but I wanted to show my current rough draft of my thoughts.]]></summary></entry><entry><title type="html">First post!</title><link href="https://jonathangerlach.com/2024/05/13/first-post.html" rel="alternate" type="text/html" title="First post!" /><published>2024-05-13T17:57:24-04:00</published><updated>2024-05-13T17:57:24-04:00</updated><id>https://jonathangerlach.com/2024/05/13/first-post</id><content type="html" xml:base="https://jonathangerlach.com/2024/05/13/first-post.html"><![CDATA[<p>Hello! I’ve decided to start blogging and this is all I’ve got, so far.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Hello! I’ve decided to start blogging and this is all I’ve got, so far.]]></summary></entry></feed>