<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ai-Generated on Marcello Barnaba</title>
    <link>https://sindro.me/tags/ai-generated/</link>
    <description>Recent content in Ai-Generated on Marcello Barnaba</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 07 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://sindro.me/tags/ai-generated/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>How I Used Claude to Completely Revamp My Blog in Two Days</title>
      <link>https://sindro.me/posts/2026-04-07-how-i-used-claude-to-revamp-my-blog/</link>
      <pubDate>Tue, 07 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2026-04-07-how-i-used-claude-to-revamp-my-blog/</guid>
      <description>&lt;p&gt;It&amp;rsquo;s like having an incredibly fast, skilled, and thorough engineer sitting next to you — one that really allows your creativity to flow without borders. You say &amp;ldquo;what if we&amp;hellip;&amp;rdquo; and 30 seconds later you&amp;rsquo;re looking at a working prototype. You go &amp;ldquo;no, more like this&amp;rdquo; and it&amp;rsquo;s done before you finish explaining why.&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s what working with &lt;a href=&#34;https://claude.ai/code&#34; target=&#34;_blank&#34;&gt;Claude Code&lt;/a&gt; felt like over the past two days. I completely revamped this blog — translated all 69 posts to Italian, redesigned the layout from the ground up, added a nerdy boot sequence easter egg, cleaned up years of tag cruft, and iterated through dozens of design decisions. All of it tracked in git, all of it reviewable, all of it live.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Every single commit is public.&lt;/strong&gt; If you want to see the raw process — the brainstorming, the iterations, the bugfixes, the back-and-forth — it&amp;rsquo;s all in the repo: &lt;strong&gt;&lt;a href=&#34;https://github.com/vjt/sindro.me&#34; target=&#34;_blank&#34;&gt;github.com/vjt/sindro.me&lt;/a&gt;&lt;/strong&gt; (and the theme fork: &lt;a href=&#34;https://github.com/vjt/hugo-sindrome-theme&#34; target=&#34;_blank&#34;&gt;github.com/vjt/hugo-sindrome-theme&lt;/a&gt;). I&amp;rsquo;m not ashamed of showing how the sausage is made. If anything, I hope someone finds it useful as a learning resource for what AI-assisted development actually looks like in practice — warts and all.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s my GitHub contribution graph to prove I&amp;rsquo;m not exaggerating:&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://sindro.me/posts/2026-04-07-how-i-used-claude-to-revamp-my-blog/github-activity.png&#34; alt=&#34;GitHub activity showing a storm of commits&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;That green wall is 40 days of working with Claude across a bunch of projects — &lt;a href=&#34;https://sindro.me/posts/2026-04-04-verisure-italy-home-assistant/&#34;&gt;home automation integrations&lt;/a&gt;, &lt;a href=&#34;https://sindro.me/posts/2026-04-03-wifi-dethrash-openwrt-mesh-analyzer/&#34;&gt;OpenWrt networking tools&lt;/a&gt;, &lt;a href=&#34;https://sindro.me/posts/2026-02-15-wifi-presence-detection-home-assistant/&#34;&gt;WiFi presence detection&lt;/a&gt;, &lt;a href=&#34;https://sindro.me/posts/2026-01-31-quectel-5g-modem-tools-for-openwrt/&#34;&gt;5G modem tooling&lt;/a&gt;, and this blog redesign. The last two days alone account for a ridiculous chunk of it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-starting-point&#34;&gt;The starting point&lt;/h2&gt;&#xA;&lt;p&gt;This blog has been around since 2007, but the Hugo version dates back to 2023 when I migrated from WordPress. It ran the &lt;a href=&#34;https://github.com/lukeorth/poison&#34; target=&#34;_blank&#34;&gt;Poison theme&lt;/a&gt; (now &lt;a href=&#34;https://github.com/vjt/hugo-sindrome-theme&#34; target=&#34;_blank&#34;&gt;Sindrome&lt;/a&gt;) — a fork of Hyde/Poole — with a dark sidebar, English only, and a layout that screamed &amp;ldquo;2015 called, they want their CSS back.&amp;rdquo;&lt;/p&gt;</description>
    </item>
    <item>
      <title>How I replaced the Verisure app with Home Assistant</title>
      <link>https://sindro.me/posts/2026-04-04-verisure-italy-home-assistant/</link>
      <pubDate>Sat, 04 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2026-04-04-verisure-italy-home-assistant/</guid>
      <description>&lt;p&gt;The Verisure app is garbage. There, I said it.&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s not that the alarm itself is bad — the SDVECU panel is solid, the&#xA;sensors are reliable, the installation is professional. But the app. Good&#xA;lord, the app.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-problem&#34;&gt;The problem&lt;/h2&gt;&#xA;&lt;p&gt;You open the app to check your alarm status and you&amp;rsquo;re greeted by &lt;strong&gt;an ad&#xA;for Verisure itself&lt;/strong&gt;. I pay through the nose for the service and they&#xA;shove ads &lt;em&gt;inside&lt;/em&gt; the app. It&amp;rsquo;s 2026 and a security company is showing me&#xA;banner ads when I&amp;rsquo;m trying to verify that my house is protected.&lt;/p&gt;&#xA;&lt;p&gt;But the ads are the least of it. The real problems are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Blind routines.&lt;/strong&gt; Yes, the app has &amp;ldquo;routines&amp;rdquo; — arm at midnight,&#xA;disarm at 7. But they have no idea where you are. It&amp;rsquo;s midnight&#xA;and you&amp;rsquo;re still in the garden? The alarm arms and the sensors&#xA;go off. Window open? The panel announces it can&amp;rsquo;t arm, but if you&#xA;don&amp;rsquo;t hear it the alarm stays disarmed. Go on vacation and forget&#xA;to disable the morning disarm routine? Alarm off with an empty&#xA;house. And routine changes take &lt;em&gt;20 minutes to propagate&lt;/em&gt; — &amp;ldquo;or&#xA;the next day&amp;rdquo;. In 2026.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Zero presence awareness.&lt;/strong&gt; The app doesn&amp;rsquo;t know where you are.&#xA;It doesn&amp;rsquo;t know who&amp;rsquo;s home. It doesn&amp;rsquo;t know if the cleaning lady&#xA;has left. No location-based automation whatsoever.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;One camera at a time.&lt;/strong&gt; Want to see all your cameras? Tap, wait,&#xA;go back, tap the next one, wait. No overview. No &amp;ldquo;capture all&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Biblically slow.&lt;/strong&gt; Request an image, wait, wait, maybe it arrives.&#xA;Sometimes you reload the app and try again. In 2026.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;No permanent storage.&lt;/strong&gt; Captured images vanish. There&amp;rsquo;s no&#xA;browsable history.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;No timestamps on images.&lt;/strong&gt; You capture a photo and you don&amp;rsquo;t know&#xA;&lt;em&gt;when&lt;/em&gt; it was taken or &lt;em&gt;which camera&lt;/em&gt; took it. You have to&#xA;remember. For a security system, that&amp;rsquo;s embarrassing.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Generic notifications.&lt;/strong&gt; One notification, same for everyone. No&#xA;actionable notifications, no critical alerts that bypass Do Not&#xA;Disturb.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;What I wanted: my alarm, integrated into my smart home, with intelligent&#xA;automations, notifications for all residents, and a dashboard that shows&#xA;&lt;em&gt;everything&lt;/em&gt; at a glance. No ads.&lt;/p&gt;</description>
    </item>
    <item>
      <title>wifi-dethrash: Finding and Fixing WiFi Mesh Thrashing on OpenWrt</title>
      <link>https://sindro.me/posts/2026-04-03-wifi-dethrash-openwrt-mesh-analyzer/</link>
      <pubDate>Fri, 03 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2026-04-03-wifi-dethrash-openwrt-mesh-analyzer/</guid>
      <description>&lt;p&gt;It started with &lt;a href=&#34;https://sindro.me/posts/2026-02-15-wifi-presence-detection-home-assistant/&#34;&gt;WiFi presence detection&lt;/a&gt;. I had built a system that tracks which room everyone is in by scraping RSSI from my OpenWrt APs. It worked — but the room assignments kept flickering. Kitchen. Office. Kitchen. Office. Three times in ten seconds. The state machine was fine. The WiFi wasn&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;p&gt;My home network runs six OpenWrt APs across three floors, two SSIDs — Mercury on 5 GHz, Saturn on 2.4 GHz — all backed by 802.11r for fast roaming. From the outside, it looks like a proper mesh. From the inside, one phone was bouncing between access points &lt;strong&gt;129 times in 24 hours&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I didn&amp;rsquo;t know this until I built the tool to see it.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://sindro.me/posts/2026-04-03-wifi-dethrash-openwrt-mesh-analyzer/roaming-timeline-24h.png&#34; alt=&#34;Roaming Timeline — 24 hours&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Each row is a WiFi client, the color shows which AP it&amp;rsquo;s connected to. Healthy clients show long solid bars. Sick ones look like barber poles. See &lt;code&gt;sara-iphone&lt;/code&gt;? That rainbow stripe is 129 connects in 24 hours — the phone is walking through an overlap zone between two APs where both have roughly equal (and terrible) signal.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-problem-you-cant-see&#34;&gt;The Problem You Can&amp;rsquo;t See&lt;/h2&gt;&#xA;&lt;p&gt;WiFi roaming is invisible. Your phone shows full bars, Netflix buffers for a moment, and you blame the internet. But what actually happened is your phone disconnected from one AP, scanned for alternatives, picked another one with a marginally different signal, associated, authenticated, and started streaming again — all in under a second if 802.11r is working, several seconds if it&amp;rsquo;s not.&lt;/p&gt;&#xA;&lt;p&gt;Do this 15 times in 2 minutes between two APs that both have garbage signal, and you get what I call &lt;strong&gt;thrashing&lt;/strong&gt;: rapid, pointless AP bouncing that kills throughput and wastes airtime.&lt;/p&gt;</description>
    </item>
    <item>
      <title>WiFi Presence Detection for Home Assistant Using OpenWrt</title>
      <link>https://sindro.me/posts/2026-02-15-wifi-presence-detection-home-assistant/</link>
      <pubDate>Sun, 15 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2026-02-15-wifi-presence-detection-home-assistant/</guid>
      <description>&lt;p&gt;I had two problems with Home Assistant&amp;rsquo;s presence detection.&lt;/p&gt;&#xA;&lt;p&gt;The first: GPS tells you &lt;em&gt;if&lt;/em&gt; someone is home, but not &lt;em&gt;where&lt;/em&gt; in the house they are. My home has six OpenWrt access points spread across three floors. They already know exactly which phone is connected to which AP at every moment — that&amp;rsquo;s room-level presence data, sitting right there in the WiFi stack, screaming to be used. Knowing who&amp;rsquo;s in which room opens up a whole class of automations that GPS can&amp;rsquo;t touch: lights that follow you, climate control per occupied room, a dashboard that shows the household at a glance.&lt;/p&gt;&#xA;&lt;p&gt;The second: our housekeeper stays at our place a couple days a week. I don&amp;rsquo;t want to set up a full HA account for her, install the companion app on her phone, or deal with GPS permissions. But I &lt;em&gt;do&lt;/em&gt; need to know if she&amp;rsquo;s home — because my alarm automation needs to know whether the house is actually empty before arming. Her phone connects to WiFi. That&amp;rsquo;s all I need.&lt;/p&gt;&#xA;&lt;p&gt;So I wrote &lt;a href=&#34;https://github.com/vjt/openwrt-ha-presence&#34; target=&#34;_blank&#34;&gt;openwrt-ha-presence&lt;/a&gt;: a state machine that scrapes RSSI metrics directly from your OpenWrt APs, figures out which room each person is in by signal strength, and publishes per-person home/away state to Home Assistant via MQTT Discovery. No cloud, no beacons, no log parsing, no time-series database. Python, async, ~600 lines of actual logic.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://sindro.me/posts/2026-02-15-wifi-presence-detection-home-assistant/home-assistant.png&#34; alt=&#34;Home Assistant room tracking history&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-it-works&#34;&gt;How It Works&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;OpenWrt APs  →  openwrt-presence  →  MQTT  →  Home Assistant&#xA; (node-exporter-lua)  (state machine)    (discovery)   (device_tracker + sensor)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Every 5 seconds, &lt;code&gt;openwrt-presence&lt;/code&gt; hits the &lt;code&gt;/metrics&lt;/code&gt; endpoint on each AP and grabs &lt;code&gt;wifi_station_signal_dbm&lt;/code&gt; for every associated station. That&amp;rsquo;s the RSSI — how loud your phone&amp;rsquo;s signal is at that AP. The engine then processes the snapshot:&lt;/p&gt;</description>
    </item>
    <item>
      <title>5G as Fiber Backup: Never Miss a Meeting Again</title>
      <link>https://sindro.me/posts/2026-01-31-quectel-5g-modem-tools-for-openwrt/</link>
      <pubDate>Sat, 31 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2026-01-31-quectel-5g-modem-tools-for-openwrt/</guid>
      <description>&lt;p&gt;A couple of months ago, my fiber went down. As per Murphy’s first corollary, it happened at the absolute worst moment: right before a crucial meeting with a partner company. I found myself frantically jamming between a distant neighbor’s AP and my phone’s hotspot, but both sucked hard. We’re talking 200ms RTT and 15% packet loss. I was apologizing profusely while my video feed turned into a 1998 slideshow; no one could parse a word I was saying. I ended up cutting the video and staying silent. Missed opportunity. &lt;strong&gt;Never. Again.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;So I went full paranoid and built a proper 5G backup setup.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-hardware&#34;&gt;The Hardware&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.gl-inet.com/products/gl-x3000/&#34; target=&#34;_blank&#34;&gt;GL.iNet X-3000&lt;/a&gt; with a Quectel RM520N-GL modem&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://poynting.tech/antennas/xpol-24/&#34; target=&#34;_blank&#34;&gt;Poynting XPOL-24&lt;/a&gt; directional antenna mounted on the wall outside my home office&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;5G signal here is non-existing, so I had to use heavy artillery. The Poynting is a beast. 11 dBi gain, real 4x4 MIMO, cross-polarized, weather-sealed. Point it at the nearest tower and suddenly your SINR jumps from &amp;ldquo;meh&amp;rdquo; to &amp;ldquo;holy shit.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;But pointing a directional antenna without visual feedback is painful. You&amp;rsquo;re basically spinning in circles, refreshing a web UI, cursing at the sky.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-software&#34;&gt;The Software&lt;/h2&gt;&#xA;&lt;p&gt;I wrote a set of tools to solve this: &lt;a href=&#34;https://github.com/vjt/quectel-5g-tools&#34; target=&#34;_blank&#34;&gt;quectel-5g-tools&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;5g-info&lt;/code&gt; dumps everything your modem knows in a readable format:&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://sindro.me/posts/2026-01-31-quectel-5g-modem-tools-for-openwrt/5g-info.png&#34; alt=&#34;5g-info output&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;5g-monitor&lt;/code&gt; is an ncurses TUI that refreshes in real-time and—here&amp;rsquo;s the good part—&lt;strong&gt;beeps based on your SINR&lt;/strong&gt;. Higher signal quality = more beeps. Point the antenna, listen for beeps, tighten the bolts. Done.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://sindro.me/posts/2026-01-31-quectel-5g-modem-tools-for-openwrt/5g-monitor.png&#34; alt=&#34;5g-monitor TUI&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s like a metal detector, but for 5G.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Docker vs. iptables: A Tale of Rage and the DOCKER-USER Chain</title>
      <link>https://sindro.me/posts/2026-01-30-docker-vs-iptables-rage-and-docker-user-chain/</link>
      <pubDate>Fri, 30 Jan 2026 00:00:00 +0100</pubDate>
      <guid>https://sindro.me/posts/2026-01-30-docker-vs-iptables-rage-and-docker-user-chain/</guid>
      <description>&lt;p&gt;It is 2026, and we are still fighting with Docker’s absolute arrogance regarding Linux networking.&lt;/p&gt;&#xA;&lt;p&gt;Here is the scenario: I run a hybrid host. On one side, I have a KVM virtual machine running &lt;strong&gt;Home Assistant&lt;/strong&gt; (because I need full OS control and &lt;a href=&#34;https://sindro.me/posts/2026-01-20-raspberry-pi-luks-encrypted-root/&#34; target=&#34;_blank&#34;&gt;full-disk encryption&lt;/a&gt;).&#xA;On the other, I have the usual suspect list of Docker containers — &lt;strong&gt;NUT&lt;/strong&gt; for monitoring my shitty Lakeview (Vultech) UPS and &lt;strong&gt;Technitium&lt;/strong&gt; for DNS and DHCP—running on the bare metal host.&lt;/p&gt;&#xA;&lt;p&gt;It sounds simple. It should be simple.&lt;/p&gt;&#xA;&lt;p&gt;But the moment I installed Docker, communication with my Home Assistant VM died. Just ceased to exist.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-problem-docker-is-a-dictator&#34;&gt;The Problem: Docker is a Dictator&lt;/h2&gt;&#xA;&lt;p&gt;Docker, by default, treats your &lt;code&gt;iptables&lt;/code&gt; rules like they are merely suggestions. When the daemon starts, it essentially clobbers the &lt;code&gt;FORWARD&lt;/code&gt; chain, inserts its own logic, and sets policies that effectively isolate anything that isn&amp;rsquo;t a container managed by itself.&lt;/p&gt;&#xA;&lt;p&gt;If you have a bridge interface for a VM (like &lt;code&gt;br0&lt;/code&gt; or &lt;code&gt;virbr0&lt;/code&gt;), Docker’s rules often end up dropping packets destined for that VM because they don&amp;rsquo;t match its internal logic for container traffic.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-naive-fix-and-why-it-fails&#34;&gt;The Naive Fix (and why it fails)&lt;/h3&gt;&#xA;&lt;p&gt;My first reaction—like any sysadmin who has been doing this since the early 2000s—was to fix the rules manually and then run:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iptables-save &amp;gt; /etc/iptables/rules.v4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a trap!&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExOHI5MzZoYzVwdGluYmNnMXBpYmJ2M2Y4cHB1OGVhaGlxdXRpZHpqOCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/3ornka9rAaKRA2Rkac/giphy.gif&#34; alt=&#34;Trap GIF&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;If you use &lt;code&gt;iptables-persistent&lt;/code&gt; (or &lt;code&gt;netfilter-persistent&lt;/code&gt;) with Docker, you are entering a world of pain for two reasons:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Garbage Persistence&lt;/strong&gt;: When you run &lt;code&gt;iptables-save&lt;/code&gt; while Docker is running, you aren&amp;rsquo;t just saving your custom rules. You are saving Docker’s dynamic state—including rules for ephemeral &lt;code&gt;veth&lt;/code&gt; interfaces and dynamic IP masquerading. When you reboot, &lt;code&gt;iptables-restore&lt;/code&gt; tries to apply rules to interfaces that &lt;em&gt;do not exist yet&lt;/em&gt;, causing the restore to fail or leave the firewall in an inconsistent state.&lt;/p&gt;</description>
    </item>
    <item>
      <title>FreeBSD encrypted ZFS remote unlocking via SSH</title>
      <link>https://sindro.me/posts/2026-01-28-freebsd-encrypted-zfs-remote-unlock/</link>
      <pubDate>Wed, 28 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://sindro.me/posts/2026-01-28-freebsd-encrypted-zfs-remote-unlock/</guid>
      <description>&lt;h2 id=&#34;remote-luks-pfft-here-is-how-to-ssh-unlock-a-zfs-encrypted-freebsd-root-the-hard-way&#34;&gt;Remote LUKS? Pfft. Here is how to SSH-Unlock a ZFS-Encrypted FreeBSD Root (The Hard Way)&lt;/h2&gt;&#xA;&lt;p&gt;If you run FreeBSD &lt;a href=&#34;https://sindro.me/posts/2023-08-13-freebsd-encrypted-root-on-zfs/&#34; target=&#34;_blank&#34;&gt;like I do&lt;/a&gt;, on a remote server with full disk encryption (ZFS on GELI), you know the panic of rebooting. You are always at the mercy of a KVM-over-IP or a VNC connection from the browser, to insert the root filesystem password at the kernel prompt.&lt;/p&gt;&#xA;&lt;p&gt;Nevertheless, if you (like me) run a system with &lt;code&gt;kern.securelevel&lt;/code&gt; &amp;gt; 0, then installing a new libc means rebooting single user and installing the updates over said KVM or VNC connection, that is &lt;em&gt;not ergonomic&lt;/em&gt; to say the least.&lt;/p&gt;&#xA;&lt;p&gt;The standard solution is usually a pre-boot SSH environment. On Linux, dropbear-initramfs makes this trivial. On FreeBSD? You are building a custom mfsroot (memory file system) from scratch.&lt;/p&gt;&#xA;&lt;p&gt;Most guides out there suggest using a static shell script as init. This works, but it’s miserable. You lose job control (no Ctrl+C), you have no proper TTY, and good luck if you need to debug network issues interactively.&lt;/p&gt;&#xA;&lt;p&gt;I didn&amp;rsquo;t want a hacky script. I wanted a real environment. I wanted &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;getty&lt;/code&gt;, &lt;code&gt;login&lt;/code&gt;, PAM authentication, and a ZFS chroot for maintenance - to install updates.&lt;/p&gt;&#xA;&lt;p&gt;Here is how I built a robust remote unlocker for FreeBSD.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-problem-with-binsh-as-init&#34;&gt;The Problem with /bin/sh as Init&lt;/h2&gt;&#xA;&lt;p&gt;The naive approach is to compile a tiny ramdisk, shove a static sh binary in it, and tell the loader to run it as PID 1.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# This creates nightmares&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat &amp;gt; /sbin/init &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;lt;&amp;lt;EOF&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#!/bin/sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/sbin/dropbear&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;exec /bin/sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;EOF&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Why does this fail?&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
