<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en" xml:base="https://osinachi.nwagboso.com/">
<title>Osinachi Nwagboso: Technical Journal</title>
<id>https://osinachi.nwagboso.com/blog/</id>
<link rel="self" type="application/atom+xml" href="https://osinachi.nwagboso.com/blog/feed.xml"/>
<link rel="alternate" type="text/html" href="https://osinachi.nwagboso.com/blog/"/>
<updated>2026-10-14T17:17:57.565446+00:00</updated>
<generator uri="https://github.com/sianachi/nix">Nix</generator>
<entry>
<title>Productivity: Nix (To be renamed)</title>
<id>https://osinachi.nwagboso.com/blog/productivity-nix-to-be-renamed/</id>
<link rel="alternate" type="text/html" href="https://osinachi.nwagboso.com/blog/productivity-nix-to-be-renamed/"/>
<published>2026-10-14T00:00:00+00:00</published>
<updated>2026-10-14T17:17:57.565446+00:00</updated>
<summary>I enjoy learning and building things, so naturally I got productivity-pilled: Notion, Obsidian, E-Ink tablets. Along the way I fell for heavy metal...</summary>
<content type="html">&lt;p&gt;I enjoy learning and building things, so naturally I got productivity-pilled: Notion, Obsidian, E-Ink tablets. Along the way I fell for heavy metal, game modding and Olympic weightlifting. (Not much carry-over, I know.) But it sparked something. I needed a way to organise my life.&lt;/p&gt;
&lt;p&gt;Every tool taught me something. Todoist taught me to run my hobbies as projects. Obsidian’s graph view taught me to think differently about notes and to journal with intent. Notion taught me that information shouldn’t be text alone.&lt;/p&gt;
&lt;p&gt;A few months later I needed pro features from five different tools, and I didn’t want to pay £100 a month just to be productive. So I built something that did everything I needed.&lt;/p&gt;
&lt;h4 id=&quot;everything-is-an-item&quot;&gt;Everything is an item&lt;a class=&quot;nix-anchor&quot; href=&quot;#everything-is-an-item&quot; aria-label=&quot;Link to Everything is an item&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In Nix, a note, a project, a reading list and a budget are all the same thing: an item with an optional body, properties and children. What changes is how you look at the children. The same tasks can be a list on Monday, a board on Tuesday and a calendar on Friday, with no copying. &lt;/p&gt;
&lt;p&gt;A body doesn’t have to be text, either. It can be a canvas for diagrams, or a spreadsheet with real A1 formulas. Notes support Mermaid diagrams, tables, callouts and columns.&lt;/p&gt;
&lt;h4 id=&quot;projects-links-and-journaling&quot;&gt;Projects, links and journaling&lt;a class=&quot;nix-anchor&quot; href=&quot;#projects-links-and-journaling&quot; aria-label=&quot;Link to Projects, links and journaling&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;From Todoist: tasks with due dates, priorities and recurrence, Today and Overdue views, push reminders with quiet hours, automations, and two-way sync with Google Calendar and Outlook.&lt;/p&gt;
&lt;p&gt;From Obsidian: &lt;code&gt;[[&lt;/code&gt; links, backlinks, a graph view with a time view, and daily notes that file themselves. There’s a Vim mode, and an Emacs mode, because I’m not a monster.&lt;/p&gt;
&lt;p&gt;I also built habit tracking with streaks, and finance tracking with budgets, bank CSV imports and a close-the-month checklist, which is the most adult thing I have ever built.&lt;/p&gt;
&lt;h4 id=&quot;ai-that-lives-in-my-notes&quot;&gt;AI that lives in my notes&lt;a class=&quot;nix-anchor&quot; href=&quot;#ai-that-lives-in-my-notes&quot; aria-label=&quot;Link to AI that lives in my notes&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This changed how I use Nix the most. I use AI to manage my notes, summarise my journals and pull insights from my weeks, months and year. Months of daily notes become something I can ask questions of.&lt;/p&gt;
&lt;p&gt;I self-host a lot of things, and my journal is the last thing I’d hand to another subscription app. So the AI lives inside Nix, on my server. You bring your own provider: Claude with an Anthropic API key, OpenRouter (including open-weight models), or, for now, a ChatGPT subscription.&lt;/p&gt;
&lt;p&gt;The AI is a companion pet that can search, write, reorganise and build structure. Ask for a training log and you get the container, fields and views, and the pets are genuinely good at picking the right view. They also have no special access: every action goes through my permissions, and every plan is shown to me before it runs. Through MCP, any other AI tool can work with my notes under the same rules.&lt;/p&gt;
&lt;p&gt;My favourite habit is asking the companion for feedback on its own tool usage: what was awkward and what it would change. An AI using your product all day is a very honest user. [Example: the companion pointed out that it struggled to produce the correct json format for the nix format and was just guessing]&lt;/p&gt;
&lt;h4 id=&quot;built-for-teams-and-for-building-itself&quot;&gt;Built for teams, and for building itself&lt;a class=&quot;nix-anchor&quot; href=&quot;#built-for-teams-and-for-building-itself&quot; aria-label=&quot;Link to Built for teams, and for building itself&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;A collaboration server gives Nix real-time editing with live cursors, plus roles and invitations, all enforced by the database rather than the browser. That makes it a solid home for a small team.&lt;/p&gt;
&lt;p&gt;It’s also where I build Nix. My dev notes, plans, decisions and Mermaid architecture diagrams all live in Nix, and through &lt;code&gt;nixctl&lt;/code&gt; and MCP, my coding agents read the same docs I do. If something annoys me, it gets fixed, because I’ll hit it again tomorrow.&lt;/p&gt;
&lt;h4 id=&quot;a-playground-for-platform-engineering&quot;&gt;A playground for platform engineering&lt;a class=&quot;nix-anchor&quot; href=&quot;#a-playground-for-platform-engineering&quot; aria-label=&quot;Link to A playground for platform engineering&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Nix runs on an ARM64 NVIDIA box in my homelab, and it taught me platform engineering properly:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;CI builds everything.&lt;/strong&gt; Multi-arch images, tagged with the full commit SHA. No &lt;code&gt;latest&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Releases are boring on purpose.&lt;/strong&gt; A drift preview first, migrations as isolated jobs, and a smoke test that checks real exported files. A green health check is not a successful deployment.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backups are tested.&lt;/strong&gt; Nightly, verified, encrypted off-site to Cloudflare R2.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deleting is a skill.&lt;/strong&gt; I retired OpenSearch, MinIO and a monitoring stack. Every service you run is one you have to back up and secure.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h4 id=&quot;this-blog-is-a-note&quot;&gt;This blog is a note&lt;a class=&quot;nix-anchor&quot; href=&quot;#this-blog-is-a-note&quot; aria-label=&quot;Link to This blog is a note&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;You’re reading Nix right now. Any page tree can be published as a static site. My blog, portfolio and the Nix docs are all just notes.&lt;/p&gt;
&lt;p&gt;Even the website for the product is written in Nix: &lt;a href=&quot;https://nix.nixsites.com/&quot; rel=&quot;noopener noreferrer&quot;&gt;https://nix.nixsites.com/&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;what-s-next&quot;&gt;What’s next&lt;a class=&quot;nix-anchor&quot; href=&quot;#what-s-next&quot; aria-label=&quot;Link to What’s next&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Nix is v0.1, and I want it to be a premium product. Friction irritates me, and in beta I’m the one feeling it most.&lt;/p&gt;
&lt;p&gt;First, a cleaner desktop UI. Second, a native mobile app. The PWA’s offline support is my biggest pain point: it only keeps notes I’ve already opened, and the browser decides how long to keep them. I want my whole life available on a train with no signal. I’m deciding between React Native and fully native, with Swift first and Kotlin later.&lt;/p&gt;
&lt;p&gt;Android matters for one more reason: my E-Ink tablet runs it. Journaling on E-Ink, synced to my own server, is the setup I wanted when I first got productivity-pilled.&lt;/p&gt;
&lt;h4 id=&quot;the-catch&quot;&gt;The catch&lt;a class=&quot;nix-anchor&quot; href=&quot;#the-catch&quot; aria-label=&quot;Link to The catch&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Nix is self-hosted and isn’t small yet, and it needs a new name, because Nix is taken by a famous package manager. Suggestions welcome.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s still rough around the edges and still needs a couple of months before it&amp;#39;s the premium product that I&amp;#39;m currently dreaming of but this is a great start and it&amp;#39;s already very useful to me.&lt;/p&gt;</content>
</entry>
<entry>
<title>AI as a layer of abstraction</title>
<id>https://osinachi.nwagboso.com/blog/ai-as-a-layer-of-abstraction/</id>
<link rel="alternate" type="text/html" href="https://osinachi.nwagboso.com/blog/ai-as-a-layer-of-abstraction/"/>
<published>2026-06-28T00:00:00+00:00</published>
<updated>2026-10-12T16:10:56.939291+00:00</updated>
<summary>I wrote this website&#39;s backend in a fictional language</summary>
<category term="glang"/>
<category term="c"/>
<category term="claude-code"/>
<content type="html">&lt;p&gt;I started developing software when I was about 9 years old and one thing I have always wanted to make is my own programming language. My first attempt was a C style language that made use of XML style tags. This was not by conscious design, I just didn&amp;#39;t know how to make a proper parser so I used Regex and the tags made it easier to cheat.&lt;/p&gt;
&lt;figure class=&quot;nix-figure&quot;&gt;&lt;img src=&quot;/_nix/assets/5a5c447a74427129de9c3a2b01b1cb87fc22315ff886d3f603a0e8b0c87ea2f8.png&quot; alt=&quot;1782644305942-Screenshot-2026-06-28-at-11-57-45&quot; width=&quot;552&quot; height=&quot;425&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/figure&gt;
&lt;p&gt;Another difficulty that I faced was handling scopes recursively so I designed the language to support exactly one scope and made all the statements separated by &amp;quot;|&amp;quot; because the parser would see &amp;quot;;&amp;quot; as the end of a statement and the interpreter would just crash.&lt;/p&gt;
&lt;p&gt;Additional context: This was just before I started my undergraduate degree.&lt;/p&gt;
&lt;p&gt;Fast forward 8 years, I have by computer science degrees and work experience and Claude code. At this point, I also know the features I like from different languages, link Linq from c# or union types from typescript or C. I decided to bring G (Gnosis meaning knowledge) back to life so I did and I got help from the AI and we came up with something beautiful.&lt;/p&gt;
&lt;p&gt;Here is a platform to learn GLang: &lt;a href=&quot;https://glang.nwagboso.com/&quot; rel=&quot;noopener noreferrer&quot;&gt;Glang Link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The platform has:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;p&gt;A fully functional language server&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;A playground where you can play with the language&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;and lessons because why not&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;and the backend was written in Glang: &lt;a href=&quot;https://github.com/sianachi/Glang&quot; rel=&quot;noopener noreferrer&quot;&gt;Glang Source Code&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;nix-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Link to Conclusion&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This experiment had me thinking about the state of software development because I wrote a fullstack application in a fictional programming language. My gnosis (pun intended) is that all programming languages are fictional and the orchestration of AI could just be another higher layer of abstraction some day and that&amp;#39;s okay.&lt;/p&gt;</content>
</entry>
<entry>
<title>Why Your Jetson Won&#39;t Stay Bricked (Probably)</title>
<id>https://osinachi.nwagboso.com/blog/why-your-jetson-won-t-stay-bricked-probably/</id>
<link rel="alternate" type="text/html" href="https://osinachi.nwagboso.com/blog/why-your-jetson-won-t-stay-bricked-probably/"/>
<published>2026-06-17T00:00:00+00:00</published>
<updated>2026-10-12T16:10:53.027729+00:00</updated>
<summary>I always wondered what WSL (Windows Subsystem for Linux) was actually for. Why not just use Linux? It always felt like a strange amount of work to...</summary>
<category term="wsl"/>
<category term="nvidia"/>
<category term="cuda"/>
<content type="html">&lt;p&gt;I always wondered what WSL (Windows Subsystem for Linux) was actually for.&lt;/p&gt;
&lt;p&gt;Why not just use Linux? It always felt like a strange amount of work to avoid buying a cheap ThinkPad, dual booting, or spinning up a VM. I never really saw the point. Then I started working with Jetsons.&lt;/p&gt;
&lt;p&gt;For context, we use quite a few of them at work because a lot of what we do involves AI at the edge. Vehicle tracking, image processing, and inference running somewhere that doesn&amp;#39;t have the luxury of shoving everything into the cloud. CUDA has always been a bit of a pain in this space. It has improved considerably with CUDA 12, but there are still enough moving parts that cause people pain.&lt;/p&gt;
&lt;p&gt;We also work with the Home Office, which means once something has been deployed it doesn&amp;#39;t move very quickly. If a system was validated on a particular JetPack release, there is a decent chance it stays there for quite a while. That&amp;#39;s how you end up supporting several JetPack versions at the same time instead of simply upgrading everything and forgetting about it.&lt;/p&gt;
&lt;h3 id=&quot;the-version-problem-nobody-mentions&quot;&gt;The version problem nobody mentions&lt;a class=&quot;nix-anchor&quot; href=&quot;#the-version-problem-nobody-mentions&quot; aria-label=&quot;Link to The version problem nobody mentions&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;NVIDIA ties JetPack releases fairly closely to host Ubuntu versions.&lt;/p&gt;
&lt;p&gt;JetPack Host Ubuntu 4.x - 18.04, 5.x - 20.04, 6.x - 22.04&lt;/p&gt;
&lt;p&gt;That sounds harmless until you&amp;#39;re supporting several projects at once.&lt;/p&gt;
&lt;p&gt;Without WSL, your options are fairly uninspiring.&lt;/p&gt;
&lt;div class=&quot;nix-table&quot; role=&quot;region&quot; aria-label=&quot;Table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;&lt;p&gt;Approach&lt;/p&gt;&lt;/th&gt;&lt;th&gt;&lt;p&gt;Reality&lt;/p&gt;&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Dedicated flashing machine&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Works, but you&amp;#39;ve committed an entire system to one purpose.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Multiple partitions&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Fine until you&amp;#39;re rebooting several times a day.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Several old laptops&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Also works, but no one wants a growing pile of Ubuntu machines under their desk.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Virtual machines&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Sounds sensible until USB passthrough starts behaving unpredictably halfway through a flash.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;WSL&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Open an 18.04 shell, do the flash, close it, then move to 20.04 or 22.04 when needed. Or even have all devices being flashed at the same time (Don&amp;#39;t forget to use Usbpid to make the USB visible to WSL.)&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h3 id=&quot;you-usually-don-t-touch-flash-sh&quot;&gt;You usually don&amp;#39;t touch &lt;a href=&quot;http://flash.sh&quot; rel=&quot;noopener noreferrer&quot;&gt;flash.sh&lt;/a&gt;&lt;a class=&quot;nix-anchor&quot; href=&quot;#you-usually-don-t-touch-flash-sh&quot; aria-label=&quot;Link to You usually don&amp;#39;t touch flash.sh&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Another thing that surprised me when I started was how little people actually interact with &lt;a href=&quot;http://flash.sh&quot; rel=&quot;noopener noreferrer&quot;&gt;flash.sh&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;SDK Manager does most of the work.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;p&gt;It downloads the BSP.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It prepares the root filesystem.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It invokes the flashing tools.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Most people probably never even notice the underlying commands.&lt;/p&gt;
&lt;p&gt;That changes fairly quickly once custom hardware appears.&lt;/p&gt;
&lt;p&gt;A lot of carrier board vendors provide their own patches, device trees, kernel tweaks, pin mux settings, or partition layouts. At some point someone sends you a tarball and a PDF containing instructions that basically translate to:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Please read this carefully because support does not want to talk to you tomorrow.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That patch file isn&amp;#39;t optional.&lt;/p&gt;
&lt;p&gt;Skip it, apply the wrong one, or patch the wrong L4T version and you suddenly have a £3,000 box that doesn&amp;#39;t boot.&lt;/p&gt;
&lt;p&gt;The really frustrating bit is that it often doesn&amp;#39;t tell you why it doesn&amp;#39;t boot because the thing that would normally explain what is wrong was part of the thing you forgot to patch.&lt;/p&gt;
&lt;h3 id=&quot;jetsons-are-harder-to-brick-than-people-think&quot;&gt;Jetsons are harder to brick than people think&lt;a class=&quot;nix-anchor&quot; href=&quot;#jetsons-are-harder-to-brick-than-people-think&quot; aria-label=&quot;Link to Jetsons are harder to brick than people think&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The good news is that Jetsons are surprisingly forgiving.Most failed flashes aren&amp;#39;t actually bricks. They just end up back in recovery mode waiting for another attempt.&lt;/p&gt;
&lt;p&gt;The failure modes usually look something like this.&lt;/p&gt;
&lt;div class=&quot;nix-table&quot; role=&quot;region&quot; aria-label=&quot;Table&quot; tabindex=&quot;0&quot;&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;&lt;p&gt;What went wrong?&lt;/p&gt;&lt;/th&gt;&lt;th&gt;&lt;p&gt;Can recovery mode save it?&lt;/p&gt;&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Corrupted root filesystem&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Wrong device tree&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Half written bootloader&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Bad kernel image&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Incorrect partition layout&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Usually&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;Burned security fuses&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Force Recovery Mode lives in the BootROM. It&amp;#39;s part of the silicon itself, not something stored in eMMC, QSPI, or Linux.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;p&gt;Broken root filesystem?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Wrong device tree?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Half written bootloader?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It doesn&amp;#39;t really care.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Put the board back into recovery mode and it&amp;#39;ll sit there patiently&lt;/p&gt;
&lt;h3 id=&quot;the-takeaway&quot;&gt;The takeaway&lt;a class=&quot;nix-anchor&quot; href=&quot;#the-takeaway&quot; aria-label=&quot;Link to The takeaway&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;WSL finally made sense to me once I stopped thinking about it as &amp;quot;Linux on Windows.&amp;quot;&lt;/p&gt;
&lt;p&gt;For Jetson development, it&amp;#39;s more like having three Ubuntu machines stuffed into one laptop.&lt;/p&gt;
&lt;p&gt;That isn&amp;#39;t obvious from Microsoft&amp;#39;s marketing, and it certainly isn&amp;#39;t obvious from NVIDIA&amp;#39;s documentation.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s just one of those things you eventually appreciate after flashing your fifth board on a Tuesday afternoon and noticing that you haven&amp;#39;t rebooted your workstation once.&lt;/p&gt;</content>
</entry>
<entry>
<title>The admin panel has no password</title>
<id>https://osinachi.nwagboso.com/blog/the-admin-panel-has-no-password/</id>
<link rel="alternate" type="text/html" href="https://osinachi.nwagboso.com/blog/the-admin-panel-has-no-password/"/>
<published>2026-04-30T00:00:00+00:00</published>
<updated>2026-10-12T16:10:52.861728+00:00</updated>
<summary>The management side of this site has no password. I didn&#39;t replace authentication with nothing, though — I replaced it with passkeys. A look at when a password is actually doing security work, and when it&#39;s just there because we expect it to be.</summary>
<category term="passkeys"/>
<category term="1password"/>
<category term="auth"/>
<content type="html">&lt;p&gt;I&amp;#39;ve been building this site as a creative outlet, a place to ship something for myself and stretch into web design a bit more. I&amp;#39;m a backend developer in my day job, so getting properly hands-on with React and Svelte has been a nice change of pace (a topic for another day). The &lt;a href=&quot;https://osinachi.nwagboso.com/blog/my-k3s-experience&quot; rel=&quot;noopener noreferrer&quot;&gt;previous post&lt;/a&gt; covered how it gets deployed onto my K3s cluster. This one is about a smaller decision I made along the way.&lt;/p&gt;
&lt;p&gt;The management side of the site has no password.&lt;/p&gt;
&lt;p&gt;That sentence reads worse than it is. I didn&amp;#39;t replace authentication with nothing. I replaced it with passkeys. There&amp;#39;s still a strong cryptographic check between me and the admin interface, it just isn&amp;#39;t a string I have to remember. The more I sat with the decision, the more it became a useful lens on a question I don&amp;#39;t think we ask often enough: when is a password actually doing security work, and when is it just there because we expect it to be?&lt;/p&gt;
&lt;h3 id=&quot;where-passwords-start-to-be-theatre&quot;&gt;Where passwords start to be theatre&lt;a class=&quot;nix-anchor&quot; href=&quot;#where-passwords-start-to-be-theatre&quot; aria-label=&quot;Link to Where passwords start to be theatre&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Passwords are the default for good reasons. They&amp;#39;re universally understood, work on any device, and are easy to provision. For a system with many users and varied threat models, a password backed by a manager and a second factor is a sensible floor.&lt;/p&gt;
&lt;p&gt;But passwords carry failure modes that have nothing to do with how strong the password itself is. They get phished. They get reused. They get leaked in breaches of unrelated services and sprayed at every login form on the internet. A password on a single-user admin panel, defended only by &amp;quot;I am the only one who knows it,&amp;quot; is doing less work than it appears to be. The strength of that control isn&amp;#39;t really the password. It&amp;#39;s the obscurity of the URL plus my personal vigilance, and neither belongs in a threat model with a straight face.&lt;/p&gt;
&lt;h3 id=&quot;what-passkeys-change&quot;&gt;What passkeys change&lt;a class=&quot;nix-anchor&quot; href=&quot;#what-passkeys-change&quot; aria-label=&quot;Link to What passkeys change&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Passkeys are a different shape of control. The private key never leaves my device. The challenge is bound to the origin, so a phishing site can&amp;#39;t replay it against the real one. There&amp;#39;s no shared secret sitting in a database to leak. And the UX is better than a password: Touch ID and I&amp;#39;m in.&lt;/p&gt;
&lt;p&gt;For a single-user admin interface, this is a near-perfect fit. The threat I actually care about is someone on the internet reaching my admin panel, and passkeys make that materially harder than a password would while removing phishing almost entirely.&lt;/p&gt;
&lt;p&gt;The obvious caveat: passkeys are tied to devices, so you need a recovery story. I use 1Password for sync, which keeps them portable across the machines I actually use.&lt;/p&gt;
&lt;h3 id=&quot;so-when-is-a-password-the-right-call&quot;&gt;So when is a password the right call?&lt;a class=&quot;nix-anchor&quot; href=&quot;#so-when-is-a-password-the-right-call&quot; aria-label=&quot;Link to So when is a password the right call?&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I don&amp;#39;t want to land on &amp;quot;passwords are bad.&amp;quot; That&amp;#39;s the wrong takeaway. A password is a tool with a specific shape, and you pick it when the shape fits.&lt;/p&gt;
&lt;p&gt;It fits when you have many users on heterogeneous devices, when you can&amp;#39;t guarantee passkey support, or when you need a credential that can be handed off out-of-band. It&amp;#39;s theatre when it&amp;#39;s the only control on a high-value surface, when users will inevitably reuse it, or when something stronger (passkeys, mTLS, a network boundary, SSO) is genuinely available and you&amp;#39;re defaulting to a password out of habit.&lt;/p&gt;
&lt;h3 id=&quot;the-actual-lesson&quot;&gt;The actual lesson&lt;a class=&quot;nix-anchor&quot; href=&quot;#the-actual-lesson&quot; aria-label=&quot;Link to The actual lesson&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My decision wasn&amp;#39;t &amp;quot;skip the password because it&amp;#39;s annoying.&amp;quot; It was &amp;quot;the threat I&amp;#39;m defending against is internet-scale credential abuse, and there&amp;#39;s a control that handles that better than a password does.&amp;quot; The fact that it&amp;#39;s also more pleasant is a bonus, not the justification.&lt;/p&gt;
&lt;p&gt;Hardening systems is mostly about being honest about what each control does. A password you can&amp;#39;t be bothered to remember isn&amp;#39;t hardening anything. It&amp;#39;s just a worse version of the control you&amp;#39;d pick if you were thinking clearly.&lt;/p&gt;</content>
</entry>
<entry>
<title>Kubernetes made my life easier</title>
<id>https://osinachi.nwagboso.com/blog/my-k3s-experience/</id>
<link rel="alternate" type="text/html" href="https://osinachi.nwagboso.com/blog/my-k3s-experience/"/>
<published>2026-04-26T00:00:00+00:00</published>
<updated>2026-10-12T16:10:52.694101+00:00</updated>
<summary>I was going to deploy my portfolio to Vercel until I hit the free-tier limit: 11 serverless functions. The next tier was £20 a month. I already pay £10 for a VPS that was sitting idle, so I stopped renting someone else&#39;s abstraction and ran k3s on my own.</summary>
<category term="infastructure"/>
<category term="k3s"/>
<category term="vercel"/>
<content type="html">&lt;p&gt;I&amp;#39;ve started taking my personal projects more seriously, which means I&amp;#39;ve been doing a lot more deployment than I used to.&lt;/p&gt;
&lt;p&gt;For a while, the workflow was simple: write a &lt;code&gt;docker-compose.yml&lt;/code&gt;, push it to my VPS, deploy through Portainer. Fine on paper. In practice, every deployment was a frenzy. SSL certificates misbehaved. One service would come up while another silently failed. I&amp;#39;d forget which compose flag I needed this time. No matter how often I did it, something was always slightly broken, and the fix was always slightly different from last time.&lt;/p&gt;
&lt;p&gt;Eventually I came across k3s: a lightweight Kubernetes distribution that ships as a single binary.&lt;/p&gt;
&lt;h3 id=&quot;the-detour-that-pushed-me-over-the-edge&quot;&gt;The detour that pushed me over the edge&lt;a class=&quot;nix-anchor&quot; href=&quot;#the-detour-that-pushed-me-over-the-edge&quot; aria-label=&quot;Link to The detour that pushed me over the edge&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I was originally going to deploy my new portfolio to Vercel. Then I hit the limit: 11 serverless functions per project on the free tier. The portfolio itself is simple, but I wanted a blog attached for technical writeups, and that pushed me over. The next tier was £20 a month.&lt;/p&gt;
&lt;p&gt;I already pay £10 a month for a VPS that was sitting mostly idle. So I stopped renting someone else&amp;#39;s abstraction and ran my own.&lt;/p&gt;
&lt;h3 id=&quot;the-stack&quot;&gt;The stack&lt;a class=&quot;nix-anchor&quot; href=&quot;#the-stack&quot; aria-label=&quot;Link to The stack&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The portfolio is straightforward, but the blog adds a few moving parts:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;p&gt;MinIO for S3-compatible object storage (blog images, assets)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;MongoDB for blog content&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Express.js API&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;React frontend&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Under docker-compose, that&amp;#39;s four services wired together imperatively, plus a reverse proxy, plus whatever I cobble together for TLS. Under k3s, it&amp;#39;s four manifests. Traefik handles ingress out of the box. cert-manager handles SSL declaratively. I describe what I want; the cluster makes it true.&lt;/p&gt;
&lt;p&gt;That&amp;#39;s the shift. Compose tells the machine what to do. Kubernetes tells it what should be true. When something drifts, the cluster pulls it back. When I redeploy, I&amp;#39;m not hoping the previous state cleaned up properly. I&amp;#39;m declaring the new one.&lt;/p&gt;
&lt;h3 id=&quot;how-it-actually-went&quot;&gt;How it actually went&lt;a class=&quot;nix-anchor&quot; href=&quot;#how-it-actually-went&quot; aria-label=&quot;Link to How it actually went&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Smoothly. I deployed the whole thing from my laptop with &lt;code&gt;kubectl&lt;/code&gt;, pointed at the cluster on my VPS. Certificates issued themselves through cert-manager and Let&amp;#39;s Encrypt. No frenzy.&lt;/p&gt;
&lt;p&gt;The first deploy took longer than a compose file would have. Every deploy since has been faster, more predictable, and easier to reason about.&lt;/p&gt;
&lt;h3 id=&quot;why-this-matters-for-solo-devs&quot;&gt;Why this matters for solo devs&lt;a class=&quot;nix-anchor&quot; href=&quot;#why-this-matters-for-solo-devs&quot; aria-label=&quot;Link to Why this matters for solo devs&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The pitch for Kubernetes is almost always about scale: surviving a Hacker News hug of death, autoscaling across regions, surviving node failures at 3am. None of that applies to me. I have one VPS and not many users.&lt;/p&gt;
&lt;p&gt;What I got instead:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;p&gt;Declarative management. Cluster state lives in a Git repo. Everything is version-controlled.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Quick deployments. &lt;code&gt;kubectl apply -f&lt;/code&gt; and walk away.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Consistent output. The cluster converges to what the manifests say. No more &amp;quot;works on my VPS.&amp;quot;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Kubernetes isn&amp;#39;t just about scale. For a solo dev, it&amp;#39;s about not having to remember things. The cluster remembers for you.&lt;/p&gt;</content>
</entry>
</feed>
